diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/3937-searching-with-target-resource-parameter-in-include-fails.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/3937-searching-with-target-resource-parameter-in-include-fails.yaml new file mode 100644 index 00000000000..12ab6207ab1 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/3937-searching-with-target-resource-parameter-in-include-fails.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 3937 +jira: SMILE-4959 +title: "Fixing bug where searching with a target resource parameter (Coverage:payor:Patient) as value to an _include parameter would fail with a 500 response." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java index a1d9e16488f..44999127247 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java @@ -1171,17 +1171,24 @@ public class SearchBuilder implements ISearchBuilder { } } //@formatter:off - String resourceUrlBasedQuery = "SELECT " + fieldsToLoadFromSpidxUriTable + + StringBuilder resourceUrlBasedQuery = new StringBuilder("SELECT " + fieldsToLoadFromSpidxUriTable + " FROM hfj_res_link r " + " JOIN hfj_spidx_uri rUri ON ( " + " r.target_resource_url = rUri.sp_uri AND " + - " rUri.sp_name = 'url' " + - (targetResourceType != null ? " AND rUri.res_type = :target_resource_type " : "") + - (haveTargetTypesDefinedByParam ? " AND rUri.res_type IN (:target_resource_types) " : "") + - " ) " + + " rUri.sp_name = 'url' "); + + if(targetResourceType != null) { + resourceUrlBasedQuery.append(" AND rUri.res_type = :target_resource_type "); + + } else if(haveTargetTypesDefinedByParam) { + resourceUrlBasedQuery.append(" AND rUri.res_type IN (:target_resource_types) "); + } + + resourceUrlBasedQuery.append(" ) "); + resourceUrlBasedQuery.append( " WHERE r.src_path = :src_path AND " + - " r.target_resource_id IS NULL AND " + - " r." + searchPidFieldSqlColumn + " IN (:target_pids) "; + " r.target_resource_id IS NULL AND " + + " r." + searchPidFieldSqlColumn + " IN (:target_pids) "); //@formatter:on String sql = resourceIdBasedQuery + " UNION " + resourceUrlBasedQuery; @@ -1196,6 +1203,7 @@ public class SearchBuilder implements ISearchBuilder { } else if (haveTargetTypesDefinedByParam) { q.setParameter("target_resource_types", param.getTargets()); } + List results = q.getResultList(); if (theMaxCount != null) { q.setMaxResults(theMaxCount); diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index a85a24a73ec..16ba5ef1596 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -85,6 +85,7 @@ import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Condition; +import org.hl7.fhir.r4.model.Coverage; import org.hl7.fhir.r4.model.DateTimeType; import org.hl7.fhir.r4.model.DateType; import org.hl7.fhir.r4.model.DecimalType; @@ -1819,6 +1820,27 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { } } + @Test + public void testSearchWithIncludeAndTargetResourceParameterWillSucceed() { + + Coverage coverage = new Coverage(); + coverage.getMeta().addProfile("http://foo"); + coverage.setId(IdType.newRandomUuid()); + coverage.addIdentifier().setSystem("http://coverage").setValue("12345"); + coverage.setStatus(Coverage.CoverageStatus.ACTIVE); + coverage.setType(new CodeableConcept().addCoding(new Coding("http://coverage-type", "12345", null))); + + MethodOutcome methodOutcome = myClient.create().resource(coverage).execute(); + + Bundle returnedBundle = myClient.search().byUrl("Coverage?_include=Coverage:payor:Patient&_include=Coverage:payor:Organization").returnBundle(Bundle.class).execute(); + + IIdType createdCoverageId = methodOutcome.getId(); + String entryId = returnedBundle.getEntry().get(0).getResource().getId(); + + assertEquals(createdCoverageId.getValue(), entryId); + + } + @Test public void testEmptySearch() { Bundle responseBundle;