Work on multitenancy

This commit is contained in:
jamesagnew 2020-03-31 10:33:47 -04:00
parent 2e43c57032
commit ea1f35beaa
15 changed files with 247 additions and 57 deletions

View File

@ -351,8 +351,7 @@ public class SearchBuilder implements ISearchBuilder {
* If we have any joins to index tables, we get this behaviour already guaranteed so we don't
* need an explicit predicate for it.
*/
boolean haveNoIndexSearchParams = myParams.size() == 0 || myParams.keySet().stream().allMatch(t -> t.startsWith("_"));
if (haveNoIndexSearchParams) {
if (!myQueryRoot.hasIndexJoins()) {
if (myParams.getEverythingMode() == null) {
myQueryRoot.addPredicate(myCriteriaBuilder.equal(myQueryRoot.get("myResourceType"), myResourceName));
}
@ -895,7 +894,7 @@ public class SearchBuilder implements ISearchBuilder {
myQueryRoot.addPredicate(predicate);
}
myQueryRoot.setHasIndexJoins(true);
myQueryRoot.setHasIndexJoins();
Predicate predicate = myCriteriaBuilder.equal(join.get("myIndexString"), theIndexedString);
myQueryRoot.addPredicate(predicate);

View File

@ -53,6 +53,10 @@ public class RequestPartitionHelperService {
*/
@Nullable
public PartitionId determineReadPartitionForRequest(@Nullable RequestDetails theRequest, String theResourceType) {
if (myPartitioningBlacklist.contains(theResourceType)) {
return null;
}
PartitionId partitionId = null;
if (myDaoConfig.isPartitioningEnabled()) {
@ -73,6 +77,10 @@ public class RequestPartitionHelperService {
*/
@Nullable
public PartitionId determineCreatePartitionForRequest(@Nullable RequestDetails theRequest, @Nonnull IBaseResource theResource) {
String resourceType = myFhirContext.getResourceDefinition(theResource).getName();
if (myPartitioningBlacklist.contains(resourceType)) {
return null;
}
PartitionId partitionId = null;
if (myDaoConfig.isPartitioningEnabled()) {

View File

@ -25,11 +25,9 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndex;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.SearchParamPresent;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
@ -45,6 +43,7 @@ import javax.annotation.PostConstruct;
import javax.persistence.criteria.*;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;
abstract class BasePredicateBuilder {
@ -112,30 +111,29 @@ abstract class BasePredicateBuilder {
return (Join<ResourceTable, T>) join;
}
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing) {
// if (myDontUseHashesForSearch) {
// Join<ResourceTable, SearchParamPresent> paramPresentJoin = myQueryRoot.join("mySearchParamPresents", JoinType.LEFT);
// Join<Object, Object> paramJoin = paramPresentJoin.join("mySearchParam", JoinType.LEFT);
//
// myQueryRoot.addPredicate(myBuilder.equal(paramJoin.get("myResourceName"), theResourceName));
// myQueryRoot.addPredicate(myBuilder.equal(paramJoin.get("myParamName"), theParamName));
// myQueryRoot.addPredicate(myBuilder.equal(paramPresentJoin.get("myPresent"), !theMissing));
// }
void addPredicateParamMissingForReference(String theResourceName, String theParamName, boolean theMissing, PartitionId thePartitionId) {
Join<ResourceTable, SearchParamPresent> paramPresentJoin = myQueryRoot.join("mySearchParamPresents", JoinType.LEFT);
Expression<Long> hashPresence = paramPresentJoin.get("myHashPresence").as(Long.class);
Long hash = SearchParamPresent.calculateHashPresence(theResourceName, theParamName, !theMissing);
myQueryRoot.addPredicate(myCriteriaBuilder.equal(hashPresence, hash));
List<Predicate> predicates = new ArrayList<>();
predicates.add(myCriteriaBuilder.equal(hashPresence, hash));
addPartitionIdPredicate(thePartitionId, paramPresentJoin, predicates);
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicates(predicates);
}
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing, Join<ResourceTable, ? extends BaseResourceIndexedSearchParam> theJoin, PartitionId thePartitionId) {
void addPredicateParamMissingForNonReference(String theResourceName, String theParamName, boolean theMissing, Join<ResourceTable, ? extends BaseResourceIndexedSearchParam> theJoin, PartitionId thePartitionId) {
if (thePartitionId != null) {
myQueryRoot.addPredicate(myCriteriaBuilder.equal(theJoin.get("myPartitionIdValue"), thePartitionId.getPartitionId()));
}
myQueryRoot.addPredicate(myCriteriaBuilder.equal(theJoin.get("myResourceType"), theResourceName));
myQueryRoot.addPredicate(myCriteriaBuilder.equal(theJoin.get("myParamName"), theParamName));
myQueryRoot.addPredicate(myCriteriaBuilder.equal(theJoin.get("myMissing"), theMissing));
myQueryRoot.setHasIndexJoins();
}
Predicate combineParamIndexPredicateWithParamNamePredicate(String theResourceName, String theParamName, From<?, ? extends BaseResourceIndexedSearchParam> theFrom, Predicate thePredicate) {

View File

@ -153,7 +153,7 @@ public class PredicateBuilderCoords extends BasePredicateBuilder implements IPre
Join<ResourceTable, ResourceIndexedSearchParamCoords> join = createJoin(SearchBuilderJoinEnum.COORDS, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
@ -173,6 +173,7 @@ public class PredicateBuilderCoords extends BasePredicateBuilder implements IPre
Predicate retVal = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.addPredicate(retVal);
myQueryRoot.setHasIndexJoins();
return retVal;
}
}

View File

@ -77,7 +77,7 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
if (theList.get(0).getMissing() != null) {
Boolean missing = theList.get(0).getMissing();
addPredicateParamMissing(theResourceName, theParamName, missing, join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, missing, join, thePartitionId);
return null;
}
@ -97,6 +97,7 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
Predicate orPredicates = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.setHasIndexJoins();
if (newJoin) {
Predicate identityAndValuePredicate = combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, join, orPredicates);
myQueryRoot.addPredicate(identityAndValuePredicate);

View File

@ -60,7 +60,7 @@ class PredicateBuilderNumber extends BasePredicateBuilder implements IPredicateB
Join<ResourceTable, ResourceIndexedSearchParamNumber> join = createJoin(SearchBuilderJoinEnum.NUMBER, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
@ -109,6 +109,7 @@ class PredicateBuilderNumber extends BasePredicateBuilder implements IPredicateB
}
Predicate predicate = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicate(predicate);
return predicate;
}

View File

@ -58,7 +58,7 @@ class PredicateBuilderQuantity extends BasePredicateBuilder implements IPredicat
Join<ResourceTable, ResourceIndexedSearchParamQuantity> join = createJoin(SearchBuilderJoinEnum.QUANTITY, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
@ -77,6 +77,7 @@ class PredicateBuilderQuantity extends BasePredicateBuilder implements IPredicat
}
Predicate retVal = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicate(retVal);
return retVal;
}

View File

@ -137,7 +137,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
}
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing());
addPredicateParamMissingForReference(theResourceName, theParamName, theList.get(0).getMissing(), thePartitionId);
return null;
}
@ -227,6 +227,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
codePredicates.add(myCriteriaBuilder.and(pathPredicate, pidPredicate));
}
myQueryRoot.setHasIndexJoins();
if (codePredicates.size() > 0) {
Predicate predicate = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.addPredicate(predicate);

View File

@ -63,7 +63,7 @@ class PredicateBuilderString extends BasePredicateBuilder implements IPredicateB
Join<ResourceTable, ResourceIndexedSearchParamString> join = createJoin(SearchBuilderJoinEnum.STRING, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
@ -82,7 +82,10 @@ class PredicateBuilderString extends BasePredicateBuilder implements IPredicateB
}
Predicate retVal = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicate(retVal);
return retVal;
}

View File

@ -134,7 +134,6 @@ class PredicateBuilderTag extends BasePredicateBuilder {
continue;
}
// FIXME: add test for tag:not
// FIXME: add test for :missing
if (paramInverted) {
ourLog.debug("Searching for _tag:not");
@ -173,6 +172,7 @@ class PredicateBuilderTag extends BasePredicateBuilder {
addPartitionIdPredicate(thePartitionId, tagJoin, predicates);
}
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicates(predicates);
}

View File

@ -76,7 +76,7 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
if (theList.get(0).getMissing() != null) {
Join<ResourceTable, ResourceIndexedSearchParamToken> join = createJoin(SearchBuilderJoinEnum.TOKEN, theParamName);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
@ -108,7 +108,10 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
codePredicates.addAll(singleCode);
Predicate spPredicate = myCriteriaBuilder.or(toArray(codePredicates));
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicate(spPredicate);
return spPredicate;
}

View File

@ -62,7 +62,7 @@ class PredicateBuilderUri extends BasePredicateBuilder implements IPredicateBuil
Join<ResourceTable, ResourceIndexedSearchParamUri> join = createJoin(SearchBuilderJoinEnum.URI, theParamName);
if (theList.get(0).getMissing() != null) {
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
addPredicateParamMissingForNonReference(theResourceName, theParamName, theList.get(0).getMissing(), join, thePartitionId);
return null;
}
@ -169,6 +169,7 @@ class PredicateBuilderUri extends BasePredicateBuilder implements IPredicateBuil
*/
if (codePredicates.isEmpty()) {
Predicate predicate = myCriteriaBuilder.isNull(join.get("myMissing").as(String.class));
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicate(predicate);
return null;
}
@ -179,6 +180,7 @@ class PredicateBuilderUri extends BasePredicateBuilder implements IPredicateBuil
theParamName,
join,
orPredicate);
myQueryRoot.setHasIndexJoins();
myQueryRoot.addPredicate(outerPredicate);
return outerPredicate;
}

View File

@ -96,7 +96,7 @@ public class QueryRoot {
return myHasIndexJoins;
}
public void setHasIndexJoins(boolean theHasIndexJoins) {
public void setHasIndexJoins() {
myHasIndexJoins = true;
}
}

View File

@ -12,11 +12,11 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hamcrest.Matchers;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@ -79,11 +79,14 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
myPartitionId = 3;
myPartitionInterceptor = new MyInterceptor();
myInterceptorRegistry.registerInterceptor(myPartitionInterceptor);
}
@Test
public void testCreateResourceNoPartition() {
addCreatePartition(null, null);
Patient p = new Patient();
p.addIdentifier().setSystem("system").setValue("value");
p.setBirthDate(new Date());
@ -343,6 +346,142 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
}
@Test
public void testSearch_MissingParamString_SearchAllPartitions() {
IIdType patientIdNull = createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
IIdType patientId2 = createPatient(2, withFamily("FAMILY"));
// :missing=true
{
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_ACTIVE, new StringParam().setMissing(true));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientIdNull, patientId1, patientId2));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(0, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "SP_MISSING='true'"));
}
// :missing=false
{
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_FAMILY, new StringParam().setMissing(false));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientIdNull, patientId1, patientId2));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(0, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "SP_MISSING='false'"));
}
}
@Test
public void testSearch_MissingParamReference_SearchAllPartitions() {
IIdType patientIdNull = createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
IIdType patientId2 = createPatient(2, withFamily("FAMILY"));
// :missing=true
{
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_GENERAL_PRACTITIONER, new StringParam().setMissing(true));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientIdNull, patientId1, patientId2));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(0, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "HFJ_RES_PARAM_PRESENT"));
assertEquals(1, StringUtils.countMatches(searchSql, "HASH_PRESENCE='1919227773735728687'"));
}
}
@Test
public void testSearch_MissingParamString_SearchOnePartition() {
createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
createPatient(2, withFamily("FAMILY"));
// :missing=true
{
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_ACTIVE, new StringParam().setMissing(true));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientId1));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(1, StringUtils.countMatches(searchSql, "myparamsto1_.PARTITION_ID='1'"));
assertEquals(1, StringUtils.countMatches(searchSql, "SP_MISSING='true'"));
}
// :missing=false
{
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_FAMILY, new StringParam().setMissing(false));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientId1));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(1, StringUtils.countMatches(searchSql, "myparamsst1_.PARTITION_ID='1'"));
assertEquals(1, StringUtils.countMatches(searchSql, "SP_MISSING='false'"));
}
}
@Test
public void testSearch_MissingParamReference_SearchOnePartition() {
createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
createPatient(2, withFamily("FAMILY"));
// :missing=true
{
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_GENERAL_PRACTITIONER, new StringParam().setMissing(true));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientId1));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(1, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "mysearchpa1_.PARTITION_ID='1'"));
assertEquals(1, StringUtils.countMatches(searchSql, "HFJ_RES_PARAM_PRESENT"));
assertEquals(1, StringUtils.countMatches(searchSql, "HASH_PRESENCE='1919227773735728687'"));
}
}
@Test
public void testSearch_NoParams_SearchAllPartitions() {
IIdType patientIdNull = createPatient(null, withActiveTrue());
@ -452,9 +591,9 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
@Test
public void testSearch_TagParam_SearchOnePartition() {
IIdType patientIdNull = createPatient(null, withActiveTrue(), withTag("http://system", "code"));
createPatient(null, withActiveTrue(), withTag("http://system", "code"));
IIdType patientId1 = createPatient(1, withActiveTrue(), withTag("http://system", "code"));
IIdType patientId2 = createPatient(2, withActiveTrue(), withTag("http://system", "code"));
createPatient(2, withActiveTrue(), withTag("http://system", "code"));
addReadPartition(1);
@ -472,6 +611,56 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
assertEquals(1, StringUtils.countMatches(searchSql, "TAG_SYSTEM='http://system'"));
}
@Test
public void testSearch_TagParamNot_SearchAllPartitions() {
IIdType patientIdNull = createPatient(null, withActiveTrue(), withTag("http://system", "code"));
IIdType patientId1 = createPatient(1, withActiveTrue(), withTag("http://system", "code"));
IIdType patientId2 = createPatient(2, withActiveTrue(), withTag("http://system", "code"));
createPatient(null, withActiveTrue(), withTag("http://system", "code"), withTag("http://system", "code2"));
createPatient(1, withActiveTrue(), withTag("http://system", "code"), withTag("http://system", "code2"));
createPatient(2, withActiveTrue(), withTag("http://system", "code"), withTag("http://system", "code2"));
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Constants.PARAM_TAG, new TokenParam("http://system", "code2").setModifier(TokenParamModifier.NOT));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientIdNull, patientId1, patientId2));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(0, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "TAG_SYSTEM='http://system'"));
}
@Test
public void testSearch_TagParamNot_SearchOnePartition() {
createPatient(null, withActiveTrue(), withTag("http://system", "code"));
IIdType patientId1 = createPatient(1, withActiveTrue(), withTag("http://system", "code"));
createPatient(2, withActiveTrue(), withTag("http://system", "code"));
createPatient(null, withActiveTrue(), withTag("http://system", "code"), withTag("http://system", "code2"));
createPatient(1, withActiveTrue(), withTag("http://system", "code"), withTag("http://system", "code2"));
createPatient(2, withActiveTrue(), withTag("http://system", "code"), withTag("http://system", "code2"));
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Constants.PARAM_TAG, new TokenParam("http://system", "code2").setModifier(TokenParamModifier.NOT));
map.setLoadSynchronous(true);
IBundleProvider results = myPatientDao.search(map);
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
assertThat(ids, Matchers.contains(patientId1));
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
ourLog.info("Search SQL:\n{}", searchSql);
assertEquals(1, StringUtils.countMatches(searchSql, "PARTITION_ID"));
assertEquals(1, StringUtils.countMatches(searchSql, "TAG_SYSTEM='http://system'"));
}
@Test
public void testSearch_UniqueParam_SearchAllPartitions() {
createUniqueCompositeSp();
@ -557,13 +746,15 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
private void addCreatePartition(int thePartitionId, LocalDate thePartitionDate) {
registerInterceptorIfNeeded();
myPartitionInterceptor.addCreatePartition(new PartitionId(thePartitionId, thePartitionDate));
private void addCreatePartition(Integer thePartitionId, LocalDate thePartitionDate) {
PartitionId partitionId = null;
if (thePartitionId != null) {
partitionId = new PartitionId(thePartitionId, thePartitionDate);
}
myPartitionInterceptor.addCreatePartition(partitionId);
}
private void addReadPartition(Integer thePartitionId) {
registerInterceptorIfNeeded();
PartitionId partitionId = null;
if (thePartitionId != null) {
partitionId = new PartitionId(thePartitionId, null);
@ -571,16 +762,8 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
myPartitionInterceptor.addReadPartition(partitionId);
}
private void registerInterceptorIfNeeded() {
if (!myInterceptorRegistry.getAllRegisteredInterceptors().contains(myPartitionInterceptor)) {
myInterceptorRegistry.registerInterceptor(myPartitionInterceptor);
}
}
public IIdType createPatient(Integer thePartitionId, Consumer<Patient>... theModifiers) {
if (thePartitionId != null) {
addCreatePartition(thePartitionId, null);
}
addCreatePartition(thePartitionId, null);
Patient p = new Patient();
for (Consumer<Patient> next : theModifiers) {
@ -614,7 +797,7 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
private Consumer<Patient> withTag(String theSystem, String theCode) {
return t->t.getMeta().addTag(theSystem, theCode, theCode);
return t -> t.getMeta().addTag(theSystem, theCode, theCode);
}
@ -626,7 +809,6 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
private final List<PartitionId> myReadPartitionIds = new ArrayList<>();
public void addCreatePartition(PartitionId thePartitionId) {
Validate.notNull(thePartitionId);
myCreatePartitionIds.add(thePartitionId);
}

View File

@ -32,7 +32,7 @@ import java.io.Serializable;
@Index(name = "IDX_RESPARMPRESENT_RESID", columnList = "RES_ID"),
@Index(name = "IDX_RESPARMPRESENT_HASHPRES", columnList = "HASH_PRESENCE")
})
public class SearchParamPresent implements Serializable {
public class SearchParamPresent extends BasePartitionable implements Serializable {
private static final long serialVersionUID = 1L;
@ -52,8 +52,6 @@ public class SearchParamPresent implements Serializable {
private transient String myParamName;
@Column(name = "HASH_PRESENCE")
private Long myHashPresence;
@Embedded
private PartitionId myPartitionId;
/**
* Constructor
@ -112,18 +110,10 @@ public class SearchParamPresent implements Serializable {
b.append("resPid", myResource.getIdDt().toUnqualifiedVersionless().getValue());
b.append("paramName", myParamName);
b.append("present", myPresent);
b.append("tenant", myPartitionId);
b.append("partition", getPartitionId());
return b.build();
}
public PartitionId getPartitionId() {
return myPartitionId;
}
public void setPartitionId(PartitionId thePartitionId) {
myPartitionId = thePartitionId;
}
public static long calculateHashPresence(String theResourceType, String theParamName, Boolean thePresent) {
String string = thePresent != null ? Boolean.toString(thePresent) : Boolean.toString(false);
return BaseResourceIndexedSearchParam.hash(theResourceType, theParamName, string);