fixing test

This commit is contained in:
leif stawnyczy 2023-08-15 10:41:53 -04:00
parent e07ffddd6e
commit 478d7a1257
3 changed files with 166 additions and 157 deletions

View File

@ -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());

View File

@ -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();
}
}

View File

@ -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());
} }