diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index 1cb82679ef9..211b4eefebe 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -69,6 +69,7 @@ import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; +import javax.annotation.Nonnull; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.*; @@ -1835,19 +1836,15 @@ public class SearchBuilder implements ISearchBuilder { nextRoundMatches = pidsToInclude; } while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound); - ourLog.info("Loaded {} {} in {} rounds and {} ms", new Object[] {allAdded.size(), theReverseMode ? "_revincludes" : "_includes", roundCounts, w.getMillisAndRestart()}); + ourLog.info("Loaded {} {} in {} rounds and {} ms", allAdded.size(), theReverseMode ? "_revincludes" : "_includes", roundCounts, w.getMillisAndRestart()); return allAdded; } - private void searchForIdsWithAndOr(SearchParameterMap theParams) { - SearchParameterMap params = theParams; - if (params == null) { - params = new SearchParameterMap(); - } + private void searchForIdsWithAndOr(@Nonnull SearchParameterMap theParams) { myParams = theParams; - for (Entry>> nextParamEntry : params.entrySet()) { + for (Entry>> nextParamEntry : myParams.entrySet()) { String nextParamName = nextParamEntry.getKey(); List> andOrParams = nextParamEntry.getValue(); searchForIdsWithAndOr(myResourceName, nextParamName, andOrParams); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java index 82729e0d4ae..ceb77c900bb 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java @@ -198,6 +198,71 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { } + /** + * See #1053 + * + * Note that I don't know that _lastUpdate actually should apply to reverse includes. The + * spec doesn't say one way or ther other, but it seems like sensible behaviour to me. + * + * Definitely the $everything operation depends on this behaviour, so if we change it + * we need to account for the everything operation... + */ + @Test + public void testLastUpdateShouldApplyToReverseIncludes() { + SearchParameterMap map; + List ids; + + // This gets updated in a sec.. + Organization org = new Organization(); + org.setActive(false); + org.setId("O1"); + myOrganizationDao.update(org); + + Date beforeAll = new Date(); + ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100); + + Patient p = new Patient(); + p.setId("P1"); + p.setActive(true); + p.setManagingOrganization(new Reference("Organization/O1")); + myPatientDao.update(p); + + ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100); + + Date beforeOrg = new Date(); + ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100); + + org = new Organization(); + org.setActive(true); + org.setId("O1"); + myOrganizationDao.update(org); + + ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100); + Date afterAll = new Date(); + + // Everything should come back + map = new SearchParameterMap(); + map.setLastUpdated(new DateRangeParam().setLowerBoundInclusive(beforeAll)); + map.addRevInclude(Patient.INCLUDE_ORGANIZATION); + ids = toUnqualifiedVersionlessIdValues(myOrganizationDao.search(map)); + assertThat(ids, contains("Organization/O1", "Patient/P1")); + + // Search before everything + map = new SearchParameterMap(); + map.setLastUpdated(new DateRangeParam().setLowerBoundInclusive(beforeOrg)); + map.addInclude(Patient.INCLUDE_ORGANIZATION); + ids = toUnqualifiedVersionlessIdValues(myOrganizationDao.search(map)); + assertThat(ids, contains("Organization/O1")); + + // Search after everything + map = new SearchParameterMap(); + map.setLastUpdated(new DateRangeParam().setLowerBoundInclusive(afterAll)); + map.addInclude(Patient.INCLUDE_ORGANIZATION); + ids = toUnqualifiedVersionlessIdValues(myOrganizationDao.search(map)); + assertThat(ids, empty()); + + } + @Test public void testEverythingTimings() { String methodName = "testEverythingTimings";