You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2008/02/19 17:25:31 UTC
svn commit: r629145 -
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/
Author: mreutegg
Date: Tue Feb 19 08:25:26 2008
New Revision: 629145
URL: http://svn.apache.org/viewvc?rev=629145&view=rev
Log:
JCR-1397: Allow query results with unknown size
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryHits.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryHits.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeTraversingQueryHits.java (with props)
Removed:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WorkspaceTraversalResult.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PreparedQueryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryHits.java?rev=629145&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryHits.java Tue Feb 19 08:25:26 2008
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene;
+
+import java.io.IOException;
+
+/**
+ * <code>AbstractQueryHits</code> serves as a base class for {@link QueryHits}
+ * implementations.
+ */
+public abstract class AbstractQueryHits implements QueryHits {
+
+ /**
+ * Calls {@link #doClose()} and disposes the {@link PerQueryCache}.
+ *
+ * @throws IOException if an error occurs while releasing resources.
+ */
+ public final void close() throws IOException {
+ try {
+ doClose();
+ } finally {
+ PerQueryCache.getInstance().dispose();
+ }
+ }
+
+ /**
+ * Provides a default implementation:
+ * <pre>
+ * while (n-- > 0) {
+ * if (nextScoreNode() == null) {
+ * return;
+ * }
+ * }
+ * </pre>
+ * Sub classes may overwrite this method and implement are more efficient
+ * way to skip hits.
+ *
+ * @param n the number of hits to skip.
+ * @throws IOException if an error occurs while skipping.
+ */
+ public void skip(int n) throws IOException {
+ while (n-- > 0) {
+ if (nextScoreNode() == null) {
+ return;
+ }
+ }
+ }
+
+ /**
+ * Releases resources held by this hits instance.
+ *
+ * @throws IOException if an error occurs while releasing resources.
+ */
+ protected abstract void doClose() throws IOException;
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryHits.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java?rev=629145&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java Tue Feb 19 08:25:26 2008
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene;
+
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.index.IndexReader;
+import org.apache.jackrabbit.core.SessionImpl;
+
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+
+/**
+ * <code>JackrabbitIndexSearcher</code> implements an index searcher with
+ * jackrabbit specific optimizations.
+ */
+public class JackrabbitIndexSearcher extends IndexSearcher {
+
+ /**
+ * The session that executes the query.
+ */
+ private final SessionImpl session;
+
+ /**
+ * The underlying index reader.
+ */
+ private final IndexReader reader;
+
+ /**
+ * Creates a new jackrabbit index searcher.
+ *
+ * @param s the session that executes the query.
+ * @param r the index reader.
+ */
+ public JackrabbitIndexSearcher(SessionImpl s, IndexReader r) {
+ super(r);
+ this.session = s;
+ this.reader = r;
+ }
+
+ /**
+ * Executes the query and returns the hits that match the query.
+ *
+ * @param query the query to execute.
+ * @param sort the sort criteria.
+ * @return the query hits.
+ * @throws IOException if an error occurs while executing the query.
+ */
+ public QueryHits execute(Query query, Sort sort) throws IOException {
+ // optimize certain queries
+ if (sort.getSort().length == 0) {
+ query = query.rewrite(reader);
+ if (query instanceof MatchAllDocsQuery) {
+ try {
+ return new NodeTraversingQueryHits(
+ session.getRootNode(), true);
+ } catch (RepositoryException e) {
+ IOException ex = new IOException(e.getMessage());
+ ex.initCause(e);
+ throw ex;
+ }
+ }
+ }
+ return new LuceneQueryHits(search(query, sort), reader);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryHits.java?rev=629145&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryHits.java Tue Feb 19 08:25:26 2008
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene;
+
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.index.IndexReader;
+import org.apache.jackrabbit.core.NodeId;
+
+import java.io.IOException;
+
+/**
+ * Wraps the lucene <code>Hits</code> object and adds a close method that allows
+ * to release resources after a query has been executed and the results have
+ * been read completely.
+ */
+public class LuceneQueryHits extends AbstractQueryHits {
+
+ /**
+ * The lucene hits we wrap.
+ */
+ private final Hits hits;
+
+ /**
+ * The IndexReader in use by the lucene hits.
+ */
+ private final IndexReader reader;
+
+ /**
+ * The index of the current hit. Initially invalid.
+ */
+ private int hitIndex = -1;
+
+ /**
+ * Creates a new <code>QueryHits</code> instance wrapping <code>hits</code>.
+ * @param hits the lucene hits.
+ * @param reader the IndexReader in use by <code>hits</code>.
+ */
+ public LuceneQueryHits(Hits hits, IndexReader reader) {
+ this.hits = hits;
+ this.reader = reader;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected final void doClose() throws IOException {
+ reader.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getSize() {
+ return hits.length();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ScoreNode nextScoreNode() throws IOException {
+ if (++hitIndex >= hits.length()) {
+ return null;
+ }
+ String uuid = reader.document(id(hitIndex), FieldSelectors.UUID).get(FieldNames.UUID);
+ return new ScoreNode(NodeId.valueOf(uuid), hits.score(hitIndex));
+ }
+
+ /**
+ * Skips <code>n</code> hits.
+ *
+ * @param n the number of hits to skip.
+ * @throws IOException if an error occurs while skipping.
+ */
+ public void skip(int n) throws IOException {
+ hitIndex += n;
+ }
+
+ //-------------------------------< internal >-------------------------------
+
+ /**
+ * Returns the document number for the <code>n</code><sup>th</sup> document
+ * in this QueryHits.
+ *
+ * @param n index.
+ * @return the document number for the <code>n</code><sup>th</sup>
+ * document.
+ * @throws IOException if an error occurs.
+ */
+ private final int id(int n) throws IOException {
+ return hits.id(n);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryHits.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeTraversingQueryHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeTraversingQueryHits.java?rev=629145&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeTraversingQueryHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeTraversingQueryHits.java Tue Feb 19 08:25:26 2008
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene;
+
+import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.jackrabbit.core.NodeImpl;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * <code>NodeTraversingQueryHits</code> implements query hits that traverse
+ * a node hierarchy.
+ */
+public class NodeTraversingQueryHits extends AbstractQueryHits {
+
+ /**
+ * The nodes to traverse.
+ */
+ private final Iterator nodes;
+
+ /**
+ * Creates query hits that consist of the nodes that are traversed from
+ * a given <code>start</code> node.
+ *
+ * @param start the start node of the traversal.
+ * @param includeStart whether to include the start node in the result.
+ */
+ public NodeTraversingQueryHits(Node start, boolean includeStart) {
+ this.nodes = new TraversingNodeIterator(start);
+ if (!includeStart) {
+ nodes.next();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Does nothing.
+ */
+ protected void doClose() throws IOException {
+ // nothing to do
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * This implementation always returns <code>-1</code>.
+ */
+ public int getSize() {
+ // don't know
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ScoreNode nextScoreNode() throws IOException {
+ if (nodes.hasNext()) {
+ NodeImpl n = (NodeImpl) nodes.next();
+ return new ScoreNode(n.getNodeId(), 1.0f);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Implements a node iterator that traverses a node tree in document
+ * order.
+ */
+ private class TraversingNodeIterator implements Iterator {
+
+ /**
+ * The current <code>Node</code>, which acts as the starting point for
+ * the traversal.
+ */
+ private final Node currentNode;
+
+ /**
+ * The chain of iterators which includes the iterators of the children
+ * of the current node.
+ */
+ private IteratorChain selfAndChildren;
+
+ /**
+ * Creates a <code>TraversingNodeIterator</code>.
+ * @param start the node from where to start the traversal.
+ */
+ TraversingNodeIterator(Node start) {
+ currentNode = start;
+ }
+
+ /**
+ * @exception UnsupportedOperationException always.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("remove");
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean hasNext() {
+ init();
+ return selfAndChildren.hasNext();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public Object next() {
+ init();
+ NodeImpl n = (NodeImpl) selfAndChildren.next();
+ return n;
+ }
+
+ /**
+ * Initializes the iterator chain once.
+ */
+ private void init() {
+ if (selfAndChildren == null) {
+ Iterator current = Arrays.asList(new Node[]{currentNode}).iterator();
+ List allIterators = new ArrayList();
+ allIterators.add(current);
+
+ // create new TraversingNodeIterator for each child
+ try {
+ NodeIterator children = currentNode.getNodes();
+ while (children.hasNext()) {
+ allIterators.add(new TraversingNodeIterator(children.nextNode()));
+ }
+ } catch (RepositoryException e) {
+ // currentNode is probably stale
+ }
+ selfAndChildren = new IteratorChain(allIterators);
+ }
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/NodeTraversingQueryHits.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PreparedQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PreparedQueryImpl.java?rev=629145&r1=629144&r2=629145&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PreparedQueryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PreparedQueryImpl.java Tue Feb 19 08:25:26 2008
@@ -120,7 +120,7 @@
orderSpecs[i] = orderings[i].getOrder() == QueryObjectModelConstants.ORDER_ASCENDING;
}
return new QueryResultImpl(index, itemMgr,
- session.getNamePathResolver(), session.getAccessManager(),
+ session, session.getAccessManager(),
// TODO: spell suggestion missing
this, query, null, selectProps, orderProps, orderSpecs,
getRespectDocumentOrder(), offset, limit);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java?rev=629145&r1=629144&r2=629145&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java Tue Feb 19 08:25:26 2008
@@ -16,94 +16,43 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import org.apache.lucene.search.Hits;
-import org.apache.lucene.index.IndexReader;
import org.apache.lucene.document.Document;
import java.io.IOException;
/**
- * Wraps the lucene <code>Hits</code> object and adds a close method that allows
- * to release resources after a query has been executed and the results have
- * been read completely.
+ * Defines an interface for reading query hits. A client will call {@link
+ * #close()} to release resources after a query has been executed and the
+ * results have been read.
*/
-public class QueryHits {
-
- /**
- * The lucene hits we wrap.
- */
- private final Hits hits;
-
- /**
- * The IndexReader in use by the lucene hits.
- */
- private final IndexReader reader;
-
- /**
- * Number of results.
- */
- private final int length;
-
- /**
- * Creates a new <code>QueryHits</code> instance wrapping <code>hits</code>.
- * @param hits the lucene hits.
- * @param reader the IndexReader in use by <code>hits</code>.
- */
- public QueryHits(Hits hits, IndexReader reader) {
- this.hits = hits;
- this.reader = reader;
- this.length = hits.length();
- }
+public interface QueryHits {
/**
* Releases resources held by this hits instance.
*
* @throws IOException if an error occurs while releasing resources.
*/
- public final void close() throws IOException {
- reader.close();
- PerQueryCache.getInstance().dispose();
- }
+ void close() throws IOException;
/**
- * Returns the number of results.
- * @return the number of results.
+ * @return the number of results or <code>-1</code> if the size is unknown.
*/
- public final int length() {
- return length;
- }
+ int getSize();
/**
- * Returns the <code>n</code><sup>th</sup> document in this QueryHits.
+ * Returns the next score node in this QueryHits or <code>null</code> if
+ * there are no more score nodes.
*
- * @param n index.
- * @return the <code>n</code><sup>th</sup> document in this QueryHits.
+ * @return the next score node in this QueryHits.
* @throws IOException if an error occurs while reading from the index.
*/
- public final Document doc(int n) throws IOException {
- return hits.doc(n);
- }
-
- /**
- * Returns the score for the <code>n</code><sup>th</sup> document in this
- * QueryHits.
- * @param n index.
- * @return the score for the <code>n</code><sup>th</sup> document.
- */
- public final float score(int n) throws IOException {
- return hits.score(n);
- }
+ ScoreNode nextScoreNode() throws IOException;
/**
- * Returns the document number for the <code>n</code><sup>th</sup> document
- * in this QueryHits.
+ * Skips a <code>n</code> score nodes.
*
- * @param n index.
- * @return the document number for the <code>n</code><sup>th</sup>
- * document.
- * @throws IOException if an error occurs.
+ * @param n the number of score nodes to skip.
+ * @throws IOException if an error occurs while skipping.
*/
- public final int id(int n) throws IOException {
- return hits.id(n);
- }
+ void skip(int n) throws IOException;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java?rev=629145&r1=629144&r2=629145&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java Tue Feb 19 08:25:26 2008
@@ -45,7 +45,8 @@
import java.util.List;
/**
- * Implements the {@link ExecutableQuery} interface.
+ * Implements the {@link org.apache.jackrabbit.core.query.ExecutableQuery}
+ * interface.
*/
public class QueryImpl extends AbstractQueryImpl {
@@ -105,13 +106,6 @@
log.debug("Executing query: \n" + root.dump());
}
- // check for special query
- if (allNodesQueryNode.equals(root)) {
- return new WorkspaceTraversalResult(session,
- new Name[] { NameConstants.JCR_PRIMARYTYPE, NameConstants.JCR_PATH, NameConstants.JCR_SCORE },
- session.getNamePathResolver());
- }
-
// build lucene query
Query query = LuceneQueryBuilder.createQuery(root, session,
index.getContext().getItemStateManager(),
@@ -135,7 +129,7 @@
}
return new QueryResultImpl(index, itemMgr,
- session.getNamePathResolver(), session.getAccessManager(),
+ session, session.getAccessManager(),
this, query, new SpellSuggestion(index.getSpellChecker(), root),
getSelectProperties(), orderProperties, ascSpecs,
getRespectDocumentOrder(), offset, limit);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java?rev=629145&r1=629144&r2=629145&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java Tue Feb 19 08:25:26 2008
@@ -17,11 +17,10 @@
package org.apache.jackrabbit.core.query.lucene;
import org.apache.jackrabbit.core.ItemManager;
-import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.apache.lucene.search.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,9 +58,9 @@
private final ItemManager itemMgr;
/**
- * The name and path resolver of the session executing the query
+ * The session executing the query
*/
- protected final NamePathResolver resolver;
+ protected final SessionImpl session;
/**
* The access manager of the session that executes the query.
@@ -107,8 +106,7 @@
/**
* This is the raw number of results that matched the query. This number
* also includes matches which will not be returned due to access
- * restrictions. This value is set when the query is executed the first
- * time.
+ * restrictions. This value is set whenever hits are obtained.
*/
private int numResults = -1;
@@ -144,8 +142,7 @@
* @param index the search index where the query is executed.
* @param itemMgr the item manager of the session executing the
* query.
- * @param resolver the namespace resolver of the session executing
- * the query.
+ * @param session the session executing the query.
* @param accessMgr the access manager of the session executiong the
* query.
* @param queryImpl the query instance which created this query
@@ -164,7 +161,7 @@
*/
public QueryResultImpl(SearchIndex index,
ItemManager itemMgr,
- NamePathResolver resolver,
+ SessionImpl session,
AccessManager accessMgr,
AbstractQueryImpl queryImpl,
Query query,
@@ -177,7 +174,7 @@
long limit) throws RepositoryException {
this.index = index;
this.itemMgr = itemMgr;
- this.resolver = resolver;
+ this.session = session;
this.accessMgr = accessMgr;
this.queryImpl = queryImpl;
this.query = query;
@@ -199,7 +196,7 @@
try {
String[] propNames = new String[selectProps.length];
for (int i = 0; i < selectProps.length; i++) {
- propNames[i] = resolver.getJCRName(selectProps[i]);
+ propNames[i] = session.getJCRName(selectProps[i]);
}
return propNames;
} catch (NamespaceException npde) {
@@ -228,7 +225,7 @@
}
}
return new RowIteratorImpl(getNodeIterator(), selectProps,
- resolver, excerptProvider, spellSuggestion);
+ session, excerptProvider, spellSuggestion);
}
/**
@@ -239,7 +236,8 @@
* @throws IOException if an error occurs while executing the query.
*/
protected QueryHits executeQuery() throws IOException {
- return index.executeQuery(queryImpl, query, orderProps, orderSpecs);
+ return index.executeQuery(session, queryImpl,
+ query, orderProps, orderSpecs);
}
//--------------------------------< internal >------------------------------
@@ -269,7 +267,7 @@
*/
private void getResults(long size) throws RepositoryException {
if (log.isDebugEnabled()) {
- log.debug("getResults(" + size + ")");
+ log.debug("getResults({}) limit={}", new Long(size), new Long(limit));
}
long maxResultSize = size;
@@ -287,21 +285,21 @@
// execute it
QueryHits result = null;
try {
+ long time = System.currentTimeMillis();
result = executeQuery();
-
- // set num results with the first query execution
- if (numResults == -1) {
- numResults = result.length();
- }
+ log.debug("query executed in {} ms",
+ new Long(System.currentTimeMillis() - time));
int start = resultNodes.size() + invalid + (int) offset;
- int max = Math.min(result.length(), numResults);
- for (int i = start; i < max && resultNodes.size() < maxResultSize; i++) {
- NodeId id = NodeId.valueOf(result.doc(i).get(FieldNames.UUID));
+ time = System.currentTimeMillis();
+ result.skip(start);
+ for (ScoreNode sn = result.nextScoreNode();
+ sn != null && resultNodes.size() < maxResultSize;
+ sn = result.nextScoreNode()) {
// check access
try {
- if (accessMgr.isGranted(id, AccessManager.READ)) {
- resultNodes.add(new ScoreNode(id, result.score(i)));
+ if (accessMgr.isGranted(sn.getNodeId(), AccessManager.READ)) {
+ resultNodes.add(sn);
} else {
invalid++;
}
@@ -310,6 +308,11 @@
invalid++;
}
}
+ log.debug("retrieved ScoreNodes in {} ms",
+ new Long(System.currentTimeMillis() - time));
+
+ // update numResults
+ numResults = result.getSize();
} catch (IOException e) {
log.error("Exception while executing query: ", e);
// todo throw?
@@ -328,10 +331,15 @@
* Returns the total number of hits. This is the number of results you
* will get get if you don't set any limit or offset. Keep in mind that this
* number may get smaller if nodes are found in the result set which the
- * current session has no permission to access.
+ * current session has no permission to access. This method may return
+ * <code>-1</code> if the total size is unknown.
*/
public int getTotalSize() {
- return numResults - invalid;
+ if (numResults == -1) {
+ return -1;
+ } else {
+ return numResults - invalid;
+ }
}
private final class LazyScoreNodeIterator implements ScoreNodeIterator {
@@ -381,9 +389,6 @@
if (skipNum < 0) {
throw new IllegalArgumentException("skipNum must not be negative");
}
- if ((position + invalid + skipNum) > numResults) {
- throw new NoSuchElementException();
- }
if (skipNum == 0) {
// do nothing
} else {
@@ -411,7 +416,11 @@
* nodes or the session does not have access to a node.
*/
public long getSize() {
- long size = getTotalSize() - offset;
+ int total = getTotalSize();
+ if (total == -1) {
+ return -1;
+ }
+ long size = total - offset;
if (limit > 0 && size > limit) {
return limit;
} else {
@@ -467,8 +476,14 @@
private void fetchNext() {
next = null;
int nextPos = position + 1;
- while (next == null && (nextPos + invalid) < numResults) {
+ while (next == null) {
if (nextPos >= resultNodes.size()) {
+ // quick check if there are more results at all
+ // this check is only possible if we have numResults
+ if (numResults != -1 && (nextPos + invalid) >= numResults) {
+ break;
+ }
+
// fetch more results
try {
int num;
@@ -484,7 +499,7 @@
// check again
if (nextPos >= resultNodes.size()) {
// no more valid results
- return;
+ break;
}
}
ScoreNode sn = (ScoreNode) resultNodes.get(nextPos);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=629145&r1=629144&r2=629145&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Tue Feb 19 08:25:26 2008
@@ -47,8 +47,6 @@
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
-import org.apache.lucene.search.Hits;
-import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
@@ -638,6 +636,7 @@
/**
* Executes the query on the search index.
+ * @param session the session that executes the query.
* @param queryImpl the query impl.
* @param query the lucene query.
* @param orderProps name of the properties for sort order.
@@ -647,22 +646,17 @@
* @return the lucene Hits object.
* @throws IOException if an error occurs while searching the index.
*/
- public QueryHits executeQuery(AbstractQueryImpl queryImpl,
+ public QueryHits executeQuery(SessionImpl session,
+ AbstractQueryImpl queryImpl,
Query query,
Name[] orderProps,
boolean[] orderSpecs) throws IOException {
checkOpen();
- SortField[] sortFields = createSortFields(orderProps, orderSpecs);
+
+ Sort sort = new Sort(createSortFields(orderProps, orderSpecs));
IndexReader reader = getIndexReader(queryImpl.needsSystemTree());
- IndexSearcher searcher = new IndexSearcher(reader);
- Hits hits;
- if (sortFields.length > 0) {
- hits = searcher.search(query, new Sort(sortFields));
- } else {
- hits = searcher.search(query);
- }
- return new QueryHits(hits, reader);
+ return new JackrabbitIndexSearcher(session, reader).execute(query, sort);
}
/**