diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4613-chained-special-params.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4613-chained-special-params.yaml new file mode 100644 index 00000000000..c48224468fc --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4613-chained-special-params.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 4613 +jira: SMILE-6091 +title: "Previously, SPECIAL search parameters that were _not_ nearness parameters, such as simple string Search Parameters, could not be used in chained queries. This has been resolved, and now queries like `OrganizationAffiliation?location.some-special-param=abc` will work as intended." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java index 73f9c46af6b..fe497c7dfbe 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java @@ -664,11 +664,8 @@ public class ResourceLinkPredicateBuilder qp = new ReferenceParam(); break; case SPECIAL: - if ("Location.position".equals(theParam.getPath())) { qp = new SpecialParam(); break; - } - throw new InternalErrorException(Msg.code(1248) + "Don't know how to convert param type: " + theParam.getParamType()); case URI: qp = new UriParam(); break; diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchDistanceTest.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchDistanceTest.java index 4da9846868d..b7e520ee335 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchDistanceTest.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchDistanceTest.java @@ -67,6 +67,10 @@ public class FhirResourceDaoDstu3SearchDistanceTest extends BaseJpaDstu3Test { assertThat(ids, contains(locId)); } + + @Test + public void testNearSearchChained() { + } @Test public void testNearSearchApproximate() { Location loc = new Location(); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchDistanceTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchDistanceTest.java index e3386ad110f..746c107ce90 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchDistanceTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchDistanceTest.java @@ -4,7 +4,13 @@ import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; import ca.uhn.fhir.jpa.util.CoordCalculatorTestUtil; +import ca.uhn.fhir.rest.api.server.SystemRequestDetails; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.OrganizationAffiliation; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.SearchParameter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -42,6 +48,65 @@ public class FhirResourceDaoR4SearchDistanceTest extends BaseJpaR4Test { assertThat(ids, contains(locId)); } + @Test + public void testNearSearchDistanceChained() { + Location location = new Location(); + double latitude = CoordCalculatorTestUtil.LATITUDE_CHIN; + double longitude = CoordCalculatorTestUtil.LATITUDE_CHIN; + Location.LocationPositionComponent position = new Location.LocationPositionComponent().setLatitude(latitude).setLongitude(longitude); + location.setPosition(position); + + IIdType id = myLocationDao.create(location).getId(); + + OrganizationAffiliation aff = new OrganizationAffiliation(); + aff.addLocation(new Reference(id)); + IIdType affId = myOrganizationAffiliationDao.create(aff).getId(); + SearchParameterMap map = myMatchUrlService.translateMatchUrl("OrganizationAffiliation?location." + Location.SP_NEAR + "=" + latitude + "|" + longitude, myFhirContext.getResourceDefinition("OrganizationAffiliation")); + + List ids = toUnqualifiedVersionlessIdValues(myOrganizationAffiliationDao.search(map)); + assertThat(ids, contains(affId.toUnqualifiedVersionless().toString())); + } + + @Test + public void testNearSearchDistanceOnSpecialParameterChained() { + //Given a special SP exists + SearchParameter parameter = new SearchParameter(); + parameter.setId("location-postalcode-near"); + parameter.setName("arbitrary-name"); + parameter.setStatus(Enumerations.PublicationStatus.ACTIVE); + parameter.setCode("postalcode-near"); + parameter.addBase("Location"); + parameter.setType(Enumerations.SearchParamType.SPECIAL); + parameter.setExpression("Location.address.postalCode"); + mySearchParameterDao.update(parameter, new SystemRequestDetails()); + + //And given an OrganizationAffiliation->Location reference + Location location = new Location(); + location.getAddress().setPostalCode("60108"); + IIdType locId = myLocationDao.create(location).getId(); + + OrganizationAffiliation aff = new OrganizationAffiliation(); + aff.addLocation(new Reference(locId)); + IIdType affId = myOrganizationAffiliationDao.create(aff).getId(); + + { + //When: We search on the location + SearchParameterMap map = myMatchUrlService.translateMatchUrl("Location?postalcode-near=60108", myFhirContext.getResourceDefinition("Location")); + List ids = toUnqualifiedVersionlessIdValues(myLocationDao.search(map)); + //Then: it should find the location + assertThat(ids, contains(locId.toUnqualifiedVersionless().toString())); + } + + { + //When: We search on the OrganizationAffiliation via its location in a chain + SearchParameterMap map = myMatchUrlService.translateMatchUrl("OrganizationAffiliation?location.postalcode-near=60108", myFhirContext.getResourceDefinition("OrganizationAffiliation")); + List ids = toUnqualifiedVersionlessIdValues(myOrganizationAffiliationDao.search(map)); + + //Then: It should find the OrganizationAffiliation + assertThat(ids, contains(affId.toUnqualifiedVersionless().toString())); + } + } + @Test public void testNearSearchDistanceZero() { Location loc = new Location();