3322 graph ql searches cannot be executed when number of matching results exceeds default page size (#3323)

* fix NPE

* check if size is null
This commit is contained in:
katiesmilecdr 2022-01-24 11:53:21 -05:00 committed by GitHub
parent 37e7d6eea5
commit a11d72ba51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 4 deletions

View File

@ -0,0 +1,5 @@
---
type: fix
issue: 3322
jira: SMILE-3424
title: "GraphQL searches cannot be executed when number of matching results exceeds default page size. This has been corrected."

View File

@ -562,7 +562,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
bundleProvider.setSize(null); bundleProvider.setSize(null);
} }
} }
bundleProvider.setPreferredPageSize(theParams.getCount());
return bundleProvider; return bundleProvider;
}); });
} }

View File

@ -1,10 +1,11 @@
package ca.uhn.fhir.jpa.graphql; package ca.uhn.fhir.jpa.graphql;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.config.TestR4Config; import ca.uhn.fhir.jpa.config.TestR4Config;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test; import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Appointment; import org.hl7.fhir.r4.model.Appointment;
import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.CodeableConcept;
@ -25,18 +26,23 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import static ca.uhn.fhir.rest.api.Constants.PARAM_COUNT;
import static org.mockito.Mockito.when;
@ContextConfiguration(classes = {TestR4Config.class}) @ContextConfiguration(classes = {TestR4Config.class})
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@DirtiesContext @DirtiesContext
public class DaoRegistryGraphQLStorageServicesTest extends BaseJpaR4Test { public class DaoRegistryGraphQLStorageServicesTest extends BaseJpaR4Test {
private static final FhirContext ourCtx = FhirContext.forR4Cached();
@Autowired @Autowired
private IGraphQLStorageServices mySvc; private IGraphQLStorageServices mySvc;
@ -134,4 +140,41 @@ public class DaoRegistryGraphQLStorageServicesTest extends BaseJpaR4Test {
List<String> expectedId = Arrays.asList("hapi-123", "hapi-124"); List<String> expectedId = Arrays.asList("hapi-123", "hapi-124");
assertTrue(result.stream().allMatch((it) -> expectedId.contains(it.getIdElement().getIdPart()))); assertTrue(result.stream().allMatch((it) -> expectedId.contains(it.getIdElement().getIdPart())));
} }
@Test
public void testListResourceGraphqlWithPageSizeSmallerThanResultSize() {
for (int i = 0; i < 10; i++) {
createSomePatientWithId("hapi-" + i);
}
Argument argument = new Argument();
argument.setName("_id");
for (int i = 0; i < 10; i++) {
argument.addValue(new StringValue("hapi-" + i));
}
//fisrt page
List<IBaseResource> result = new ArrayList<>();
when(mySrd.getServer().getDefaultPageSize()).thenReturn(5);
mySvc.listResources(mySrd, "Patient", Collections.singletonList(argument), result);
assertFalse(result.isEmpty());
assertEquals(5, result.size());
List<String> expectedId = Arrays.asList("hapi-1", "hapi-2", "hapi-0", "hapi-3", "hapi-4");
assertTrue(result.stream().allMatch((it) -> expectedId.contains(it.getIdElement().getIdPart())));
//_offset=5
List<IBaseResource> result2 = new ArrayList<>();
Map<String, String[]> parametersMap = new HashMap<>();
parametersMap.put("_offset", new String[]{"5"});
when(mySrd.getParameters()).thenReturn(parametersMap);
mySvc.listResources(mySrd, "Patient", Collections.singletonList(argument), result2);
assertFalse(result2.isEmpty());
assertEquals(5, result2.size());
List<String> expectedId2 = Arrays.asList("hapi-5", "hapi-6", "hapi-7", "hapi-8", "hapi-9");
assertTrue(result2.stream().allMatch((it) -> expectedId2.contains(it.getIdElement().getIdPart())));
}
} }

View File

@ -46,6 +46,7 @@ import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException; import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseReference; import org.hl7.fhir.instance.model.api.IBaseReference;
@ -189,11 +190,15 @@ public class DaoRegistryGraphQLStorageServices implements IGraphQLStorageService
RequestDetails requestDetails = (RequestDetails) theAppInfo; RequestDetails requestDetails = (RequestDetails) theAppInfo;
IBundleProvider response = dao.search(params, requestDetails); IBundleProvider response = dao.search(params, requestDetails);
int size = response.sizeOrThrowNpe(); Integer size = response.size();
if (response.preferredPageSize() != null && response.preferredPageSize() < size) { //We set size to null in SearchCoordinatorSvcImpl.executeQuery() if matching results exceeds count
//so don't throw here
if ((response.preferredPageSize() != null && size != null && response.preferredPageSize() < size) ||
size == null) {
size = response.preferredPageSize(); size = response.preferredPageSize();
} }
Validate.notNull(size, "size is null");
theMatches.addAll(response.getResources(0, size)); theMatches.addAll(response.getResources(0, size));
} }