Work on multitenancy
This commit is contained in:
parent
8e714b6b14
commit
2e43c57032
hapi-fhir-jpaserver-base/src
main/java/ca/uhn/fhir/jpa/dao/predicate
BasePredicateBuilder.javaPredicateBuilder.javaPredicateBuilderReference.javaPredicateBuilderTag.java
test/java/ca/uhn/fhir/jpa/dao/r4
hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue