From 9d82d989e711da89c7529869455efeb806c1a228 Mon Sep 17 00:00:00 2001 From: Gustavo Fernandes Date: Tue, 5 Dec 2017 13:12:00 +0000 Subject: [PATCH] ISPN-6395 Deprecate SearchManager.getClusteredQuery --- .../query/dsl/IndexedQueryMode.java | 20 ++ .../org/infinispan/query/QueryDefinition.java | 112 ++++++++++ .../org/infinispan/query/SearchManager.java | 36 +++- .../clustered/ClusteredCacheQueryImpl.java | 33 +-- .../clustered/ClusteredQueryCommand.java | 30 +-- .../clustered/ClusteredQueryCommandType.java | 11 +- .../query/clustered/DistributedIterator.java | 12 +- .../query/clustered/NodeTopDocs.java | 5 +- .../QueryDefinitionExternalizer.java | 51 +++++ .../commandworkers/CQCreateEagerQuery.java | 33 +-- .../commandworkers/CQCreateLazyQuery.java | 2 + .../commandworkers/CQGetResultSize.java | 10 +- .../ClusteredQueryCommandWorker.java | 11 +- .../commandworkers/QueryExtractorUtil.java | 12 +- .../dsl/embedded/impl/HsQueryRequest.java | 34 +++ .../query/dsl/embedded/impl/QueryEngine.java | 86 ++++++++ .../infinispan/query/impl/CacheQueryImpl.java | 48 +++-- .../query/impl/LifecycleManager.java | 2 + .../query/impl/SearchManagerImpl.java | 42 +++- .../ClusteredTopDocsExternalizer.java | 16 +- .../impl/externalizers/ExternalizerIds.java | 2 + .../org/infinispan/query/logging/Log.java | 10 + .../ClusteredQueryMultipleCachesTest.java | 2 +- .../query/blackbox/ClusteredQueryTest.java | 200 +++++++++++++----- .../TopologyAwareClusteredQueryTest.java | 5 +- .../ClusteredQueryMassIndexingTest.java | 3 +- .../UnsharedDistMassIndexTest.java | 3 +- .../ClusteredCacheQueryTimeoutTest.java | 3 +- .../org/infinispan/query/test/Person.java | 3 +- 29 files changed, 670 insertions(+), 167 deletions(-) create mode 100644 query-dsl/src/main/java/org/infinispan/query/dsl/IndexedQueryMode.java create mode 100644 query/src/main/java/org/infinispan/query/QueryDefinition.java create mode 100644 query/src/main/java/org/infinispan/query/clustered/QueryDefinitionExternalizer.java create mode 100644 query/src/main/java/org/infinispan/query/dsl/embedded/impl/HsQueryRequest.java diff --git a/query-dsl/src/main/java/org/infinispan/query/dsl/IndexedQueryMode.java b/query-dsl/src/main/java/org/infinispan/query/dsl/IndexedQueryMode.java new file mode 100644 index 000000000000..6472f95861ad --- /dev/null +++ b/query-dsl/src/main/java/org/infinispan/query/dsl/IndexedQueryMode.java @@ -0,0 +1,20 @@ +package org.infinispan.query.dsl; + +/** + * Defines the execution mode of an indexed query. + * + * @since 9.2 + */ +public enum IndexedQueryMode { + /** + * Query is sent to all nodes, and results are combined before returning to the caller. This allows each node to have + * its own index, and the query will return the cluster wide results. + */ + BROADCAST, + + /** + * Query is executed locally in the caller. The whole index must be available in order to return full + * results, otherwise only results available at the caller's local index are returned. + */ + FETCH +} diff --git a/query/src/main/java/org/infinispan/query/QueryDefinition.java b/query/src/main/java/org/infinispan/query/QueryDefinition.java new file mode 100644 index 000000000000..5777b1682b62 --- /dev/null +++ b/query/src/main/java/org/infinispan/query/QueryDefinition.java @@ -0,0 +1,112 @@ +package org.infinispan.query; + +import java.util.Optional; + +import org.apache.lucene.search.Filter; +import org.apache.lucene.search.Sort; +import org.hibernate.search.filter.FullTextFilter; +import org.hibernate.search.query.engine.spi.HSQuery; +import org.infinispan.AdvancedCache; +import org.infinispan.query.dsl.embedded.impl.EmbeddedQueryEngine; +import org.infinispan.query.dsl.embedded.impl.HsQueryRequest; +import org.infinispan.query.dsl.embedded.impl.QueryEngine; +import org.infinispan.query.logging.Log; +import org.infinispan.util.logging.LogFactory; + +/** + * Stores the query to be executed in a cache in either a String or {@link HSQuery} form together with pagination + * and sort information. + * + * @since 9.2 + */ +public class QueryDefinition { + + private static final Log log = LogFactory.getLog(QueryDefinition.class, Log.class); + + private String queryString; + private HSQuery hsQuery; + private int maxResults = 100; + private int firstResult; + + private transient Sort sort; + + public QueryDefinition(String queryString) { + this.queryString = queryString; + } + + public QueryDefinition(HSQuery hsQuery) { + this.hsQuery = hsQuery; + } + + public Optional getQueryString() { + return Optional.ofNullable(queryString); + } + + public void initialize(AdvancedCache cache) { + if (hsQuery == null) { + QueryEngine queryEngine = cache.getComponentRegistry().getComponent(EmbeddedQueryEngine.class); + HsQueryRequest hsQueryRequest = queryEngine.createHsQuery(queryString); + this.hsQuery = hsQueryRequest.getHsQuery(); + this.sort = hsQueryRequest.getSort(); + hsQuery.firstResult(firstResult); + hsQuery.maxResults(maxResults); + } + } + + public HSQuery getHsQuery() { + if (hsQuery == null) { + throw new IllegalStateException("The QueryDefinition has not been initialized, make sure to call initialize(...) first"); + } + return hsQuery; + } + + public int getMaxResults() { + return maxResults; + } + + public void setMaxResults(int maxResults) { + this.maxResults = maxResults; + if (hsQuery != null) { + hsQuery.maxResults(maxResults); + } + } + + public int getFirstResult() { + return firstResult; + } + + public void setFirstResult(int firstResult) { + if (hsQuery != null) { + hsQuery.firstResult(firstResult); + } + this.firstResult = firstResult; + } + + public Sort getSort() { + return sort; + } + + public void setSort(Sort sort) { + if (queryString != null) { + throw log.sortNotSupportedWithQueryString(); + } + hsQuery.sort(sort); + this.sort = sort; + } + + + public void filter(Filter filter) { + if (queryString != null) throw log.filterNotSupportedWithQueryString(); + hsQuery.filter(filter); + } + + public FullTextFilter enableFullTextFilter(String name) { + if (queryString != null) throw log.filterNotSupportedWithQueryString(); + return hsQuery.enableFullTextFilter(name); + } + + public void disableFullTextFilter(String name) { + if (queryString != null) throw log.filterNotSupportedWithQueryString(); + hsQuery.disableFullTextFilter(name); + } +} diff --git a/query/src/main/java/org/infinispan/query/SearchManager.java b/query/src/main/java/org/infinispan/query/SearchManager.java index 5c3daff6355d..f7915d054df2 100644 --- a/query/src/main/java/org/infinispan/query/SearchManager.java +++ b/query/src/main/java/org/infinispan/query/SearchManager.java @@ -4,6 +4,7 @@ import org.apache.lucene.search.Query; import org.hibernate.search.query.dsl.EntityContext; import org.hibernate.search.stat.Statistics; +import org.infinispan.query.dsl.IndexedQueryMode; /** * The SearchManager is the entry point to create full text queries on top of a cache. @@ -18,27 +19,40 @@ public interface SearchManager { * in. If no classes are passed in, it is assumed that no type filtering is performed and so all known types will * be searched. * - * @param luceneQuery - {@link org.apache.lucene.search.Query} - * @param classes - optionally only return results of type that matches this list of acceptable types - * @return the CacheQuery object which can be used to iterate through results + * @param luceneQuery {@link org.apache.lucene.search.Query} + * @param indexedQueryMode The {@link IndexedQueryMode} used when executing the query. + * @param classes Optionally only return results of type that matches this list of acceptable types. + * @return the CacheQuery object which can be used to iterate through results. */ - CacheQuery getQuery(Query luceneQuery, Class... classes); + CacheQuery getQuery(Query luceneQuery, IndexedQueryMode indexedQueryMode, Class... classes); /** - * Experimental. - * Provides Hibernate Search DSL to build full text queries - * @return + * Builds a {@link CacheQuery} from a query string. + * + * @throws org.hibernate.search.exception.SearchException if the queryString cannot be converted to an indexed query, + * due to lack of indexes to resolve it fully or if contains + * aggregations and grouping. + * @see #getQuery(Query, IndexedQueryMode, Class[]) */ - EntityContext buildQueryBuilderForClass(Class entityType); + CacheQuery getQuery(String queryString, IndexedQueryMode indexedQueryMode, Class... classes); /** - * Experimental! - * Use it to try out the newly introduced distributed queries. - * + * @see #getQuery(Query, IndexedQueryMode, Class[]) + */ + CacheQuery getQuery(Query luceneQuery, Class... classes); + + /*** + * @return {@link EntityContext} + */ + EntityContext buildQueryBuilderForClass(Class entityType); + + /*** * @param luceneQuery * @param classes * @return + * @deprecated since 9.2, use {@link #getQuery(Query, IndexedQueryMode, Class[])} with QueryMode.BROADCAST */ + @Deprecated CacheQuery getClusteredQuery(Query luceneQuery, Class... classes); /** diff --git a/query/src/main/java/org/infinispan/query/clustered/ClusteredCacheQueryImpl.java b/query/src/main/java/org/infinispan/query/clustered/ClusteredCacheQueryImpl.java index 7f8de8e0985a..248a554e38de 100644 --- a/query/src/main/java/org/infinispan/query/clustered/ClusteredCacheQueryImpl.java +++ b/query/src/main/java/org/infinispan/query/clustered/ClusteredCacheQueryImpl.java @@ -14,6 +14,7 @@ import org.infinispan.AdvancedCache; import org.infinispan.query.CacheQuery; import org.infinispan.query.FetchOptions; +import org.infinispan.query.QueryDefinition; import org.infinispan.query.ResultIterator; import org.infinispan.query.backend.KeyTransformationHandler; import org.infinispan.query.impl.CacheQueryImpl; @@ -26,8 +27,6 @@ */ public class ClusteredCacheQueryImpl extends CacheQueryImpl { - private Sort sort; - private Integer resultSize; private final ExecutorService asyncExecutor; @@ -39,27 +38,35 @@ public class ClusteredCacheQueryImpl extends CacheQueryImpl { private int firstResult = 0; public ClusteredCacheQueryImpl(Query luceneQuery, SearchIntegrator searchFactory, - ExecutorService asyncExecutor, AdvancedCache cache, KeyTransformationHandler keyTransformationHandler, Class... classes) { + ExecutorService asyncExecutor, AdvancedCache cache, KeyTransformationHandler keyTransformationHandler, Class... classes) { super(luceneQuery, searchFactory, cache, keyTransformationHandler, null, classes); this.asyncExecutor = asyncExecutor; - this.hSearchQuery = searchFactory.createHSQuery(luceneQuery, classes); + } + + public ClusteredCacheQueryImpl(String queryString, ExecutorService asyncExecutor, AdvancedCache cache, + KeyTransformationHandler keyTransformationHandler) { + super(queryString, cache, keyTransformationHandler); + this.asyncExecutor = asyncExecutor; + this.queryDefinition = new QueryDefinition(queryString); } @Override public CacheQuery maxResults(int maxResults) { this.maxResults = maxResults; + this.queryDefinition.setMaxResults(maxResults); return super.maxResults(maxResults); } @Override public CacheQuery firstResult(int firstResult) { this.firstResult = firstResult; + this.queryDefinition.setFirstResult(firstResult); return this; } @Override public CacheQuery sort(Sort sort) { - this.sort = sort; + this.queryDefinition.setSort(sort); return super.sort(sort); } @@ -67,7 +74,7 @@ public CacheQuery sort(Sort sort) { public int getResultSize() { int accumulator; if (resultSize == null) { - ClusteredQueryCommand command = ClusteredQueryCommand.getResultSize(hSearchQuery, cache); + ClusteredQueryCommand command = ClusteredQueryCommand.getResultSize(queryDefinition, cache); ClusteredQueryInvoker invoker = new ClusteredQueryInvoker(cache, asyncExecutor); List responses = invoker.broadcast(command); @@ -76,32 +83,32 @@ public int getResultSize() { for (QueryResponse response : responses) { accumulator += response.getResultSize(); } - resultSize = Integer.valueOf(accumulator); + resultSize = accumulator; } else { - accumulator = resultSize.intValue(); + accumulator = resultSize; } return accumulator; } @Override public ResultIterator iterator(FetchOptions fetchOptions) throws SearchException { - hSearchQuery.maxResults(getNodeMaxResults()); + queryDefinition.setMaxResults(getNodeMaxResults()); switch (fetchOptions.getFetchMode()) { case EAGER: { - ClusteredQueryCommand command = ClusteredQueryCommand.createEagerIterator(hSearchQuery, cache); + ClusteredQueryCommand command = ClusteredQueryCommand.createEagerIterator(queryDefinition, cache); HashMap topDocsResponses = broadcastQuery(command); - return new DistributedIterator<>(sort, + return new DistributedIterator<>(queryDefinition.getSort(), fetchOptions.getFetchSize(), this.resultSize, maxResults, firstResult, topDocsResponses, cache); } case LAZY: { UUID lazyItId = UUID.randomUUID(); - ClusteredQueryCommand command = ClusteredQueryCommand.createLazyIterator(hSearchQuery, cache, lazyItId); + ClusteredQueryCommand command = ClusteredQueryCommand.createLazyIterator(queryDefinition, cache, lazyItId); HashMap topDocsResponses = broadcastQuery(command); // Make a sort copy to avoid reversed results - return new DistributedLazyIterator<>(sort, + return new DistributedLazyIterator<>(queryDefinition.getSort(), fetchOptions.getFetchSize(), this.resultSize, maxResults, firstResult, lazyItId, topDocsResponses, asyncExecutor, cache); } diff --git a/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommand.java b/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommand.java index 35385decb66b..9e325d32d939 100644 --- a/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommand.java +++ b/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommand.java @@ -6,11 +6,11 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; -import org.hibernate.search.query.engine.spi.HSQuery; import org.infinispan.Cache; import org.infinispan.commands.ReplicableCommand; import org.infinispan.commands.remote.BaseRpcCommand; import org.infinispan.commons.marshall.MarshallUtil; +import org.infinispan.query.QueryDefinition; import org.infinispan.query.clustered.commandworkers.ClusteredQueryCommandWorker; import org.infinispan.query.impl.CommandInitializer; import org.infinispan.query.impl.CustomQueryCommand; @@ -30,7 +30,7 @@ public class ClusteredQueryCommand extends BaseRpcCommand implements ReplicableC private ClusteredQueryCommandType commandType; - private HSQuery query; + private QueryDefinition queryDefinition; // local instance (set only when command arrives on target node) private Cache cache; @@ -59,22 +59,22 @@ public void fetchExecutionContext(CommandInitializer ci) { this.cache = ci.getCacheManager().getCache(cacheName.toString()); } - public static ClusteredQueryCommand createLazyIterator(HSQuery query, Cache cache, UUID id) { + public static ClusteredQueryCommand createLazyIterator(QueryDefinition queryDefinition, Cache cache, UUID id) { ClusteredQueryCommand clQuery = new ClusteredQueryCommand(ClusteredQueryCommandType.CREATE_LAZY_ITERATOR, cache.getName()); - clQuery.query = query; + clQuery.queryDefinition = queryDefinition; clQuery.lazyQueryId = id; return clQuery; } - public static ClusteredQueryCommand getResultSize(HSQuery query, Cache cache) { + public static ClusteredQueryCommand getResultSize(QueryDefinition queryDefinition, Cache cache) { ClusteredQueryCommand clQuery = new ClusteredQueryCommand(ClusteredQueryCommandType.GET_RESULT_SIZE, cache.getName()); - clQuery.query = query; + clQuery.queryDefinition = queryDefinition; return clQuery; } - public static ClusteredQueryCommand createEagerIterator(HSQuery query, Cache cache) { + public static ClusteredQueryCommand createEagerIterator(QueryDefinition queryDefinition, Cache cache) { ClusteredQueryCommand clQuery = new ClusteredQueryCommand(ClusteredQueryCommandType.CREATE_EAGER_ITERATOR, cache.getName()); - clQuery.query = query; + clQuery.queryDefinition = queryDefinition; return clQuery; } @@ -110,7 +110,7 @@ public CompletableFuture invokeAsync() throws Throwable { } public QueryResponse perform(Cache cache) { - ClusteredQueryCommandWorker worker = commandType.getCommand(cache, query, lazyQueryId, docIndex); + ClusteredQueryCommandWorker worker = commandType.getCommand(cache, queryDefinition, lazyQueryId, docIndex); return worker.perform(); } @@ -122,7 +122,7 @@ public byte getCommandId() { @Override public void writeTo(ObjectOutput output) throws IOException { MarshallUtil.marshallEnum(commandType, output); - output.writeObject(query); + output.writeObject(queryDefinition); MarshallUtil.marshallUUID(lazyQueryId, output, true); output.writeInt(docIndex); } @@ -130,7 +130,7 @@ public void writeTo(ObjectOutput output) throws IOException { @Override public void readFrom(ObjectInput input) throws IOException, ClassNotFoundException { commandType = MarshallUtil.unmarshallEnum(input, ClusteredQueryCommandType::valueOf); - query = (HSQuery) input.readObject(); + queryDefinition = (QueryDefinition) input.readObject(); lazyQueryId = MarshallUtil.unmarshallUUID(input, true); docIndex = input.readInt(); } @@ -145,7 +145,7 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((cacheName == null) ? 0 : cacheName.hashCode()); - result = prime * result + ((query == null) ? 0 : query.hashCode()); + result = prime * result + ((queryDefinition == null) ? 0 : queryDefinition.hashCode()); return result; } @@ -163,10 +163,10 @@ public boolean equals(Object obj) { return false; } else if (!cacheName.equals(other.cacheName)) return false; - if (query == null) { - if (other.query != null) + if (queryDefinition == null) { + if (other.queryDefinition != null) return false; - } else if (!query.equals(other.query)) + } else if (!queryDefinition.equals(other.queryDefinition)) return false; return true; } diff --git a/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommandType.java b/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommandType.java index 2426a7b458af..c7c1ae4b0df1 100644 --- a/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommandType.java +++ b/query/src/main/java/org/infinispan/query/clustered/ClusteredQueryCommandType.java @@ -2,8 +2,8 @@ import java.util.UUID; -import org.hibernate.search.query.engine.spi.HSQuery; import org.infinispan.Cache; +import org.infinispan.query.QueryDefinition; import org.infinispan.query.clustered.commandworkers.CQCreateEagerQuery; import org.infinispan.query.clustered.commandworkers.CQCreateLazyQuery; import org.infinispan.query.clustered.commandworkers.CQGetResultSize; @@ -55,11 +55,10 @@ public ClusteredQueryCommandWorker getNewInstance() { protected abstract ClusteredQueryCommandWorker getNewInstance(); - public ClusteredQueryCommandWorker getCommand(Cache cache, HSQuery query, UUID lazyQueryId, - int docIndex) { - ClusteredQueryCommandWorker command = null; - command = getNewInstance(); - command.init(cache, query, lazyQueryId, docIndex); + public ClusteredQueryCommandWorker getCommand(Cache cache, QueryDefinition queryDefinition, UUID lazyQueryId, + int docIndex) { + ClusteredQueryCommandWorker command = getNewInstance(); + command.init(cache, queryDefinition, lazyQueryId, docIndex); return command; } diff --git a/query/src/main/java/org/infinispan/query/clustered/DistributedIterator.java b/query/src/main/java/org/infinispan/query/clustered/DistributedIterator.java index 7410ca9ad989..d2e710dc8982 100644 --- a/query/src/main/java/org/infinispan/query/clustered/DistributedIterator.java +++ b/query/src/main/java/org/infinispan/query/clustered/DistributedIterator.java @@ -51,7 +51,7 @@ public DistributedIterator(Sort sort, int fetchSize, int resultSize, int maxResu this.partialResults = new ClusteredTopDocs[parallels]; TopDocs[] partialTopDocs = sort != null ? new TopFieldDocs[parallels] : new TopDocs[parallels]; this.partialPositionNext = new int[parallels]; - int i=0; + int i = 0; for (Entry entry : topDocsResponses.entrySet()) { partialResults[i] = entry.getValue(); partialTopDocs[i] = partialResults[i].getNodeTopDocs().topDocs; @@ -81,7 +81,7 @@ public E next() { // fetch and return the value ScoreDoc scoreDoc = mergedResults.scoreDocs[currentIndex]; int index = scoreDoc.shardIndex; - if(partialPositionNext[index] == 0) { + if (partialPositionNext[index] == 0) { partialPositionNext[index] = findSpecificPosition(scoreDoc.doc, partialResults[index].getNodeTopDocs().topDocs); } int specificPosition = partialPositionNext[index]; @@ -91,14 +91,18 @@ public E next() { private int findSpecificPosition(int docId, TopDocs topDocs) { for (int i = 0; i < topDocs.scoreDocs.length; i++) { - if(topDocs.scoreDocs[i].doc == docId) return i; + if (topDocs.scoreDocs[i].doc == docId) return i; } return 0; } protected E fetchValue(int scoreIndex, ClusteredTopDocs topDoc) { NodeTopDocs eagerTopDocs = topDoc.getNodeTopDocs(); - return (E) cache.get(eagerTopDocs.keys[scoreIndex]); + Object[] keys = eagerTopDocs.keys; + if (keys != null && keys.length > 0) { + return (E) cache.get(eagerTopDocs.keys[scoreIndex]); + } + return (E) eagerTopDocs.projections[scoreIndex]; } @Override diff --git a/query/src/main/java/org/infinispan/query/clustered/NodeTopDocs.java b/query/src/main/java/org/infinispan/query/clustered/NodeTopDocs.java index 099fc3b99b36..3ac21f073944 100644 --- a/query/src/main/java/org/infinispan/query/clustered/NodeTopDocs.java +++ b/query/src/main/java/org/infinispan/query/clustered/NodeTopDocs.java @@ -14,14 +14,17 @@ public class NodeTopDocs { public final TopDocs topDocs; public final Object[] keys; + public final Object[] projections; - public NodeTopDocs(TopDocs topDocs, Object[] keys) { + public NodeTopDocs(TopDocs topDocs, Object[] keys, Object[] projections) { this.topDocs = topDocs; this.keys = keys; + this.projections = projections; } public NodeTopDocs(TopDocs topDocs) { this.topDocs = topDocs; this.keys = null; + this.projections = null; } } diff --git a/query/src/main/java/org/infinispan/query/clustered/QueryDefinitionExternalizer.java b/query/src/main/java/org/infinispan/query/clustered/QueryDefinitionExternalizer.java new file mode 100644 index 000000000000..47a7e827c2f2 --- /dev/null +++ b/query/src/main/java/org/infinispan/query/clustered/QueryDefinitionExternalizer.java @@ -0,0 +1,51 @@ +package org.infinispan.query.clustered; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Collections; +import java.util.Set; + +import org.hibernate.search.query.engine.spi.HSQuery; +import org.infinispan.commons.marshall.AdvancedExternalizer; +import org.infinispan.query.QueryDefinition; +import org.infinispan.query.impl.externalizers.ExternalizerIds; + +public class QueryDefinitionExternalizer implements AdvancedExternalizer { + + @Override + public Set> getTypeClasses() { + return Collections.singleton(QueryDefinition.class); + } + + @Override + public Integer getId() { + return ExternalizerIds.QUERY_DEFINITION; + } + + @Override + public void writeObject(ObjectOutput output, QueryDefinition object) throws IOException { + if (object.getQueryString().isPresent()) { + output.writeBoolean(true); + output.writeUTF(object.getQueryString().get()); + } else { + output.writeBoolean(false); + output.writeObject(object.getHsQuery()); + } + output.writeInt(object.getFirstResult()); + output.writeInt(object.getMaxResults()); + } + + @Override + public QueryDefinition readObject(ObjectInput input) throws IOException, ClassNotFoundException { + QueryDefinition queryDefinition; + if (input.readBoolean()) { + queryDefinition = new QueryDefinition(input.readUTF()); + } else { + queryDefinition = new QueryDefinition((HSQuery) input.readObject()); + } + queryDefinition.setFirstResult(input.readInt()); + queryDefinition.setMaxResults(input.readInt()); + return queryDefinition; + } +} diff --git a/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateEagerQuery.java b/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateEagerQuery.java index 216ee860714f..e02dbd64ac73 100644 --- a/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateEagerQuery.java +++ b/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateEagerQuery.java @@ -2,6 +2,7 @@ import org.apache.lucene.search.TopDocs; import org.hibernate.search.query.engine.spi.DocumentExtractor; +import org.hibernate.search.query.engine.spi.HSQuery; import org.infinispan.query.backend.KeyTransformationHandler; import org.infinispan.query.clustered.NodeTopDocs; import org.infinispan.query.clustered.QueryResponse; @@ -18,33 +19,41 @@ public class CQCreateEagerQuery extends ClusteredQueryCommandWorker { @Override public QueryResponse perform() { + HSQuery query = queryDefinition.getHsQuery(); query.afterDeserialise(getSearchFactory()); - DocumentExtractor extractor = query.queryDocumentExtractor(); - try { + try (DocumentExtractor extractor = query.queryDocumentExtractor()) { int resultSize = query.queryResultSize(); - NodeTopDocs eagerTopDocs = resultSize == 0 ? null : collectKeys(extractor); + NodeTopDocs eagerTopDocs = resultSize == 0 ? null : collectKeys(extractor, query); QueryResponse queryResponse = new QueryResponse(eagerTopDocs, getQueryBox().getMyId(), resultSize); queryResponse.setAddress(cache.getAdvancedCache().getRpcManager().getAddress()); return queryResponse; - } finally { - extractor.close(); } } - private NodeTopDocs collectKeys(DocumentExtractor extractor) { + private NodeTopDocs collectKeys(DocumentExtractor extractor, HSQuery query) { TopDocs topDocs = extractor.getTopDocs(); - Object[] keys = new Object[topDocs.scoreDocs.length]; + int topDocsLength = topDocs.scoreDocs.length; + Object[] keys = null; + Object[] projections = null; KeyTransformationHandler keyTransformationHandler = KeyTransformationHandler .getInstance(cache.getAdvancedCache()); - // collecting keys (it's a eager query!) - for (int i = 0; i < topDocs.scoreDocs.length; i++) { - keys[i] = QueryExtractorUtil.extractKey(extractor, cache, - keyTransformationHandler, i); + if (query.getProjectedFields() == null) { + keys = new Object[topDocsLength]; + // collecting keys (it's a eager query!) + for (int i = 0; i < topDocsLength; i++) { + keys[i] = QueryExtractorUtil.extractKey(extractor, cache, + keyTransformationHandler, i); + } + } else { + projections = new Object[topDocsLength]; + for (int i = 0; i < topDocsLength; i++) { + projections[i] = QueryExtractorUtil.extractProjection(extractor, i); + } } - return new NodeTopDocs(topDocs, keys); + return new NodeTopDocs(topDocs, keys, projections); } } diff --git a/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateLazyQuery.java b/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateLazyQuery.java index 60fa60bdc543..6d3c31393754 100644 --- a/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateLazyQuery.java +++ b/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQCreateLazyQuery.java @@ -2,6 +2,7 @@ import org.apache.lucene.search.TopDocs; import org.hibernate.search.query.engine.spi.DocumentExtractor; +import org.hibernate.search.query.engine.spi.HSQuery; import org.infinispan.query.clustered.NodeTopDocs; import org.infinispan.query.clustered.QueryBox; import org.infinispan.query.clustered.QueryResponse; @@ -18,6 +19,7 @@ public class CQCreateLazyQuery extends ClusteredQueryCommandWorker { @Override public QueryResponse perform() { + HSQuery query = queryDefinition.getHsQuery(); query.afterDeserialise(getSearchFactory()); DocumentExtractor extractor = query.queryDocumentExtractor(); int resultSize = query.queryResultSize(); diff --git a/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQGetResultSize.java b/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQGetResultSize.java index 6e232c4867a7..1cc07dec170a 100644 --- a/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQGetResultSize.java +++ b/query/src/main/java/org/infinispan/query/clustered/commandworkers/CQGetResultSize.java @@ -1,6 +1,7 @@ package org.infinispan.query.clustered.commandworkers; import org.hibernate.search.query.engine.spi.DocumentExtractor; +import org.hibernate.search.query.engine.spi.HSQuery; import org.infinispan.query.clustered.QueryResponse; /** @@ -15,14 +16,11 @@ public class CQGetResultSize extends ClusteredQueryCommandWorker { @Override public QueryResponse perform() { + HSQuery query = queryDefinition.getHsQuery(); query.afterDeserialise(getSearchFactory()); - DocumentExtractor extractor = query.queryDocumentExtractor(); - try { + try (DocumentExtractor ignored = query.queryDocumentExtractor()) { int resultSize = query.queryResultSize(); - QueryResponse queryResponse = new QueryResponse(resultSize); - return queryResponse; - } finally { - extractor.close(); + return new QueryResponse(resultSize); } } diff --git a/query/src/main/java/org/infinispan/query/clustered/commandworkers/ClusteredQueryCommandWorker.java b/query/src/main/java/org/infinispan/query/clustered/commandworkers/ClusteredQueryCommandWorker.java index 8cc8afbacbef..1b3b878d9a50 100644 --- a/query/src/main/java/org/infinispan/query/clustered/commandworkers/ClusteredQueryCommandWorker.java +++ b/query/src/main/java/org/infinispan/query/clustered/commandworkers/ClusteredQueryCommandWorker.java @@ -2,10 +2,10 @@ import java.util.UUID; -import org.hibernate.search.query.engine.spi.HSQuery; import org.hibernate.search.spi.SearchIntegrator; import org.infinispan.Cache; import org.infinispan.factories.ComponentRegistry; +import org.infinispan.query.QueryDefinition; import org.infinispan.query.clustered.QueryBox; import org.infinispan.query.clustered.QueryResponse; @@ -27,13 +27,16 @@ public abstract class ClusteredQueryCommandWorker { private SearchIntegrator searchFactory; // the query - protected HSQuery query; + protected QueryDefinition queryDefinition; protected UUID lazyQueryId; protected int docIndex; - public void init(Cache cache, HSQuery query, UUID lazyQueryId, int docIndex) { + public void init(Cache cache, QueryDefinition queryDefinition, UUID lazyQueryId, int docIndex) { this.cache = cache; - this.query = query; + if (queryDefinition != null) { + this.queryDefinition = queryDefinition; + this.queryDefinition.initialize(cache.getAdvancedCache()); + } this.lazyQueryId = lazyQueryId; this.docIndex = docIndex; } diff --git a/query/src/main/java/org/infinispan/query/clustered/commandworkers/QueryExtractorUtil.java b/query/src/main/java/org/infinispan/query/clustered/commandworkers/QueryExtractorUtil.java index b467416aa02b..76df51a16247 100644 --- a/query/src/main/java/org/infinispan/query/clustered/commandworkers/QueryExtractorUtil.java +++ b/query/src/main/java/org/infinispan/query/clustered/commandworkers/QueryExtractorUtil.java @@ -2,6 +2,7 @@ import java.io.IOException; +import org.hibernate.search.exception.SearchException; import org.hibernate.search.query.engine.spi.DocumentExtractor; import org.infinispan.Cache; import org.infinispan.query.backend.KeyTransformationHandler; @@ -33,9 +34,16 @@ public static Object extractKey(DocumentExtractor extractor, Cache cache, return null; } - Object key = keyTransformationHandler.stringToKey(bufferDocumentId, cache + return keyTransformationHandler.stringToKey(bufferDocumentId, cache .getAdvancedCache().getClassLoader()); - return key; + } + + static Object[] extractProjection(DocumentExtractor extractor, int docIndex) { + try { + return extractor.extract(docIndex).getProjection(); + } catch (IOException e) { + throw new SearchException("Error while extracting projection...", e); + } } } diff --git a/query/src/main/java/org/infinispan/query/dsl/embedded/impl/HsQueryRequest.java b/query/src/main/java/org/infinispan/query/dsl/embedded/impl/HsQueryRequest.java new file mode 100644 index 000000000000..d60bad32f311 --- /dev/null +++ b/query/src/main/java/org/infinispan/query/dsl/embedded/impl/HsQueryRequest.java @@ -0,0 +1,34 @@ +package org.infinispan.query.dsl.embedded.impl; + +import org.apache.lucene.search.Sort; +import org.hibernate.search.query.engine.spi.HSQuery; + +/** + * Stores the definition of a {@link HSQuery}. + * + * @since 9.2 + */ +public class HsQueryRequest { + + private final HSQuery hsQuery; + private final Sort sort; + private final String[] projections; + + HsQueryRequest(HSQuery hsQuery, Sort sort, String[] projections) { + this.hsQuery = hsQuery; + this.sort = sort; + this.projections = projections; + } + + public HSQuery getHsQuery() { + return hsQuery; + } + + public Sort getSort() { + return sort; + } + + public String[] getProjections() { + return projections; + } +} diff --git a/query/src/main/java/org/infinispan/query/dsl/embedded/impl/QueryEngine.java b/query/src/main/java/org/infinispan/query/dsl/embedded/impl/QueryEngine.java index f1975087be65..5c653e667581 100644 --- a/query/src/main/java/org/infinispan/query/dsl/embedded/impl/QueryEngine.java +++ b/query/src/main/java/org/infinispan/query/dsl/embedded/impl/QueryEngine.java @@ -1,11 +1,17 @@ package org.infinispan.query.dsl.embedded.impl; +import static java.util.Collections.emptyMap; + import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; +import org.apache.lucene.search.Sort; +import org.hibernate.search.query.engine.spi.HSQuery; +import org.hibernate.search.query.engine.spi.TimeoutExceptionFactory; import org.hibernate.search.spi.SearchIntegrator; import org.infinispan.AdvancedCache; import org.infinispan.commons.dataconversion.IdentityEncoder; @@ -43,10 +49,14 @@ import org.infinispan.objectfilter.impl.syntax.parser.RowPropertyHelper; import org.infinispan.query.CacheQuery; import org.infinispan.query.SearchManager; +import org.infinispan.query.backend.KeyTransformationHandler; +import org.infinispan.query.clustered.ClusteredCacheQueryImpl; +import org.infinispan.query.dsl.IndexedQueryMode; import org.infinispan.query.dsl.Query; import org.infinispan.query.dsl.QueryFactory; import org.infinispan.query.dsl.impl.BaseQuery; import org.infinispan.query.dsl.impl.QueryStringCreator; +import org.infinispan.query.impl.CacheQueryImpl; import org.infinispan.query.impl.ComponentRegistryUtils; import org.infinispan.query.logging.Log; import org.infinispan.util.logging.LogFactory; @@ -687,6 +697,82 @@ protected IckleFilterAndConverter createFilter(String queryString, Map CacheQuery buildCacheQuery(org.apache.lucene.search.Query luceneQuery, IndexedQueryMode indexedQueryMode, + KeyTransformationHandler keyTransformationHandler, + TimeoutExceptionFactory timeoutExceptionFactory, + ExecutorService asyncExecutor, + Class... classes) { + CacheQuery cacheQuery; + if (indexedQueryMode == IndexedQueryMode.BROADCAST) { + cacheQuery = new ClusteredCacheQueryImpl<>(luceneQuery, getSearchFactory(), asyncExecutor, cache, + keyTransformationHandler, classes); + } else { + cacheQuery = new CacheQueryImpl<>(luceneQuery, getSearchFactory(), cache, keyTransformationHandler, + timeoutExceptionFactory, classes); + } + return (CacheQuery) cacheQuery; + } + + public HsQueryRequest createHsQuery(String queryString) { + IckleParsingResult parsingResult = parse(queryString); + if (parsingResult.hasGroupingOrAggregations()) { + throw log.groupAggregationsNotSupported(); + } + LuceneQueryParsingResult luceneParsingResult = transformParsingResult(parsingResult, emptyMap()); + org.apache.lucene.search.Query luceneQuery = makeTypeQuery(luceneParsingResult.getQuery(), luceneParsingResult.getTargetEntityName()); + HSQuery hsQuery = getSearchFactory().createHSQuery(luceneQuery); + Sort sort = luceneParsingResult.getSort(); + String[] projections = luceneParsingResult.getProjections(); + if (sort != null) { + hsQuery.sort(sort); + } + if (projections != null) { + hsQuery.projection(projections); + } + return new HsQueryRequest(hsQuery, sort, projections); + } + + public CacheQuery buildCacheQuery(String queryString, IndexedQueryMode indexedQueryMode, + KeyTransformationHandler keyTransformationHandler, + TimeoutExceptionFactory timeoutExceptionFactory, + ExecutorService asyncExecutor, + Class... classes) { + if (!isIndexed) { + throw log.cannotRunLuceneQueriesIfNotIndexed(cache.getName()); + } + + if (log.isDebugEnabled()) { + log.debugf("Building Lucene query for : %s", queryString); + } + + IckleParsingResult parsingResult = parse(queryString); + if (parsingResult.hasGroupingOrAggregations()) { + throw log.groupAggregationsNotSupported(); + } + LuceneQueryParsingResult luceneParsingResult = transformParsingResult(parsingResult, emptyMap()); + org.apache.lucene.search.Query luceneQuery = makeTypeQuery(luceneParsingResult.getQuery(), luceneParsingResult.getTargetEntityName()); + + if (indexedQueryMode == IndexedQueryMode.BROADCAST) { + return new ClusteredCacheQueryImpl<>(queryString, asyncExecutor, cache, keyTransformationHandler); + } else { + + if (log.isDebugEnabled()) { + log.debugf("The resulting Lucene query is : %s", luceneQuery.toString()); + } + + CacheQuery cacheQuery = new CacheQueryImpl<>(luceneQuery, searchFactory, cache, keyTransformationHandler, + timeoutExceptionFactory, classes); + + if (luceneParsingResult.getSort() != null) { + cacheQuery = cacheQuery.sort(luceneParsingResult.getSort()); + } + if (luceneParsingResult.getProjections() != null) { + cacheQuery = cacheQuery.projection(luceneParsingResult.getProjections()); + } + return (CacheQuery) cacheQuery; + } + } + /** * Build a Lucene index query. */ diff --git a/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java b/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java index 1c238d5fb826..dab382df7e92 100644 --- a/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java +++ b/query/src/main/java/org/infinispan/query/impl/CacheQueryImpl.java @@ -19,6 +19,7 @@ import org.infinispan.query.CacheQuery; import org.infinispan.query.FetchOptions; import org.infinispan.query.FetchOptions.FetchMode; +import org.infinispan.query.QueryDefinition; import org.infinispan.query.ResultIterator; import org.infinispan.query.backend.KeyTransformationHandler; @@ -43,7 +44,7 @@ public class CacheQueryImpl implements CacheQuery { protected final AdvancedCache cache; protected final KeyTransformationHandler keyTransformationHandler; - protected HSQuery hSearchQuery; + protected QueryDefinition queryDefinition; private ProjectionConverter projectionConverter; /** @@ -57,11 +58,18 @@ public CacheQueryImpl(Query luceneQuery, SearchIntegrator searchFactory, Advance cache, keyTransformationHandler); } + public CacheQueryImpl(String queryString, AdvancedCache cache, + KeyTransformationHandler keyTransformationHandler) { + this.queryDefinition = new QueryDefinition(queryString); + this.cache = cache; + this.keyTransformationHandler = keyTransformationHandler; + } + /** * Create a CacheQueryImpl based on a HSQuery. */ public CacheQueryImpl(HSQuery hSearchQuery, AdvancedCache cache, KeyTransformationHandler keyTransformationHandler) { - this.hSearchQuery = hSearchQuery; + this.queryDefinition = new QueryDefinition(hSearchQuery); this.cache = cache; this.keyTransformationHandler = keyTransformationHandler; } @@ -73,7 +81,7 @@ public CacheQueryImpl(HSQuery hSearchQuery, AdvancedCache cache, KeyTransf */ @Override public CacheQuery filter(Filter filter) { - hSearchQuery.filter(filter); + queryDefinition.filter(filter); return this; } @@ -82,12 +90,12 @@ public CacheQuery filter(Filter filter) { */ @Override public int getResultSize() { - return hSearchQuery.queryResultSize(); + return queryDefinition.getHsQuery().queryResultSize(); } @Override public CacheQuery sort(Sort sort) { - hSearchQuery.sort(sort); + queryDefinition.setSort(sort); return this; } @@ -99,7 +107,7 @@ public CacheQuery sort(Sort sort) { */ @Override public FullTextFilter enableFullTextFilter(String name) { - return hSearchQuery.enableFullTextFilter(name); + return queryDefinition.enableFullTextFilter(name); } /** @@ -109,7 +117,7 @@ public FullTextFilter enableFullTextFilter(String name) { */ @Override public CacheQuery disableFullTextFilter(String name) { - hSearchQuery.disableFullTextFilter(name); + queryDefinition.disableFullTextFilter(name); return this; } @@ -121,13 +129,13 @@ public CacheQuery disableFullTextFilter(String name) { */ @Override public CacheQuery firstResult(int firstResult) { - hSearchQuery.firstResult(firstResult); + queryDefinition.setFirstResult(firstResult); return this; } @Override public CacheQuery maxResults(int maxResults) { - hSearchQuery.maxResults(maxResults); + queryDefinition.setMaxResults(maxResults); return this; } @@ -138,13 +146,14 @@ public ResultIterator iterator() throws SearchException { @Override public ResultIterator iterator(FetchOptions fetchOptions) throws SearchException { + HSQuery hSearchQuery = queryDefinition.getHsQuery(); if (fetchOptions.getFetchMode() == FetchOptions.FetchMode.EAGER) { hSearchQuery.getTimeoutManager().start(); List entityInfos = hSearchQuery.queryEntityInfos(); - return filterNulls(new EagerIterator<>(entityInfos, getResultLoader(), fetchOptions.getFetchSize())); + return filterNulls(new EagerIterator<>(entityInfos, getResultLoader(hSearchQuery), fetchOptions.getFetchSize())); } else if (fetchOptions.getFetchMode() == FetchOptions.FetchMode.LAZY) { DocumentExtractor extractor = hSearchQuery.queryDocumentExtractor(); //triggers actual Lucene search - return filterNulls(new LazyIterator<>(extractor, getResultLoader(), fetchOptions.getFetchSize())); + return filterNulls(new LazyIterator<>(extractor, getResultLoader(hSearchQuery), fetchOptions.getFetchSize())); } else { throw new IllegalArgumentException("Unknown FetchMode " + fetchOptions.getFetchMode()); } @@ -156,16 +165,17 @@ private ResultIterator filterNulls(ResultIterator iterator) { @Override public List list() throws SearchException { + HSQuery hSearchQuery = queryDefinition.getHsQuery(); hSearchQuery.getTimeoutManager().start(); final List entityInfos = hSearchQuery.queryEntityInfos(); - return (List) getResultLoader().load(entityInfos); + return (List) getResultLoader(hSearchQuery).load(entityInfos); } - private QueryResultLoader getResultLoader() { - return isProjected() ? getProjectionLoader() : getEntityLoader(); + private QueryResultLoader getResultLoader(HSQuery hSearchQuery) { + return isProjected(hSearchQuery) ? getProjectionLoader() : getEntityLoader(); } - private boolean isProjected() { + private boolean isProjected(HSQuery hSearchQuery) { return hSearchQuery.getProjectedFields() != null; } @@ -179,24 +189,24 @@ private EntityLoader getEntityLoader() { @Override public FacetManager getFacetManager() { - return hSearchQuery.getFacetManager(); + return queryDefinition.getHsQuery().getFacetManager(); } @Override public Explanation explain(int documentId) { - return hSearchQuery.explain(documentId); + return queryDefinition.getHsQuery().explain(documentId); } @Override public CacheQuery projection(String... fields) { this.projectionConverter = new ProjectionConverter(fields, cache, keyTransformationHandler); - hSearchQuery.projection(projectionConverter.getHSearchProjection()); + queryDefinition.getHsQuery().projection(projectionConverter.getHSearchProjection()); return (CacheQuery) this; } @Override public CacheQuery timeout(long timeout, TimeUnit timeUnit) { - hSearchQuery.getTimeoutManager().setTimeout(timeout, timeUnit); + queryDefinition.getHsQuery().getTimeoutManager().setTimeout(timeout, timeUnit); return this; } diff --git a/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java b/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java index 0f81f4dbb0cd..969dc6610cf5 100644 --- a/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java +++ b/query/src/main/java/org/infinispan/query/impl/LifecycleManager.java @@ -57,6 +57,7 @@ import org.infinispan.query.backend.SearchableCacheConfiguration; import org.infinispan.query.backend.TxQueryInterceptor; import org.infinispan.query.clustered.QueryBox; +import org.infinispan.query.clustered.QueryDefinitionExternalizer; import org.infinispan.query.continuous.impl.ContinuousQueryResult; import org.infinispan.query.continuous.impl.IckleContinuousQueryCacheEventFilterConverter; import org.infinispan.query.dsl.embedded.impl.EmbeddedQueryEngine; @@ -444,6 +445,7 @@ public void cacheManagerStarting(GlobalComponentRegistry gcr, GlobalConfiguratio externalizerMap.put(ExternalizerIds.LUCENE_QUERY_PREFIX, new LucenePrefixQueryExternalizer()); externalizerMap.put(ExternalizerIds.LUCENE_QUERY_WILDCARD, new LuceneWildcardQueryExternalizer()); externalizerMap.put(ExternalizerIds.LUCENE_QUERY_FUZZY, new LuceneFuzzyQueryExternalizer()); + externalizerMap.put(ExternalizerIds.QUERY_DEFINITION, new QueryDefinitionExternalizer()); } } diff --git a/query/src/main/java/org/infinispan/query/impl/SearchManagerImpl.java b/query/src/main/java/org/infinispan/query/impl/SearchManagerImpl.java index 36d4f937688f..5d32c5d27cd8 100644 --- a/query/src/main/java/org/infinispan/query/impl/SearchManagerImpl.java +++ b/query/src/main/java/org/infinispan/query/impl/SearchManagerImpl.java @@ -4,6 +4,7 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.search.Query; +import org.hibernate.search.exception.SearchException; import org.hibernate.search.query.dsl.EntityContext; import org.hibernate.search.query.engine.spi.HSQuery; import org.hibernate.search.query.engine.spi.TimeoutExceptionFactory; @@ -15,8 +16,10 @@ import org.infinispan.query.CacheQuery; import org.infinispan.query.MassIndexer; import org.infinispan.query.Transformer; +import org.infinispan.query.backend.KeyTransformationHandler; import org.infinispan.query.backend.QueryInterceptor; -import org.infinispan.query.clustered.ClusteredCacheQueryImpl; +import org.infinispan.query.dsl.IndexedQueryMode; +import org.infinispan.query.dsl.embedded.impl.EmbeddedQueryEngine; import org.infinispan.query.impl.massindex.DistributedExecutorMassIndexer; import org.infinispan.query.spi.SearchManagerImplementor; @@ -33,6 +36,7 @@ public class SearchManagerImpl implements SearchManagerImplementor { private final AdvancedCache cache; private final SearchIntegrator searchFactory; private final QueryInterceptor queryInterceptor; + private final EmbeddedQueryEngine queryEngine; private TimeoutExceptionFactory timeoutExceptionFactory; public SearchManagerImpl(AdvancedCache cache) { @@ -42,6 +46,27 @@ public SearchManagerImpl(AdvancedCache cache) { this.cache = cache; this.searchFactory = ComponentRegistryUtils.getComponent(cache, SearchIntegrator.class); this.queryInterceptor = ComponentRegistryUtils.getQueryInterceptor(cache); + this.queryEngine = ComponentRegistryUtils.getComponent(cache, EmbeddedQueryEngine.class); + } + + @Override + public CacheQuery getQuery(Query luceneQuery, IndexedQueryMode indexedQueryMode, Class... classes) { + queryInterceptor.enableClasses(classes); + KeyTransformationHandler keyTransformationHandler = queryInterceptor.getKeyTransformationHandler(); + ExecutorService asyncExecutor = queryInterceptor.getAsyncExecutor(); + return queryEngine.buildCacheQuery(luceneQuery, indexedQueryMode, keyTransformationHandler, timeoutExceptionFactory, asyncExecutor, classes); + } + + @Override + public CacheQuery getQuery(String queryString, IndexedQueryMode indexedQueryMode, Class... classes) { + queryInterceptor.enableClasses(classes); + KeyTransformationHandler keyTransformationHandler = queryInterceptor.getKeyTransformationHandler(); + try { + ExecutorService asyncExecutor = queryInterceptor.getAsyncExecutor(); + return queryEngine.buildCacheQuery(queryString, indexedQueryMode, keyTransformationHandler, timeoutExceptionFactory, asyncExecutor, classes); + } catch (SearchException se) { + throw new SearchException(queryString + " cannot be converted to an indexed Query", se); + } } /* (non-Javadoc) @@ -49,9 +74,7 @@ public SearchManagerImpl(AdvancedCache cache) { */ @Override public CacheQuery getQuery(Query luceneQuery, Class... classes) { - queryInterceptor.enableClasses(classes); - return new CacheQueryImpl<>(luceneQuery, searchFactory, cache, - queryInterceptor.getKeyTransformationHandler(), timeoutExceptionFactory, classes); + return getQuery(luceneQuery, IndexedQueryMode.FETCH, classes); } /** @@ -79,9 +102,7 @@ public CacheQuery getQuery(HSQuery hSearchQuery) { */ @Override public CacheQuery getClusteredQuery(Query luceneQuery, Class... classes) { - queryInterceptor.enableClasses(classes); - ExecutorService asyncExecutor = queryInterceptor.getAsyncExecutor(); - return new ClusteredCacheQueryImpl<>(luceneQuery, searchFactory, asyncExecutor, cache, queryInterceptor.getKeyTransformationHandler(), classes); + return getQuery(luceneQuery, IndexedQueryMode.BROADCAST, classes); } @Override @@ -99,7 +120,7 @@ public void setTimeoutExceptionFactory(TimeoutExceptionFactory timeoutExceptionF */ @Override public EntityContext buildQueryBuilderForClass(Class entityType) { - queryInterceptor.enableClasses(new Class[] { entityType }); + queryInterceptor.enableClasses(new Class[]{entityType}); return searchFactory.buildQueryBuilder().forEntity(entityType); } @@ -127,7 +148,7 @@ public Analyzer getAnalyzer(Class clazz) { @Override public void purge(Class entityType) { - queryInterceptor.purgeIndex(entityType); + queryInterceptor.purgeIndex(entityType); } @Override @@ -137,8 +158,7 @@ public T unwrap(Class cls) { } if (SearchManagerImplementor.class.isAssignableFrom(cls)) { return (T) this; - } - else { + } else { throw new IllegalArgumentException("Can not unwrap a SearchManagerImpl into a '" + cls + "'"); } } diff --git a/query/src/main/java/org/infinispan/query/impl/externalizers/ClusteredTopDocsExternalizer.java b/query/src/main/java/org/infinispan/query/impl/externalizers/ClusteredTopDocsExternalizer.java index e48887fb6ef6..beb5cad6604f 100644 --- a/query/src/main/java/org/infinispan/query/impl/externalizers/ClusteredTopDocsExternalizer.java +++ b/query/src/main/java/org/infinispan/query/impl/externalizers/ClusteredTopDocsExternalizer.java @@ -22,11 +22,16 @@ public Set> getTypeClasses() { public NodeTopDocs readObject(final ObjectInput input) throws IOException, ClassNotFoundException { final int keysNumber = UnsignedNumeric.readUnsignedInt(input); final Object[] keys = new Object[keysNumber]; - for (int i=0; i>> caches = createClusteredCaches(2, cacheCfg, "cacheA", "cacheB"); cacheAMachine1 = caches.get(0).get(0); cacheAMachine2 = caches.get(1).get(0); cacheBMachine1 = caches.get(0).get(1); cacheBMachine2 = caches.get(1).get(1); + populateCache(); } @Override diff --git a/query/src/test/java/org/infinispan/query/blackbox/ClusteredQueryTest.java b/query/src/test/java/org/infinispan/query/blackbox/ClusteredQueryTest.java index 1d9a4a65417a..e276e287e2bb 100644 --- a/query/src/test/java/org/infinispan/query/blackbox/ClusteredQueryTest.java +++ b/query/src/test/java/org/infinispan/query/blackbox/ClusteredQueryTest.java @@ -7,8 +7,10 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.BooleanClause.Occur; @@ -18,6 +20,8 @@ import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.lucene.search.SortField.Type; +import org.hibernate.search.engine.integration.impl.ExtendedSearchIntegrator; +import org.hibernate.search.exception.SearchException; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; @@ -28,9 +32,11 @@ import org.infinispan.query.ResultIterator; import org.infinispan.query.Search; import org.infinispan.query.SearchManager; +import org.infinispan.query.dsl.IndexedQueryMode; import org.infinispan.query.helper.StaticTestingErrorHandler; import org.infinispan.query.test.Person; import org.infinispan.test.MultipleCacheManagersTest; +import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; /** @@ -43,17 +49,12 @@ public class ClusteredQueryTest extends MultipleCacheManagersTest { private final QueryParser queryParser = createQueryParser("blurb"); - static final int NUM_ENTRIES = 30; + static final int NUM_ENTRIES = 50; Cache cacheAMachine1, cacheAMachine2; - CacheQuery cacheQuery; + private CacheQuery cacheQuery; protected StorageType storageType; - public ClusteredQueryTest() { - // BasicConfigurator.configure(); - cleanup = CleanupPhase.AFTER_METHOD; - } - public Object[] factory() { return new Object[]{ new ClusteredQueryTest().storageType(StorageType.OFF_HEAP), @@ -67,8 +68,10 @@ ClusteredQueryTest storageType(StorageType storageType) { return this; } - protected void enhanceConfig(ConfigurationBuilder cacheCfg) { - // meant to be overridden + @AfterMethod + @Override + protected void clearContent() throws Throwable { + // Leave it be } @Override @@ -83,10 +86,10 @@ protected void createCacheManagers() throws Throwable { .addProperty("lucene_version", "LUCENE_CURRENT"); cacheCfg.memory() .storageType(storageType); - enhanceConfig(cacheCfg); List> caches = createClusteredCaches(2, cacheCfg); cacheAMachine1 = caches.get(0); cacheAMachine2 = caches.get(1); + populateCache(); } protected CacheMode getCacheMode() { @@ -105,16 +108,13 @@ protected void prepareTestData() { } public void testLazyOrdered() throws ParseException { - populateCache(); - // applying sort SortField sortField = new SortField("age", Type.INT); Sort sort = new Sort(sortField); cacheQuery.sort(sort); for (int i = 0; i < 2; i++) { - ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.LAZY)); - try { + try (ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.LAZY))) { assert cacheQuery.getResultSize() == 10 : cacheQuery.getResultSize(); int previousAge = 0; @@ -123,28 +123,19 @@ public void testLazyOrdered() throws ParseException { assert person.getAge() > previousAge; previousAge = person.getAge(); } - } finally { - iterator.close(); } } StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } public void testLazyNonOrdered() throws ParseException { - populateCache(); - - ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.LAZY)); - try { + try (ResultIterator ignored = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.LAZY))) { assert cacheQuery.getResultSize() == 10 : cacheQuery.getResultSize(); - } finally { - iterator.close(); } StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } public void testLocalQuery() throws ParseException { - populateCache(); - final SearchManager searchManager1 = Search.getSearchManager(cacheAMachine1); final CacheQuery localQuery1 = searchManager1.getQuery(createLuceneQuery()); List results1 = localQuery1.list(); @@ -159,15 +150,12 @@ public void testLocalQuery() throws ParseException { } public void testEagerOrdered() throws ParseException { - populateCache(); - // applying sort SortField sortField = new SortField("age", Type.INT); Sort sort = new Sort(sortField); cacheQuery.sort(sort); - ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.EAGER)); - try { + try (ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.EAGER))) { assertEquals(10, cacheQuery.getResultSize()); int previousAge = 0; @@ -176,48 +164,34 @@ public void testEagerOrdered() throws ParseException { assert person.getAge() > previousAge; previousAge = person.getAge(); } - } finally { - iterator.close(); } StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } @Test(expectedExceptions = NoSuchElementException.class, expectedExceptionsMessageRegExp = "Out of boundaries") public void testIteratorNextOutOfBounds() throws Exception { - populateCache(); - cacheQuery.maxResults(1); - ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.EAGER)); - try { + try (ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.EAGER))) { assert iterator.hasNext(); iterator.next(); assert !iterator.hasNext(); iterator.next(); - } finally { - iterator.close(); } StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testIteratorRemove() throws Exception { - populateCache(); - cacheQuery.maxResults(1); - ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.EAGER)); - try { + try (ResultIterator iterator = cacheQuery.iterator(new FetchOptions().fetchMode(FetchOptions.FetchMode.EAGER))) { assert iterator.hasNext(); iterator.remove(); - } finally { - iterator.close(); } StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } public void testList() throws ParseException { - populateCache(); - // applying sort SortField sortField = new SortField("age", Type.INT); Sort sort = new Sort(sortField); @@ -235,13 +209,10 @@ public void testList() throws ParseException { } public void testGetResultSizeList() throws ParseException { - populateCache(); assertEquals(10, cacheQuery.getResultSize()); } public void testPagination() throws ParseException { - populateCache(); - cacheQuery.firstResult(2); cacheQuery.maxResults(1); @@ -277,8 +248,6 @@ private void testPaginationWithSort(int pageSize, String field, Type type) throw } private void testPaginationInternal(int pageSize, Sort sort) throws ParseException { - populateCache(); - CacheQuery paginationQuery = buildPaginationQuery(0, pageSize, sort); int idx = 0; @@ -296,7 +265,7 @@ private void testPaginationInternal(int pageSize, Sort sort) throws ParseExcepti private CacheQuery buildPaginationQuery(int offset, int pageSize, Sort sort) throws ParseException { CacheQuery clusteredQuery = Search.getSearchManager(cacheAMachine1) - .getClusteredQuery(new MatchAllDocsQuery()); + .getQuery(new MatchAllDocsQuery(), IndexedQueryMode.BROADCAST); clusteredQuery.firstResult(offset); clusteredQuery.maxResults(pageSize); if (sort != null) { @@ -306,9 +275,8 @@ private CacheQuery buildPaginationQuery(int offset, int pageSize, Sort s } public void testQueryAll() throws ParseException { - populateCache(); CacheQuery clusteredQuery = Search.getSearchManager(cacheAMachine1) - .getClusteredQuery(new MatchAllDocsQuery(), Person.class); + .getQuery(new MatchAllDocsQuery(), IndexedQueryMode.BROADCAST, Person.class); assertEquals(NUM_ENTRIES, clusteredQuery.list().size()); StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); @@ -326,10 +294,136 @@ public void testFuzzyQuery() throws ParseException { StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } + public void testBroadcastIckleMatchAllQuery() throws Exception { + CacheQuery everybody = Search.getSearchManager(cacheAMachine1) + .getQuery(String.format("FROM %s", Person.class.getName()), IndexedQueryMode.BROADCAST, Person.class); + + assertEquals(NUM_ENTRIES, everybody.list().size()); + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + public void testBroadcastIckleTermQuery() throws Exception { + String targetName = "name2"; + CacheQuery singlePerson = Search.getSearchManager(cacheAMachine1) + .getQuery(String.format("FROM %s p where p.name:'%s'", Person.class.getName(), targetName), + IndexedQueryMode.BROADCAST, Person.class); + + assertEquals(1, singlePerson.list().size()); + assertEquals(targetName, singlePerson.list().iterator().next().getName()); + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + public void testBroadcastFuzzyIckle() throws Exception { + CacheQuery persons0to10 = Search.getSearchManager(cacheAMachine1) + .getQuery(String.format("FROM %s p where p.name:'nome'~2", Person.class.getName()), + IndexedQueryMode.BROADCAST, Person.class); + + assertEquals(10, persons0to10.list().size()); + + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + public void testBroadcastNumericRangeQuery() throws Exception { + CacheQuery infants = Search.getSearchManager(cacheAMachine1) + .getQuery(String.format("FROM %s p where p.age between 0 and 5", Person.class.getName()), + IndexedQueryMode.BROADCAST, Person.class); + + assertEquals(6, infants.list().size()); + + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + public void testBroadcastProjectionIckleQuery() throws Exception { + SearchManager sm = Search.getSearchManager(cacheAMachine2); + CacheQuery onlyNames = sm.getQuery( + String.format("Select p.name FROM %s p", Person.class.getName()), IndexedQueryMode.BROADCAST, Person.class + ); + + List results = onlyNames.list(); + assertEquals(NUM_ENTRIES, results.size()); + + Set names = new HashSet<>(); + results.iterator().forEachRemaining(s -> names.add((String) s[0])); + + Set allNames = IntStream.range(0, NUM_ENTRIES).boxed().map(i -> "name" + i).collect(Collectors.toSet()); + assertEquals(allNames, names); + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + public void testBroadcastSortedIckleQuery() throws Exception { + SearchManager sm = Search.getSearchManager(cacheAMachine2); + CacheQuery theLastWillBeFirst = sm.getQuery( + String.format("FROM %s p order by p.age desc", Person.class.getName()), IndexedQueryMode.BROADCAST, Person.class + ); + + List results = theLastWillBeFirst.list(); + assertEquals(NUM_ENTRIES, results.size()); + assertEquals(NUM_ENTRIES - 1, results.iterator().next().getAge()); + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + public void testPaginatedIckleQuery() throws Exception { + SearchManager sm = Search.getSearchManager(cacheAMachine1); + CacheQuery q = sm.getQuery(String.format("FROM %s p order by p.age", Person.class.getName()), + IndexedQueryMode.BROADCAST, Person.class); + + q.firstResult(5); + q.maxResults(10); + + List results = q.list(); + + assertEquals(10, results.size()); + assertEquals("name5", results.iterator().next().getName()); + assertEquals("name14", results.get(9).getName()); + } + + public void testPartialIckleQuery() throws Exception { + SearchManager searchManager1 = Search.getSearchManager(cacheAMachine1); + SearchManager searchManager2 = Search.getSearchManager(cacheAMachine2); + String query = String.format("FROM %s p", Person.class.getName()); + + CacheQuery machine1Results = searchManager1.getQuery(query, IndexedQueryMode.FETCH, Person.class); + CacheQuery machine2Results = searchManager2.getQuery(query, IndexedQueryMode.FETCH, Person.class); + + int numDocsMachine1 = countLocalIndex(cacheAMachine1); + int numDocsMachine2 = countLocalIndex(cacheAMachine2); + + assertEquals(NUM_ENTRIES, numDocsMachine1 + numDocsMachine2); + assertEquals(numDocsMachine1, machine1Results.list().size()); + assertEquals(numDocsMachine2, machine2Results.list().size()); + + StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); + } + + private int countLocalIndex(Cache cache) { + SearchManager sm = Search.getSearchManager(cache); + ExtendedSearchIntegrator esi = sm.unwrap(ExtendedSearchIntegrator.class); + IndexReader indexReader = esi.getIndexManager("person").getReaderProvider().openIndexReader(); + return indexReader.numDocs(); + } + + @Test(expectedExceptions = SearchException.class, expectedExceptionsMessageRegExp = ".*cannot be converted to an indexed Query") + public void testPreventHybridQuery() throws Exception { + CacheQuery hybridQuery = Search.getSearchManager(cacheAMachine1) + .getQuery(String.format("FROM %s p where p.nonSearchableField = 'nothing'", Person.class.getName()), + IndexedQueryMode.BROADCAST, Person.class); + + hybridQuery.list(); + } + + @Test(expectedExceptions = SearchException.class, expectedExceptionsMessageRegExp = ".*cannot be converted to an indexed Query") + public void testPreventAggregationQueries() throws Exception { + CacheQuery aggregationQuery = Search.getSearchManager(cacheAMachine1) + .getQuery(String.format("FROM %s p where p.name:'name3' group by p.name", Person.class.getName()), + IndexedQueryMode.BROADCAST, Person.class); + + aggregationQuery.list(); + } + protected void populateCache() throws ParseException { prepareTestData(); - cacheQuery = Search.getSearchManager(cacheAMachine1).getClusteredQuery(createLuceneQuery()); + cacheQuery = Search.getSearchManager(cacheAMachine1).getQuery(createLuceneQuery(), IndexedQueryMode.BROADCAST); StaticTestingErrorHandler.assertAllGood(cacheAMachine1, cacheAMachine2); } diff --git a/query/src/test/java/org/infinispan/query/blackbox/TopologyAwareClusteredQueryTest.java b/query/src/test/java/org/infinispan/query/blackbox/TopologyAwareClusteredQueryTest.java index 91b6203dd25d..f841e9268637 100644 --- a/query/src/test/java/org/infinispan/query/blackbox/TopologyAwareClusteredQueryTest.java +++ b/query/src/test/java/org/infinispan/query/blackbox/TopologyAwareClusteredQueryTest.java @@ -19,9 +19,9 @@ public class TopologyAwareClusteredQueryTest extends ClusteredQueryTest { @Override protected void createCacheManagers() throws Throwable { List caches = TestQueryHelperFactory.createTopologyAwareCacheNodes(2, getCacheMode(), transactionEnabled(), - isIndexLocalOnly(), isRamDirectory(), "default", Person.class); + isIndexLocalOnly(), isRamDirectory(), "default", Person.class); - for(Object cache : caches) { + for (Object cache : caches) { cacheManagers.add(((Cache) cache).getCacheManager()); } @@ -29,6 +29,7 @@ protected void createCacheManagers() throws Throwable { cacheAMachine2 = (Cache) caches.get(1); waitForClusterToForm(); + populateCache(); } public CacheMode getCacheMode() { diff --git a/query/src/test/java/org/infinispan/query/distributed/ClusteredQueryMassIndexingTest.java b/query/src/test/java/org/infinispan/query/distributed/ClusteredQueryMassIndexingTest.java index 73d576a24866..34e9280e6488 100644 --- a/query/src/test/java/org/infinispan/query/distributed/ClusteredQueryMassIndexingTest.java +++ b/query/src/test/java/org/infinispan/query/distributed/ClusteredQueryMassIndexingTest.java @@ -7,6 +7,7 @@ import org.infinispan.Cache; import org.infinispan.query.CacheQuery; import org.infinispan.query.Search; +import org.infinispan.query.dsl.IndexedQueryMode; import org.testng.annotations.Test; /** @@ -22,7 +23,7 @@ protected String getConfigurationFile() { protected void verifyFindsCar(Cache cache, int expectedCount, String carMake) { CacheQuery cacheQuery = Search.getSearchManager(cache) - .getClusteredQuery(new TermQuery(new Term("make", carMake))); + .getQuery(new TermQuery(new Term("make", carMake)), IndexedQueryMode.BROADCAST); assertEquals(expectedCount, cacheQuery.getResultSize()); } diff --git a/query/src/test/java/org/infinispan/query/distributed/UnsharedDistMassIndexTest.java b/query/src/test/java/org/infinispan/query/distributed/UnsharedDistMassIndexTest.java index 8b37a2f81f3c..63d0a528b9b7 100644 --- a/query/src/test/java/org/infinispan/query/distributed/UnsharedDistMassIndexTest.java +++ b/query/src/test/java/org/infinispan/query/distributed/UnsharedDistMassIndexTest.java @@ -8,6 +8,7 @@ import org.infinispan.query.CacheQuery; import org.infinispan.query.Search; import org.infinispan.query.SearchManager; +import org.infinispan.query.dsl.IndexedQueryMode; import org.testng.annotations.Test; /** @@ -27,7 +28,7 @@ protected String getConfigurationFile() { @Override protected void verifyFindsCar(Cache cache, int expectedCount, String carMake) { SearchManager searchManager = Search.getSearchManager(cache); - CacheQuery cacheQuery = searchManager.getClusteredQuery(new TermQuery(new Term("make", carMake))); + CacheQuery cacheQuery = searchManager.getQuery(new TermQuery(new Term("make", carMake)), IndexedQueryMode.BROADCAST); assertEquals(expectedCount, cacheQuery.getResultSize()); } } diff --git a/query/src/test/java/org/infinispan/query/searchmanager/ClusteredCacheQueryTimeoutTest.java b/query/src/test/java/org/infinispan/query/searchmanager/ClusteredCacheQueryTimeoutTest.java index d14262fc11f9..5921012cf509 100644 --- a/query/src/test/java/org/infinispan/query/searchmanager/ClusteredCacheQueryTimeoutTest.java +++ b/query/src/test/java/org/infinispan/query/searchmanager/ClusteredCacheQueryTimeoutTest.java @@ -15,6 +15,7 @@ import org.infinispan.query.CacheQuery; import org.infinispan.query.Search; import org.infinispan.query.SearchManager; +import org.infinispan.query.dsl.IndexedQueryMode; import org.infinispan.query.test.Person; import org.infinispan.test.MultipleCacheManagersTest; import org.testng.annotations.Test; @@ -48,7 +49,7 @@ public void testClusteredQueryCacheTimeout() throws Exception { QueryParser queryParser = createQueryParser("bar"); org.apache.lucene.search.Query luceneQuery = queryParser.parse("fakebar"); - CacheQuery query = searchManager.getClusteredQuery(luceneQuery, Foo.class); + CacheQuery query = searchManager.getQuery(luceneQuery, IndexedQueryMode.BROADCAST, Foo.class); query.timeout(1, TimeUnit.NANOSECONDS); } diff --git a/query/src/test/java/org/infinispan/query/test/Person.java b/query/src/test/java/org/infinispan/query/test/Person.java index 5c696144992e..b76398a4cb73 100644 --- a/query/src/test/java/org/infinispan/query/test/Person.java +++ b/query/src/test/java/org/infinispan/query/test/Person.java @@ -107,7 +107,8 @@ public boolean equals(Object o) { if (age != person.age) return false; if (blurb != null ? !blurb.equals(person.blurb) : person.blurb != null) return false; if (name != null ? !name.equals(person.name) : person.name != null) return false; - if (dateOfGraduation != null ? !dateOfGraduation.equals(person.dateOfGraduation) : person.dateOfGraduation != null) return false; + if (dateOfGraduation != null ? !dateOfGraduation.equals(person.dateOfGraduation) : person.dateOfGraduation != null) + return false; return true; }