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 0b1a2bf6046..86ec9de59ce 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 @@ -1268,6 +1268,8 @@ public class SearchBuilder implements ISearchBuilder { } + private List myAlsoIncludePids; + private TypedQuery createQuery(SortSpec sort) { CriteriaQuery outerQuery; /* @@ -1329,6 +1331,10 @@ public class SearchBuilder implements ISearchBuilder { if (myParams.get(BaseResource.SP_RES_ID) != null) { StringParam idParm = (StringParam) myParams.get(BaseResource.SP_RES_ID).get(0).get(0); Long pid = BaseHapiFhirDao.translateForcedIdToPid(myResourceName, idParm.getValue(), myForcedIdDao); + if (myAlsoIncludePids == null) { + myAlsoIncludePids = new ArrayList(1); + } + myAlsoIncludePids.add(pid); myPredicates.add(myBuilder.equal(join.get("myTargetResourcePid").as(Long.class), pid)); } else { Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName); @@ -1931,6 +1937,7 @@ public class SearchBuilder implements ISearchBuilder { private final Set myPidSet = new HashSet(); private Iterator myResultsIterator; private SortSpec mySort; + private Iterator myPreResultsIterator; private QueryIterator() { mySort = myParams.getSort(); @@ -1938,19 +1945,39 @@ public class SearchBuilder implements ISearchBuilder { private void fetchNext() { - // If we don't have + // If we don't have a query yet, create one if (myResultsIterator == null) { final TypedQuery query = createQuery(mySort); myResultsIterator = query.getResultList().iterator(); + + // If the query resulted in extra results being requested + if (myAlsoIncludePids != null) { + myPreResultsIterator = myAlsoIncludePids.iterator(); + } } + if (myNext == null) { - while (myResultsIterator.hasNext()) { - Long next = myResultsIterator.next(); - if (next != null && myPidSet.add(next)) { - myNext = next; - break; + + if (myPreResultsIterator != null && myPreResultsIterator.hasNext()) { + while (myPreResultsIterator.hasNext()) { + Long next = myPreResultsIterator.next(); + if (next != null && myPidSet.add(next)) { + myNext = next; + break; + } + } + } + + if (myNext == null) { + while (myResultsIterator.hasNext()) { + Long next = myResultsIterator.next(); + if (next != null && myPidSet.add(next)) { + myNext = next; + break; + } } } + if (myNext == null) { myNext = NO_MORE; } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index 77021e524e3..a2fe944e208 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -205,6 +205,26 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { } + + @Test + public void testEverythingWithOnlyPatient() { + Patient p = new Patient(); + p.setActive(true); + IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless(); + + myFhirCtx.getRestfulClientFactory().setSocketTimeout(300 * 1000); + + Bundle response = ourClient + .operation() + .onInstance(id) + .named("everything") + .withNoParameters(Parameters.class) + .returnResourceType(Bundle.class) + .execute(); + + assertEquals(1, response.getEntry().size()); + } + @Test diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchDstu3Test.java index 9e0e6257589..3eafeb5eecf 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/SearchDstu3Test.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.rest.server; -import static org.junit.Assert.assertEquals; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.*; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -26,9 +27,15 @@ import org.junit.BeforeClass; import org.junit.Test; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.rest.annotation.RequiredParam; import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.client.IGenericClient; +import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; +import ca.uhn.fhir.rest.gclient.StringClientParam; +import ca.uhn.fhir.rest.method.SearchStyleEnum; import ca.uhn.fhir.rest.param.TokenAndListParam; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.PortUtil; import ca.uhn.fhir.util.TestUtil; @@ -87,6 +94,34 @@ public class SearchDstu3Test { } + @Test + public void testSearchWithPostAndInvalidParameters() throws Exception { + IGenericClient client = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort); + LoggingInterceptor interceptor = new LoggingInterceptor(); + interceptor.setLogRequestSummary(true); + interceptor.setLogRequestBody(true); + interceptor.setLogRequestHeaders(false); + interceptor.setLogResponseBody(false); + interceptor.setLogResponseHeaders(false); + interceptor.setLogResponseSummary(false); + client.registerInterceptor(interceptor); + try { + client + .search() + .forResource(Patient.class) + .where(new StringClientParam("foo").matches().value("bar")) + .encodedJson() + .prettyPrint() + .usingStyle(SearchStyleEnum.POST) + .returnBundle(org.hl7.fhir.dstu3.model.Bundle.class) + .execute(); + fail(); + } catch (InvalidRequestException e) { + assertThat(e.getMessage(), containsString("Invalid request: The FHIR endpoint on this server does not know how to handle POST operation[Patient/_search] with parameters [[_pretty, foo]]")); + } + + } + @AfterClass public static void afterClassClearContext() throws Exception { ourServer.stop(); @@ -135,7 +170,6 @@ public class SearchDstu3Test { return retVal; } - } }