Work on multitenancy

This commit is contained in:
jamesagnew 2020-03-30 09:49:17 -04:00
parent 8e714b6b14
commit 2e43c57032
8 changed files with 183 additions and 115 deletions

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
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;
@ -205,7 +206,7 @@ abstract class BasePredicateBuilder {
return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, num);
}
void addPartitionIdPredicate(PartitionId thePartitionId, Join<ResourceTable, ? extends BaseResourceIndex> theJoin, List<Predicate> theCodePredicates) {
void addPartitionIdPredicate(PartitionId thePartitionId, Join<ResourceTable, ? extends BasePartitionable> theJoin, List<Predicate> theCodePredicates) {
if (thePartitionId != null) {
Integer partitionId = thePartitionId.getPartitionId();
Predicate partitionPredicate = myCriteriaBuilder.equal(theJoin.get("myPartitionIdValue").as(Integer.class), partitionId);

View File

@ -79,8 +79,8 @@ public class PredicateBuilder {
return myPredicateBuilderString.addPredicate(theResourceName, theParamName, theNextAnd, theOperation, thePartitionId);
}
void addPredicateTag(List<List<IQueryParameterType>> theAndOrParams, String theParamName) {
myPredicateBuilderTag.addPredicateTag(theAndOrParams, theParamName);
void addPredicateTag(List<List<IQueryParameterType>> theAndOrParams, String theParamName, PartitionId thePartitionId) {
myPredicateBuilderTag.addPredicateTag(theAndOrParams, theParamName, thePartitionId);
}
Predicate addPredicateToken(String theResourceName, String theParamName, List<? extends IQueryParameterType> theNextAnd, SearchFilterParser.CompareOperation theOperation, PartitionId thePartitionId) {

View File

@ -525,7 +525,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
case Constants.PARAM_TAG:
case Constants.PARAM_PROFILE:
case Constants.PARAM_SECURITY:
myPredicateBuilder.addPredicateTag(theAndOrParams, theParamName);
myPredicateBuilder.addPredicateTag(theAndOrParams, theParamName, thePartitionId);
break;
case Constants.PARAM_SOURCE:

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao.predicate;
*/
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.PartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
@ -38,12 +39,18 @@ import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.persistence.criteria.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
// FIXME: add partition
@Component
@Scope("prototype")
class PredicateBuilderTag extends BasePredicateBuilder {
@ -53,7 +60,7 @@ class PredicateBuilderTag extends BasePredicateBuilder {
super(theSearchBuilder);
}
void addPredicateTag(List<List<IQueryParameterType>> theList, String theParamName) {
void addPredicateTag(List<List<IQueryParameterType>> theList, String theParamName, PartitionId thePartitionId) {
TagTypeEnum tagType;
if (Constants.PARAM_TAG.equals(theParamName)) {
tagType = TagTypeEnum.TAG;
@ -127,6 +134,8 @@ class PredicateBuilderTag extends BasePredicateBuilder {
continue;
}
// FIXME: add test for tag:not
// FIXME: add test for :missing
if (paramInverted) {
ourLog.debug("Searching for _tag:not");
@ -158,7 +167,13 @@ class PredicateBuilderTag extends BasePredicateBuilder {
From<ResourceTag, TagDefinition> defJoin = tagJoin.join("myTag");
Predicate tagListPredicate = createPredicateTagList(defJoin, myCriteriaBuilder, tagType, tokens);
myQueryRoot.addPredicate(tagListPredicate);
List<Predicate> predicates = Lists.newArrayList(tagListPredicate);
if (thePartitionId != null) {
addPartitionIdPredicate(thePartitionId, tagJoin, predicates);
}
myQueryRoot.addPredicates(predicates);
}

View File

@ -7,9 +7,11 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.Constants;
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.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil;
@ -50,13 +52,13 @@ import static org.mockito.Mockito.when;
public class PartitioningR4Test extends BaseJpaR4SystemTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PartitioningR4Test.class);
private MyInterceptor myTenantInterceptor;
private LocalDate myTenantDate;
private MyInterceptor myPartitionInterceptor;
private LocalDate myPartitionDate;
private int myPartitionId;
@After
public void after() {
myTenantInterceptor.assertNoRemainingIds();
myPartitionInterceptor.assertNoRemainingIds();
myDaoConfig.setPartitioningEnabled(new DaoConfig().isPartitioningEnabled());
@ -73,15 +75,15 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
myDaoConfig.setUniqueIndexesEnabled(true);
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
myTenantDate = LocalDate.of(2020, Month.JANUARY, 14);
myPartitionDate = LocalDate.of(2020, Month.JANUARY, 14);
myPartitionId = 3;
myTenantInterceptor = new MyInterceptor();
myPartitionInterceptor = new MyInterceptor();
}
@Test
public void testCreateResourceNoTenant() {
public void testCreateResourceNoPartition() {
Patient p = new Patient();
p.addIdentifier().setSystem("system").setValue("value");
p.setBirthDate(new Date());
@ -95,12 +97,12 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
@Test
public void testCreateResourceWithTenant() {
public void testCreateResourceWithPartition() {
createUniqueCompositeSp();
createRequestId();
addCreateTenant(myPartitionId, myTenantDate);
addCreateTenant(myPartitionId, myTenantDate);
addCreatePartition(myPartitionId, myPartitionDate);
addCreatePartition(myPartitionId, myPartitionDate);
Organization org = new Organization();
org.setName("org");
@ -118,71 +120,71 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
// HFJ_RESOURCE
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
assertEquals(myPartitionId, resourceTable.getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, resourceTable.getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, resourceTable.getPartitionId().getPartitionDate());
// HFJ_RES_TAG
List<ResourceTag> tags = myResourceTagDao.findAll();
assertEquals(1, tags.size());
assertEquals(myPartitionId, tags.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, tags.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, tags.get(0).getPartitionId().getPartitionDate());
// HFJ_RES_VER
ResourceHistoryTable version = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, 1L);
assertEquals(myPartitionId, version.getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, version.getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, version.getPartitionId().getPartitionDate());
// HFJ_HISTORY_TAG
List<ResourceHistoryTag> historyTags = myResourceHistoryTagDao.findAll();
assertEquals(1, historyTags.size());
assertEquals(myPartitionId, historyTags.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, historyTags.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, historyTags.get(0).getPartitionId().getPartitionDate());
// HFJ_RES_VER_PROV
assertNotNull(version.getProvenance());
assertEquals(myPartitionId, version.getProvenance().getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, version.getProvenance().getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, version.getProvenance().getPartitionId().getPartitionDate());
// HFJ_SPIDX_STRING
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAllForResourceId(patientId);
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
assertEquals(10, strings.size());
assertEquals(myPartitionId, strings.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, strings.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, strings.get(0).getPartitionId().getPartitionDate());
// HFJ_SPIDX_DATE
List<ResourceIndexedSearchParamDate> dates = myResourceIndexedSearchParamDateDao.findAllForResourceId(patientId);
ourLog.info("\n * {}", dates.stream().map(ResourceIndexedSearchParamDate::toString).collect(Collectors.joining("\n * ")));
assertEquals(2, dates.size());
assertEquals(myPartitionId, dates.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, dates.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, dates.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionId, dates.get(1).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, dates.get(1).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, dates.get(1).getPartitionId().getPartitionDate());
// HFJ_RES_LINK
List<ResourceLink> resourceLinks = myResourceLinkDao.findAllForResourceId(patientId);
assertEquals(1, resourceLinks.size());
assertEquals(myPartitionId, resourceLinks.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, resourceLinks.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, resourceLinks.get(0).getPartitionId().getPartitionDate());
// HFJ_RES_PARAM_PRESENT
List<SearchParamPresent> presents = mySearchParamPresentDao.findAllForResource(resourceTable);
assertEquals(myPartitionId, presents.size());
assertEquals(myPartitionId, presents.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, presents.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, presents.get(0).getPartitionId().getPartitionDate());
// HFJ_IDX_CMP_STRING_UNIQ
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceId(patientId);
assertEquals(1, uniques.size());
assertEquals(myPartitionId, uniques.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, uniques.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, uniques.get(0).getPartitionId().getPartitionDate());
});
}
@Test
public void testCreateWithForcedId() {
addCreateTenant(myPartitionId, myTenantDate);
addCreateTenant(myPartitionId, myTenantDate);
addCreatePartition(myPartitionId, myPartitionDate);
addCreatePartition(myPartitionId, myPartitionDate);
Organization org = new Organization();
org.setId("org");
@ -199,18 +201,18 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
List<ForcedId> forcedIds = myForcedIdDao.findAll();
assertEquals(2, forcedIds.size());
assertEquals(myPartitionId, forcedIds.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, forcedIds.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, forcedIds.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionId, forcedIds.get(1).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, forcedIds.get(1).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, forcedIds.get(1).getPartitionId().getPartitionDate());
});
}
@Test
public void testUpdateResourceWithTenant() {
public void testUpdateResourceWithPartition() {
createRequestId();
addCreateTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
addCreateTenant(3, LocalDate.of(2020, Month.JANUARY, 14));
addCreatePartition(3, LocalDate.of(2020, Month.JANUARY, 14));
addCreatePartition(3, LocalDate.of(2020, Month.JANUARY, 14));
// Create a resource
Patient p = new Patient();
@ -221,7 +223,7 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
// HFJ_RESOURCE
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
assertEquals(myPartitionId, resourceTable.getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, resourceTable.getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, resourceTable.getPartitionId().getPartitionDate());
});
// Update that resource
@ -234,66 +236,66 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
// HFJ_RESOURCE
ResourceTable resourceTable = myResourceTableDao.findById(patientId).orElseThrow(IllegalArgumentException::new);
assertEquals(myPartitionId, resourceTable.getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, resourceTable.getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, resourceTable.getPartitionId().getPartitionDate());
// HFJ_RES_VER
int version = 2;
ResourceHistoryTable resVer = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(patientId, version);
assertEquals(myPartitionId, resVer.getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, resVer.getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, resVer.getPartitionId().getPartitionDate());
// HFJ_HISTORY_TAG
List<ResourceHistoryTag> historyTags = myResourceHistoryTagDao.findAll();
assertEquals(2, historyTags.size());
assertEquals(myPartitionId, historyTags.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, historyTags.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, historyTags.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionId, historyTags.get(1).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, historyTags.get(1).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, historyTags.get(1).getPartitionId().getPartitionDate());
// HFJ_RES_VER_PROV
assertNotNull(resVer.getProvenance());
assertNotNull(resVer.getPartitionId());
assertEquals(myPartitionId, resVer.getProvenance().getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, resVer.getProvenance().getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, resVer.getProvenance().getPartitionId().getPartitionDate());
// HFJ_SPIDX_STRING
List<ResourceIndexedSearchParamString> strings = myResourceIndexedSearchParamStringDao.findAllForResourceId(patientId);
ourLog.info("\n * {}", strings.stream().map(ResourceIndexedSearchParamString::toString).collect(Collectors.joining("\n * ")));
assertEquals(10, strings.size());
assertEquals(myPartitionId, strings.get(0).getPartitionId().getPartitionId().intValue());
assertEquals(myTenantDate, strings.get(0).getPartitionId().getPartitionDate());
assertEquals(myPartitionDate, strings.get(0).getPartitionId().getPartitionDate());
});
}
@Test
public void testReadAcrossTenants() {
public void testReadAcrossPartitions() {
IIdType patientId1 = createPatient(1, withActiveTrue());
IIdType patientId2 = createPatient(2, withActiveTrue());
addReadTenant(null);
addReadPartition(null);
IdType gotId1 = myPatientDao.read(patientId1, mySrd).getIdElement().toUnqualifiedVersionless();
assertEquals(patientId1, gotId1);
addReadTenant(null);
addReadPartition(null);
IdType gotId2 = myPatientDao.read(patientId2, mySrd).getIdElement().toUnqualifiedVersionless();
assertEquals(patientId2, gotId2);
}
@Test
public void testReadSpecificTenant_PidId() {
public void testReadSpecificPartition_PidId() {
IIdType patientIdNull = createPatient(null, withActiveTrue());
IIdType patientId1 = createPatient(1, withActiveTrue());
IIdType patientId2 = createPatient(2, withActiveTrue());
// Read in correct tenant
addReadTenant(1);
// Read in correct Partition
addReadPartition(1);
IdType gotId1 = myPatientDao.read(patientId1, mySrd).getIdElement().toUnqualifiedVersionless();
assertEquals(patientId1, gotId1);
// Read in null tenant
addReadTenant(1);
// Read in null Partition
addReadPartition(1);
try {
myPatientDao.read(patientIdNull, mySrd).getIdElement().toUnqualifiedVersionless();
fail();
@ -301,8 +303,8 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
assertThat(e.getMessage(), matchesPattern("Resource Patient/[0-9]+ is not known"));
}
// Read in wrong tenant
addReadTenant(1);
// Read in wrong Partition
addReadPartition(1);
try {
myPatientDao.read(patientId2, mySrd).getIdElement().toUnqualifiedVersionless();
fail();
@ -312,18 +314,18 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testReadSpecificTenant_ForcedId() {
public void testReadSpecificPartition_ForcedId() {
IIdType patientIdNull = createPatient(null, withActiveTrue(), withId("NULL"));
IIdType patientId1 = createPatient(1, withActiveTrue(), withId("ONE"));
IIdType patientId2 = createPatient(2, withActiveTrue(), withId("TWO"));
// Read in correct tenant
addReadTenant(1);
// Read in correct Partition
addReadPartition(1);
IdType gotId1 = myPatientDao.read(patientId1, mySrd).getIdElement().toUnqualifiedVersionless();
assertEquals(patientId1, gotId1);
// Read in null tenant
addReadTenant(1);
// Read in null Partition
addReadPartition(1);
try {
myPatientDao.read(patientIdNull, mySrd).getIdElement().toUnqualifiedVersionless();
fail();
@ -331,8 +333,8 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
assertThat(e.getMessage(), matchesPattern("Resource Patient/[0-9]+ is not known"));
}
// Read in wrong tenant
addReadTenant(1);
// Read in wrong Partition
addReadPartition(1);
try {
myPatientDao.read(patientId2, mySrd).getIdElement().toUnqualifiedVersionless();
fail();
@ -342,12 +344,12 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testSearch_NoParams_SearchAllTenants() {
public void testSearch_NoParams_SearchAllPartitions() {
IIdType patientIdNull = createPatient(null, withActiveTrue());
IIdType patientId1 = createPatient(1, withActiveTrue());
IIdType patientId2 = createPatient(2, withActiveTrue());
addReadTenant(null);
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
@ -362,12 +364,12 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testSearch_NoParams_SearchOneTenant() {
public void testSearch_NoParams_SearchOnePartition() {
createPatient(null, withActiveTrue());
IIdType patientId1 = createPatient(1, withActiveTrue());
createPatient(2, withActiveTrue());
addReadTenant(1);
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
@ -382,12 +384,12 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testSearch_StringParam_SearchAllTenants() {
public void testSearch_StringParam_SearchAllPartitions() {
IIdType patientIdNull = createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
IIdType patientId2 = createPatient(2, withFamily("FAMILY"));
addReadTenant(null);
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
@ -404,12 +406,12 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testSearch_StringParam_SearchOneTenant() {
public void testSearch_StringParam_SearchOnePartition() {
createPatient(null, withFamily("FAMILY"));
IIdType patientId1 = createPatient(1, withFamily("FAMILY"));
createPatient(2, withFamily("FAMILY"));
addReadTenant(1);
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
@ -427,11 +429,57 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testSearch_UniqueParam_SearchAllTenants() {
public void testSearch_TagParam_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"));
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Constants.PARAM_TAG, new TokenParam("http://system", "code"));
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_TagParam_SearchOnePartition() {
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"));
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Constants.PARAM_TAG, new TokenParam("http://system", "code"));
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();
IIdType id = createPatient(1, withBirthdate("2020-01-01"));
addReadPartition(null);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
@ -449,12 +497,12 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
@Test
public void testSearch_UniqueParam_SearchOneTenant() {
public void testSearch_UniqueParam_SearchOnePartition() {
createUniqueCompositeSp();
IIdType id = createPatient(1, withBirthdate("2020-01-01"));
addReadTenant(1);
addReadPartition(1);
myCaptureQueriesListener.clear();
SearchParameterMap map = new SearchParameterMap();
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
@ -470,7 +518,7 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
assertEquals(1, StringUtils.countMatches(searchSql, "IDX_STRING='Patient?birthdate=2020-01-01'"));
// Same query, different partition
addReadTenant(2);
addReadPartition(2);
myCaptureQueriesListener.clear();
map = new SearchParameterMap();
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
@ -509,29 +557,29 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
private void addCreateTenant(int thePartitionId, LocalDate theTenantDate) {
private void addCreatePartition(int thePartitionId, LocalDate thePartitionDate) {
registerInterceptorIfNeeded();
myTenantInterceptor.addCreateTenant(new PartitionId(thePartitionId, theTenantDate));
myPartitionInterceptor.addCreatePartition(new PartitionId(thePartitionId, thePartitionDate));
}
private void addReadTenant(Integer thePartitionId) {
private void addReadPartition(Integer thePartitionId) {
registerInterceptorIfNeeded();
PartitionId partitionId = null;
if (thePartitionId != null) {
partitionId = new PartitionId(thePartitionId, null);
}
myTenantInterceptor.addReadTenant(partitionId);
myPartitionInterceptor.addReadPartition(partitionId);
}
private void registerInterceptorIfNeeded() {
if (!myInterceptorRegistry.getAllRegisteredInterceptors().contains(myTenantInterceptor)) {
myInterceptorRegistry.registerInterceptor(myTenantInterceptor);
if (!myInterceptorRegistry.getAllRegisteredInterceptors().contains(myPartitionInterceptor)) {
myInterceptorRegistry.registerInterceptor(myPartitionInterceptor);
}
}
public IIdType createPatient(Integer thePartitionId, Consumer<Patient>... theModifiers) {
if (thePartitionId != null) {
addCreateTenant(thePartitionId, null);
addCreatePartition(thePartitionId, null);
}
Patient p = new Patient();
@ -565,6 +613,11 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
};
}
private Consumer<Patient> withTag(String theSystem, String theCode) {
return t->t.getMeta().addTag(theSystem, theCode, theCode);
}
@Interceptor
public static class MyInterceptor {
@ -572,17 +625,17 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
private final List<PartitionId> myCreatePartitionIds = new ArrayList<>();
private final List<PartitionId> myReadPartitionIds = new ArrayList<>();
public void addCreateTenant(PartitionId thePartitionId) {
public void addCreatePartition(PartitionId thePartitionId) {
Validate.notNull(thePartitionId);
myCreatePartitionIds.add(thePartitionId);
}
public void addReadTenant(PartitionId thePartitionId) {
public void addReadPartition(PartitionId thePartitionId) {
myReadPartitionIds.add(thePartitionId);
}
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_CREATE)
public PartitionId tenantIdentifyCreate(IBaseResource theResource, ServletRequestDetails theRequestDetails) {
public PartitionId PartitionIdentifyCreate(IBaseResource theResource, ServletRequestDetails theRequestDetails) {
assertNotNull(theResource);
PartitionId retVal = myCreatePartitionIds.remove(0);
ourLog.info("Returning partition for create: {}", retVal);
@ -590,7 +643,7 @@ public class PartitioningR4Test extends BaseJpaR4SystemTest {
}
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_READ)
public PartitionId tenantIdentifyRead(ServletRequestDetails theRequestDetails) {
public PartitionId PartitionIdentifyRead(ServletRequestDetails theRequestDetails) {
PartitionId retVal = myReadPartitionIds.remove(0);
ourLog.info("Returning partition for read: {}", retVal);
return retVal;

View File

@ -0,0 +1,30 @@
package ca.uhn.fhir.jpa.model.entity;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
@MappedSuperclass
public class BasePartitionable implements Serializable {
@Embedded
private PartitionId myPartitionId;
/**
* This is here to support queries only, do not set this field directly
*/
@SuppressWarnings("unused")
@Column(name = PartitionId.PARTITION_ID, insertable = false, updatable = false, nullable = true)
private Integer myPartitionIdValue;
public PartitionId getPartitionId() {
return myPartitionId;
}
public void setPartitionId(PartitionId thePartitionId) {
myPartitionId = thePartitionId;
}
}

View File

@ -20,31 +20,11 @@ package ca.uhn.fhir.jpa.model.entity;
* #L%
*/
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseResourceIndex implements Serializable {
@Embedded
private PartitionId myPartitionId;
/**
* This is here to support queries only, do not set this field directly
*/
@SuppressWarnings("unused")
@Column(name = PartitionId.PARTITION_ID, insertable = false, updatable = false, nullable = true)
private Integer myPartitionIdValue;
public PartitionId getPartitionId() {
return myPartitionId;
}
public void setPartitionId(PartitionId thePartitionId) {
myPartitionId = thePartitionId;
}
public abstract class BaseResourceIndex extends BasePartitionable implements Serializable {
public abstract Long getId();

View File

@ -28,7 +28,7 @@ import javax.persistence.MappedSuperclass;
import java.io.Serializable;
@MappedSuperclass
public class BaseTag implements Serializable {
public class BaseTag extends BasePartitionable implements Serializable {
private static final long serialVersionUID = 1L;
@ -39,9 +39,6 @@ public class BaseTag implements Serializable {
@Column(name = "TAG_ID", insertable = false, updatable = false)
private Long myTagId;
@Embedded
private PartitionId myPartitionId;
public Long getTagId() {
return myTagId;
}
@ -54,12 +51,4 @@ public class BaseTag implements Serializable {
myTag = theTag;
}
public PartitionId getPartitionId() {
return myPartitionId;
}
public void setPartitionId(PartitionId thePartitionId) {
myPartitionId = thePartitionId;
}
}