fixing test
This commit is contained in:
parent
e07ffddd6e
commit
478d7a1257
|
@ -55,6 +55,7 @@ import ca.uhn.fhir.jpa.model.search.SearchBuilderLoadIncludesParameters;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||||
import ca.uhn.fhir.jpa.search.SearchConstants;
|
import ca.uhn.fhir.jpa.search.SearchConstants;
|
||||||
|
import ca.uhn.fhir.jpa.search.builder.models.ListWrappingSearchQueryExecutor;
|
||||||
import ca.uhn.fhir.jpa.search.builder.sql.GeneratedSql;
|
import ca.uhn.fhir.jpa.search.builder.sql.GeneratedSql;
|
||||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryExecutor;
|
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryExecutor;
|
||||||
|
@ -459,10 +460,15 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
} else {
|
} else {
|
||||||
// do everything in the database.
|
// do everything in the database.
|
||||||
createChunkedQuery(
|
createChunkedQuery(
|
||||||
theParams, sort, theOffset, theMaximumResults, theCountOnlyFlag, theRequest, null,
|
theParams,
|
||||||
|
sort,
|
||||||
|
theOffset,
|
||||||
|
theMaximumResults,
|
||||||
|
theCountOnlyFlag,
|
||||||
|
theRequest,
|
||||||
|
null,
|
||||||
queries
|
queries
|
||||||
);
|
);
|
||||||
// query.ifPresent(queries::add);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return queries;
|
return queries;
|
||||||
|
@ -552,10 +558,16 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
if (thePids.size() < getMaximumPageSize()) {
|
if (thePids.size() < getMaximumPageSize()) {
|
||||||
normalizeIdListForLastNInClause(thePids);
|
normalizeIdListForLastNInClause(thePids);
|
||||||
}
|
}
|
||||||
// Optional<SearchQueryExecutor> query =
|
createChunkedQuery(
|
||||||
createChunkedQuery(theParams, sort, theOffset, thePids.size(), theCount, theRequest, thePids,
|
theParams,
|
||||||
theQueries);
|
sort,
|
||||||
// query.ifPresent(t -> theQueries.add(t));
|
theOffset,
|
||||||
|
thePids.size(),
|
||||||
|
theCount,
|
||||||
|
theRequest,
|
||||||
|
thePids,
|
||||||
|
theQueries
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -563,7 +575,7 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
*
|
*
|
||||||
* @param theTargetPids
|
* @param theTargetPids
|
||||||
*/
|
*/
|
||||||
private void extractTargetPidsFromIdParams(HashSet<Long> theTargetPids) {
|
private void extractTargetPidsFromIdParams(HashSet<Long> theTargetPids, List<ISearchQueryExecutor> theSearchQueryExecutors) {
|
||||||
// get all the IQueryParameterType objects
|
// get all the IQueryParameterType objects
|
||||||
// for _id -> these should all be StringParam values
|
// for _id -> these should all be StringParam values
|
||||||
HashSet<String> ids = new HashSet<>();
|
HashSet<String> ids = new HashSet<>();
|
||||||
|
@ -587,15 +599,17 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
// this will throw if an id is not found
|
// this will throw if an id is not found
|
||||||
Map<String, JpaPid> idToPid = myIdHelperService.resolveResourcePersistentIds(
|
Map<String, JpaPid> idToPid = myIdHelperService.resolveResourcePersistentIds(
|
||||||
myRequestPartitionId, myResourceName, new ArrayList<>(ids));
|
myRequestPartitionId, myResourceName, new ArrayList<>(ids));
|
||||||
if (myAlsoIncludePids == null) {
|
|
||||||
myAlsoIncludePids = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the pids to targetPids
|
// add the pids to targetPids
|
||||||
for (JpaPid pid : idToPid.values()) {
|
for (JpaPid pid : idToPid.values()) {
|
||||||
myAlsoIncludePids.add(pid);
|
|
||||||
theTargetPids.add(pid.getId());
|
theTargetPids.add(pid.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add the target pids to our executors as the first
|
||||||
|
// results iterator to go through
|
||||||
|
theSearchQueryExecutors.add(new ListWrappingSearchQueryExecutor(
|
||||||
|
new ArrayList<>(theTargetPids)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createChunkedQuery(
|
private void createChunkedQuery(
|
||||||
|
@ -641,7 +655,7 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
if (myParams.getEverythingMode() != null) {
|
if (myParams.getEverythingMode() != null) {
|
||||||
HashSet<Long> targetPids = new HashSet<>();
|
HashSet<Long> targetPids = new HashSet<>();
|
||||||
if (myParams.get(IAnyResource.SP_RES_ID) != null) {
|
if (myParams.get(IAnyResource.SP_RES_ID) != null) {
|
||||||
extractTargetPidsFromIdParams(targetPids);
|
extractTargetPidsFromIdParams(targetPids, theSearchQueryExecutors);
|
||||||
} else {
|
} else {
|
||||||
// For Everything queries, we make the query root by the ResourceLink table, since this query
|
// For Everything queries, we make the query root by the ResourceLink table, since this query
|
||||||
// is basically a reverse-include search. For type/Everything (as opposed to instance/Everything)
|
// is basically a reverse-include search. For type/Everything (as opposed to instance/Everything)
|
||||||
|
@ -661,33 +675,10 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
Object[] args = allTargetsSql.getBindVariables().toArray(new Object[0]);
|
Object[] args = allTargetsSql.getBindVariables().toArray(new Object[0]);
|
||||||
|
|
||||||
List<Long> output = jdbcTemplate.query(sql, args, new SingleColumnRowMapper<>(Long.class));
|
List<Long> output = jdbcTemplate.query(sql, args, new SingleColumnRowMapper<>(Long.class));
|
||||||
// if (myAlsoIncludePids == null) {
|
|
||||||
// myAlsoIncludePids = new ArrayList<>(output.size());
|
|
||||||
// }
|
|
||||||
// myAlsoIncludePids.addAll(JpaPid.fromLongList(output));
|
|
||||||
|
|
||||||
theSearchQueryExecutors.add(new ISearchQueryExecutor() {
|
// we add the search to the list of search executors as the first
|
||||||
private final Iterator<Long> myIterator = output.iterator();
|
// search executor/resultsiterator
|
||||||
|
theSearchQueryExecutors.add(new ListWrappingSearchQueryExecutor(output));
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return myIterator.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long next() {
|
|
||||||
return myIterator.next();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// theSearchQueryExecutors.add(
|
|
||||||
// mySqlBuilderFactory.newSearchQueryExecutor(allTargetsSql, myMaxResultsToFetch)
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> typeSourceResources = new ArrayList<>();
|
List<String> typeSourceResources = new ArrayList<>();
|
||||||
|
@ -785,14 +776,10 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
* Now perform the search
|
* Now perform the search
|
||||||
*/
|
*/
|
||||||
GeneratedSql generatedSql = sqlBuilder.generate(theOffset, myMaxResultsToFetch);
|
GeneratedSql generatedSql = sqlBuilder.generate(theOffset, myMaxResultsToFetch);
|
||||||
if (generatedSql.isMatchNothing()) {
|
if (!generatedSql.isMatchNothing()) {
|
||||||
// return Optional.empty();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchQueryExecutor executor = mySqlBuilderFactory.newSearchQueryExecutor(generatedSql, myMaxResultsToFetch);
|
SearchQueryExecutor executor = mySqlBuilderFactory.newSearchQueryExecutor(generatedSql, myMaxResultsToFetch);
|
||||||
theSearchQueryExecutors.add(executor);
|
theSearchQueryExecutors.add(executor);
|
||||||
// return Optional.of(executor);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<String> extractTypeSourceResourcesFromParams() {
|
private Collection<String> extractTypeSourceResourcesFromParams() {
|
||||||
|
@ -2025,29 +2012,17 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* assigns the results iterator.
|
* assigns the results iterator
|
||||||
* Can also assign and populate myAlsoIncludePids.
|
* and populates the myQueryList.
|
||||||
* Specifically in type/$everything mode
|
|
||||||
* (ie, /Patient/$everything)
|
|
||||||
*/
|
*/
|
||||||
initializeIteratorQuery(myOffset, myMaxResultsToFetch);
|
initializeIteratorQuery(myOffset, myMaxResultsToFetch);
|
||||||
|
|
||||||
// but if it doesn't, we'll set an empty list here
|
// if it's null, we'll set an empty list here
|
||||||
if (myAlsoIncludePids == null) {
|
if (myAlsoIncludePids == null) {
|
||||||
myAlsoIncludePids = new ArrayList<>();
|
myAlsoIncludePids = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myNext == null) {
|
|
||||||
// we first consume any alsoIncludePids
|
|
||||||
for (JpaPid next : myAlsoIncludePids) {
|
|
||||||
if (next != null)
|
|
||||||
if (myPidSet.add(next)) {
|
|
||||||
myNext = next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myNext == null) {
|
if (myNext == null) {
|
||||||
// no next means we need a new query (if one is available)
|
// no next means we need a new query (if one is available)
|
||||||
while (myResultsIterator.hasNext() || !myQueryList.isEmpty()) {
|
while (myResultsIterator.hasNext() || !myQueryList.isEmpty()) {
|
||||||
|
@ -2138,7 +2113,7 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
myNext = NO_MORE;
|
myNext = NO_MORE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // if we need to fetch the next result
|
|
||||||
|
|
||||||
mySearchRuntimeDetails.setFoundMatchesCount(myPidSet.size());
|
mySearchRuntimeDetails.setFoundMatchesCount(myPidSet.size());
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ca.uhn.fhir.jpa.search.builder.models;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.search.builder.ISearchQueryExecutor;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of ISearchQueryExecutor that wraps a simple list.
|
||||||
|
*/
|
||||||
|
public class ListWrappingSearchQueryExecutor implements ISearchQueryExecutor {
|
||||||
|
|
||||||
|
private final Iterator<Long> myIterator;
|
||||||
|
|
||||||
|
public ListWrappingSearchQueryExecutor(List<Long> theList) {
|
||||||
|
myIterator = theList.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return myIterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long next() {
|
||||||
|
return myIterator.next();
|
||||||
|
}
|
||||||
|
}
|
|
@ -101,8 +101,10 @@ public class PatientEverythingPaginationR4Test extends BaseResourceProviderR4Tes
|
||||||
@ValueSource(booleans = { true, false })
|
@ValueSource(booleans = { true, false })
|
||||||
public void testEverythingPagination_LastPage(boolean theProvideCountBool) throws IOException {
|
public void testEverythingPagination_LastPage(boolean theProvideCountBool) throws IOException {
|
||||||
// setup
|
// setup
|
||||||
myStorageSettings.setSearchPreFetchThresholds(Arrays.asList(10, 50,-1));
|
List<Integer> prefetchThreshold = Arrays.asList(10, 50,-1);
|
||||||
// 3 pages
|
myStorageSettings.setSearchPreFetchThresholds(prefetchThreshold);
|
||||||
|
|
||||||
|
// 3 pages @ 50
|
||||||
int total = 154;
|
int total = 154;
|
||||||
createPatients(total);
|
createPatients(total);
|
||||||
Set<String> ids = new HashSet<>();
|
Set<String> ids = new HashSet<>();
|
||||||
|
@ -119,7 +121,11 @@ public class PatientEverythingPaginationR4Test extends BaseResourceProviderR4Tes
|
||||||
|
|
||||||
// first page
|
// first page
|
||||||
List<Patient> patientsPage = BundleUtil.toListOfResourcesOfType(myFhirContext, bundle, Patient.class);
|
List<Patient> patientsPage = BundleUtil.toListOfResourcesOfType(myFhirContext, bundle, Patient.class);
|
||||||
// assertEquals(50, patientsPage.size());
|
if (theProvideCountBool) {
|
||||||
|
assertEquals(50, patientsPage.size());
|
||||||
|
} else {
|
||||||
|
assertEquals(10, patientsPage.size());
|
||||||
|
}
|
||||||
for (Patient p : patientsPage) {
|
for (Patient p : patientsPage) {
|
||||||
assertTrue(ids.add(p.getId()));
|
assertTrue(ids.add(p.getId()));
|
||||||
}
|
}
|
||||||
|
@ -134,24 +140,19 @@ public class PatientEverythingPaginationR4Test extends BaseResourceProviderR4Tes
|
||||||
for (Patient p : patientsPage) {
|
for (Patient p : patientsPage) {
|
||||||
assertTrue(ids.add(p.getId()));
|
assertTrue(ids.add(p.getId()));
|
||||||
}
|
}
|
||||||
// assertEquals(50, patientsPage.size());
|
|
||||||
nextUrl = BundleUtil.getLinkUrlOfType(myFhirContext, bundle, LINK_NEXT);
|
nextUrl = BundleUtil.getLinkUrlOfType(myFhirContext, bundle, LINK_NEXT);
|
||||||
|
if (nextUrl != null) {
|
||||||
|
if (theProvideCountBool) {
|
||||||
|
assertEquals(50, patientsPage.size());
|
||||||
|
} else {
|
||||||
|
assertEquals(10, patientsPage.size());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assertEquals(4, patientsPage.size());
|
||||||
|
}
|
||||||
} while (nextUrl != null);
|
} while (nextUrl != null);
|
||||||
assertNull(nextUrl);
|
assertNull(nextUrl);
|
||||||
|
|
||||||
// last page
|
|
||||||
// nextUrl = BundleUtil.getLinkUrlOfType(myFhirContext, bundle, LINK_NEXT);
|
|
||||||
// assertNotNull(nextUrl);
|
|
||||||
// bundle = fetchBundle(nextUrl);
|
|
||||||
// nextUrl = BundleUtil.getLinkUrlOfType(myFhirContext, bundle, LINK_NEXT);
|
|
||||||
// assertNull(nextUrl);
|
|
||||||
// patientsPage = BundleUtil.toListOfResourcesOfType(myFhirContext, bundle, Patient.class);
|
|
||||||
//
|
|
||||||
// assertEquals(4, patientsPage.size());
|
|
||||||
// for (Patient p : patientsPage) {
|
|
||||||
// assertTrue(ids.add(p.getId()));
|
|
||||||
// }
|
|
||||||
|
|
||||||
assertEquals(total, ids.size());
|
assertEquals(total, ids.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue