You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ck...@apache.org on 2007/08/08 00:42:10 UTC

svn commit: r563688 - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ jackrabbit-core/s...

Author: ckiehl
Date: Tue Aug  7 15:42:09 2007
New Revision: 563688

URL: http://svn.apache.org/viewvc?view=rev&rev=563688
Log:
JCR-989: Added JackrabbitQuery interface which provides setLimit() and setOffset() and is implemented by QueryImpl.

Added:
    jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitQuery.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/LimitAndOffsetTest.java
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/AbstractQueryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java

Added: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitQuery.java?view=auto&rev=563688
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitQuery.java (added)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitQuery.java Tue Aug  7 15:42:09 2007
@@ -0,0 +1,26 @@
+package org.apache.jackrabbit.api;
+
+import javax.jcr.query.Query;
+
+/**
+ * This interface adds some methods that are to be expected in JCR 2.0 aka
+ * JSR-283 (https://jsr-283.dev.java.net/issues/show_bug.cgi?id=214). It will
+ * be obsolete when Jackrabbit implements JCR 2.0.
+ */
+public interface JackrabbitQuery extends Query {
+
+    /**
+     * Sets the maximum size of the result set.
+     * 
+     * @param limit new maximum size of the result set
+     */
+    void setLimit(long limit);
+
+    /**
+     * Sets the start offset of the result set.
+     * 
+     * @param offset new start offset of the result set
+     */
+    void setOffset(long offset);
+
+}

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/AbstractQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/AbstractQueryImpl.java?view=diff&rev=563688&r1=563687&r2=563688
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/AbstractQueryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/AbstractQueryImpl.java Tue Aug  7 15:42:09 2007
@@ -16,10 +16,10 @@
  */
 package org.apache.jackrabbit.core.query;
 
+import org.apache.jackrabbit.api.JackrabbitQuery;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.ItemManager;
 
-import javax.jcr.query.Query;
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
@@ -27,7 +27,7 @@
 /**
  * Defines common initialization methods for all query implementations.
  */
-public abstract class AbstractQueryImpl implements Query {
+public abstract class AbstractQueryImpl implements JackrabbitQuery {
 
     /**
      * Initializes a query instance from a query string.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java?view=diff&rev=563688&r1=563687&r2=563688
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/ExecutableQuery.java Tue Aug  7 15:42:09 2007
@@ -28,9 +28,11 @@
 
     /**
      * Executes this query and returns a <code>{@link QueryResult}</code>.
+     * @param offset the offset in the total result set
+     * @param limit the maximum result size
      *
      * @return a <code>QueryResult</code>
      * @throws RepositoryException if an error occurs
      */
-    QueryResult execute() throws RepositoryException;
+    QueryResult execute(long offset, long limit) throws RepositoryException;
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java?view=diff&rev=563688&r1=563687&r2=563688
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java Tue Aug  7 15:42:09 2007
@@ -89,6 +89,16 @@
     private boolean initialized = false;
 
     /**
+     * The maximum result size
+     */
+    private long limit;
+
+    /**
+     * The offset in the total result set
+     */
+    private long offset;
+
+    /**
      * @inheritDoc
      */
     public void init(SessionImpl session,
@@ -136,7 +146,7 @@
     public QueryResult execute() throws RepositoryException {
         checkInitialized();
         long time = System.currentTimeMillis();
-        QueryResult result = query.execute();
+        QueryResult result = query.execute(offset, limit);
         if (log.isDebugEnabled()) {
             time = System.currentTimeMillis() - time;
             NumberFormat format = NumberFormat.getNumberInstance();
@@ -206,6 +216,24 @@
         } catch (NameException e) {
             throw new RepositoryException(e.getMessage(), e);
         }
+    }
+    
+    /**
+     * Sets the maximum size of the result set.
+     * 
+     * @param limit new maximum size of the result set
+     */
+    public void setLimit(long limit) {
+        this.limit = limit;
+    }
+
+    /**
+     * Sets the start offset of the result set.
+     * 
+     * @param offset new start offset of the result set
+     */
+    public void setOffset(long offset) {
+        this.offset = offset;
     }
 
     //-----------------------------< internal >---------------------------------

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java?view=diff&rev=563688&r1=563687&r2=563688
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java Tue Aug  7 15:42:09 2007
@@ -125,6 +125,16 @@
     private ExcerptProvider excerptProvider;
 
     /**
+     * The offset in the total result set
+     */
+    private final long offset;
+
+    /**
+     * The maximum size of this result if limit > 0
+     */
+    private final long limit;
+
+    /**
      * Creates a new query result.
      *
      * @param index         the search index where the query is executed.
@@ -141,6 +151,8 @@
      * @param orderSpecs    the order specs, one for each order property name.
      * @param documentOrder if <code>true</code> the result is returned in
      *                      document order.
+     * @param limit         the maximum result size
+     * @param offset        the offset in the total result set
      */
     public LazyQueryResultImpl(SearchIndex index,
                            ItemManager itemMgr,
@@ -151,7 +163,9 @@
                            QName[] selectProps,
                            QName[] orderProps,
                            boolean[] orderSpecs,
-                           boolean documentOrder) throws RepositoryException {
+                           boolean documentOrder,
+                           long offset,
+                           long limit) throws RepositoryException {
         this.index = index;
         this.itemMgr = itemMgr;
         this.resolver = resolver;
@@ -162,6 +176,8 @@
         this.orderProps = orderProps;
         this.orderSpecs = orderSpecs;
         this.docOrder = orderProps.length == 0 && documentOrder;
+        this.offset = offset;
+        this.limit = limit;
         // if document order is requested get all results right away
         getResults(docOrder ? Integer.MAX_VALUE : index.getResultFetchSize());
     }
@@ -242,11 +258,19 @@
      * @throws RepositoryException if an error occurs while executing the
      *                             query.
      */
-    private void getResults(int size) throws RepositoryException {
+    private void getResults(long size) throws RepositoryException {
         if (log.isDebugEnabled()) {
             log.debug("getResults(" + size + ")");
         }
-        if (resultNodes.size() >= size) {
+        
+        long maxResultSize = size;
+        
+        // is there any limit?
+        if (limit > 0) {
+            maxResultSize = limit;
+        }
+        
+        if (resultNodes.size() >= maxResultSize) {
             // we already have them all
             return;
         }
@@ -263,12 +287,16 @@
 
             int start = resultNodes.size() + invalid;
             int max = Math.min(result.length(), numResults);
-            for (int i = start; i < max && resultNodes.size() < size; i++) {
+            for (int i = start; i < max && resultNodes.size() < maxResultSize; i++) {
                 NodeId id = NodeId.valueOf(result.doc(i).get(FieldNames.UUID));
                 // check access
                 try {
                     if (accessMgr.isGranted(id, AccessManager.READ)) {
-                        resultNodes.add(new ScoreNode(id, result.score(i)));
+                        if (i < offset) {
+                            invalid++;
+                        } else {
+                            resultNodes.add(new ScoreNode(id, result.score(i)));
+                        }
                     } else {
                         invalid++;
                     }

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?view=diff&rev=563688&r1=563687&r2=563688
==============================================================================
--- 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 Aug  7 15:42:09 2007
@@ -126,10 +126,12 @@
     /**
      * Executes this query and returns a <code>{@link QueryResult}</code>.
      *
+     * @param offset the offset in the total result set
+     * @param limit the maximum result size
      * @return a <code>QueryResult</code>
      * @throws RepositoryException if an error occurs
      */
-    public QueryResult execute() throws RepositoryException {
+    public QueryResult execute(long offset, long limit) throws RepositoryException {
         if (log.isDebugEnabled()) {
             log.debug("Executing query: \n" + root.dump());
         }
@@ -163,7 +165,7 @@
 
         return new LazyQueryResultImpl(index, itemMgr, session.getNamespaceResolver(),
                 session.getAccessManager(), this, query, getSelectProperties(),
-                orderProperties, ascSpecs, documentOrder);
+                orderProperties, ascSpecs, documentOrder, offset, limit);
     }
 
     /**

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/LimitAndOffsetTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/LimitAndOffsetTest.java?view=auto&rev=563688
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/LimitAndOffsetTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/LimitAndOffsetTest.java Tue Aug  7 15:42:09 2007
@@ -0,0 +1,91 @@
+package org.apache.jackrabbit.core.query;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+
+import org.apache.jackrabbit.api.JackrabbitQuery;
+
+public class LimitAndOffsetTest extends AbstractQueryTest {
+
+    private Node node1;
+    private Node node2;
+    private Node node3;
+
+    private JackrabbitQuery query;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        node1 = testRootNode.addNode("foo");
+        node1.setProperty("name", "1");
+        node2 = testRootNode.addNode("foo");
+        node2.setProperty("name", "2");
+        node3 = testRootNode.addNode("foo");
+        node3.setProperty("name", "3");
+
+        testRootNode.save();
+
+        query = createXPathQuery("/jcr:root" + testRoot + "/* order by @name");
+    }
+
+    private JackrabbitQuery createXPathQuery(String xpath)
+            throws InvalidQueryException, RepositoryException {
+        QueryManager queryManager = superuser.getWorkspace().getQueryManager();
+        return (JackrabbitQuery) queryManager.createQuery(xpath, Query.XPATH);
+    }
+
+    public void testLimit() throws Exception {
+        query.setLimit(1);
+        QueryResult result = query.execute();
+        checkResult(result, new Node[] { node1 });
+
+        query.setLimit(2);
+        result = query.execute();
+        checkResult(result, new Node[] { node1, node2 });
+
+        query.setLimit(3);
+        result = query.execute();
+        checkResult(result, new Node[] { node1, node2, node3 });
+    }
+
+    public void testOffset() throws Exception {
+        query.setOffset(0);
+        QueryResult result = query.execute();
+        checkResult(result, new Node[] { node1, node2, node3 });
+
+        query.setOffset(1);
+        result = query.execute();
+        checkResult(result, new Node[] { node2, node3 });
+
+        query.setOffset(2);
+        result = query.execute();
+        checkResult(result, new Node[] { node3 });
+    }
+
+    public void testOffsetAndLimit() throws Exception {
+        query.setOffset(0);
+        query.setLimit(1);
+        QueryResult result = query.execute();
+        checkResult(result, new Node[] { node1 });
+
+        query.setOffset(1);
+        query.setLimit(1);
+        result = query.execute();
+        checkResult(result, new Node[] { node2 });
+
+        query.setOffset(1);
+        query.setLimit(2);
+        result = query.execute();
+        checkResult(result, new Node[] { node2, node3 });
+
+        query.setOffset(0);
+        query.setLimit(2);
+        result = query.execute();
+        checkResult(result, new Node[] { node1, node2 });
+    }
+
+}