Get large searches working on Oracle

This commit is contained in:
James Agnew 2017-05-05 15:45:45 +02:00
parent 3780248a2f
commit e53d747f2b
3 changed files with 31 additions and 46 deletions

View File

@ -22,33 +22,18 @@ package ca.uhn.fhir.rest.server;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.Closeable; import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.*;
import java.lang.reflect.Method; import java.util.*;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.Manifest; import java.util.jar.Manifest;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.UnavailableException; import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -56,35 +41,17 @@ import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ProvidedResourceScanner;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.Destroy; import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Initialize;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RequestTypeEnum; import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.method.BaseMethodBinding; import ca.uhn.fhir.rest.method.*;
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
import ca.uhn.fhir.rest.method.ParseAction;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding; import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.interceptor.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.*;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlPathTokenizer;
import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.util.VersionUtil;
public class RestfulServer extends HttpServlet implements IRestfulServer<ServletRequestDetails> { public class RestfulServer extends HttpServlet implements IRestfulServer<ServletRequestDetails> {
@ -415,7 +382,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
} }
/** /**
* Returns a ist of all registered server interceptors * Returns a list of all registered server interceptors
*/ */
@Override @Override
public List<IServerInterceptor> getInterceptors() { public List<IServerInterceptor> getInterceptors() {

View File

@ -232,7 +232,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>

View File

@ -1487,10 +1487,29 @@ public class SearchBuilder implements ISearchBuilder {
theResourceListToPopulate.add(null); theResourceListToPopulate.add(null);
} }
/*
* As always, Oracle can't handle things that other databases don't mind.. In this
* case it doesn't like more than ~1000 IDs in a single load, so we break this up
* if it's lots of IDs. I suppose maybe we should be doing this as a join anyhow
* but this should work too. Sigh.
*/
int maxLoad = 800;
List<Long> pids = new ArrayList<Long>(theIncludePids);
for (int i = 0; i < pids.size(); i += maxLoad) {
int to = i + maxLoad;
to = Math.min(to, pids.size());
List<Long> pidsSubList = pids.subList(i, to);
doLoadPids(theResourceListToPopulate, theRevIncludedPids, theForHistoryOperation, entityManager, context, theDao, position, pidsSubList);
}
}
private void doLoadPids(List<IBaseResource> theResourceListToPopulate, Set<Long> theRevIncludedPids, boolean theForHistoryOperation, EntityManager entityManager, FhirContext context, IDao theDao,
Map<Long, Integer> position, Collection<Long> pids) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<ResourceTable> cq = builder.createQuery(ResourceTable.class); CriteriaQuery<ResourceTable> cq = builder.createQuery(ResourceTable.class);
Root<ResourceTable> from = cq.from(ResourceTable.class); Root<ResourceTable> from = cq.from(ResourceTable.class);
cq.where(from.get("myId").in(theIncludePids)); cq.where(from.get("myId").in(pids));
TypedQuery<ResourceTable> q = entityManager.createQuery(cq); TypedQuery<ResourceTable> q = entityManager.createQuery(cq);
for (ResourceTable next : q.getResultList()) { for (ResourceTable next : q.getResultList()) {