You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/10/19 14:03:20 UTC

svn commit: r1024211 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join: ChildNodeJoinMerger.java DescendantNodeJoinMerger.java EquiJoinMerger.java JoinMerger.java QueryEngine.java SameNodeJoinMerger.java

Author: jukka
Date: Tue Oct 19 12:03:19 2010
New Revision: 1024211

URL: http://svn.apache.org/viewvc?rev=1024211&view=rev
Log:
JCR-2715: Improved join query performance

Add support for offset and limit on join queries.
Better handling of queries with too many or clauses.
Various smaller improvements.

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ChildNodeJoinMerger.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/DescendantNodeJoinMerger.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoinMerger.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ChildNodeJoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ChildNodeJoinMerger.java?rev=1024211&r1=1024210&r2=1024211&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ChildNodeJoinMerger.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ChildNodeJoinMerger.java Tue Oct 19 12:03:19 2010
@@ -57,10 +57,10 @@ class ChildNodeJoinMerger extends JoinMe
     }
 
     @Override
-    public Constraint getRightJoinConstraint(List<Row> leftRows)
+    public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
             throws RepositoryException {
         // TODO Auto-generated method stub
-        return null;
+        return Collections.emptyList();
     }
 
     private Set<String> getValues(Set<String> selectors, Row row)

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/DescendantNodeJoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/DescendantNodeJoinMerger.java?rev=1024211&r1=1024210&r2=1024211&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/DescendantNodeJoinMerger.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/DescendantNodeJoinMerger.java Tue Oct 19 12:03:19 2010
@@ -27,7 +27,6 @@ import javax.jcr.RepositoryException;
 import javax.jcr.query.Row;
 import javax.jcr.query.qom.Constraint;
 import javax.jcr.query.qom.DescendantNodeJoinCondition;
-import javax.jcr.query.qom.EquiJoinCondition;
 import javax.jcr.query.qom.Join;
 import javax.jcr.query.qom.PropertyValue;
 import javax.jcr.query.qom.QueryObjectModelFactory;
@@ -59,10 +58,10 @@ class DescendantNodeJoinMerger extends J
     }
 
     @Override
-    public Constraint getRightJoinConstraint(List<Row> leftRows)
+    public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
             throws RepositoryException {
         // TODO Auto-generated method stub
-        return null;
+        return Collections.emptyList();
     }
 
     private Set<String> getValues(Set<String> selectors, Row row)

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoinMerger.java?rev=1024211&r1=1024210&r2=1024211&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoinMerger.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoinMerger.java Tue Oct 19 12:03:19 2010
@@ -76,7 +76,7 @@ class EquiJoinMerger extends JoinMerger 
     }
 
     @Override
-    public Constraint getRightJoinConstraint(List<Row> leftRows)
+    public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
             throws RepositoryException {
         Map<String, Literal> literals = new HashMap<String, Literal>();
         for (Row leftRow : leftRows) {
@@ -91,8 +91,7 @@ class EquiJoinMerger extends JoinMerger 
             constraints.add(factory.comparison(
                     rightProperty, JCR_OPERATOR_EQUAL_TO, literal));
         }
-
-        return Constraints.or(factory, constraints);
+        return constraints;
     }
 
     private Set<String> getValues(PropertyValue property, Row row)

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java?rev=1024211&r1=1024210&r2=1024211&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/JoinMerger.java Tue Oct 19 12:03:19 2010
@@ -141,7 +141,7 @@ abstract class JoinMerger {
     }
 
     public QueryResult merge(
-            RowIterator leftRows, RowIterator rightRows)
+            RowIterator leftRows, RowIterator rightRows, long offset, long limit)
             throws RepositoryException {
         RowIterator joinRows;
         if (JCR_JOIN_TYPE_RIGHT_OUTER.equals(type)) {
@@ -172,6 +172,16 @@ abstract class JoinMerger {
             boolean outer = JCR_JOIN_TYPE_LEFT_OUTER.equals(type);
             joinRows = mergeLeft(leftRows, map, outer);
         }
+        while ((offset-- > 0 || limit == 0) && joinRows.hasNext()) {
+            joinRows.nextRow();
+        }
+        if (limit > 0) {
+            List<Row> rows = new ArrayList<Row>((int) limit);
+            for (int i = 0; i < limit && joinRows.hasNext(); i++) {
+                rows.add(joinRows.nextRow());
+            }
+            joinRows = new RowIteratorAdapter(rows);
+        }
         return new SimpleQueryResult(columnNames, selectorNames, joinRows);
     }
 
@@ -252,7 +262,7 @@ abstract class JoinMerger {
     public abstract Set<String> getRightValues(Row row)
             throws RepositoryException;
 
-    public abstract Constraint getRightJoinConstraint(List<Row> leftRows)
+    public abstract List<Constraint> getRightJoinConstraints(List<Row> leftRows)
             throws RepositoryException;
 
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java?rev=1024211&r1=1024210&r2=1024211&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java Tue Oct 19 12:03:19 2010
@@ -28,15 +28,12 @@ import static javax.jcr.query.qom.QueryO
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
+import javax.jcr.NodeIterator;
 import javax.jcr.PropertyType;
 import javax.jcr.RangeIterator;
 import javax.jcr.RepositoryException;
@@ -76,6 +73,7 @@ import javax.jcr.query.qom.Source;
 import javax.jcr.query.qom.UpperCase;
 
 import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
 import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
 import org.apache.jackrabbit.commons.iterator.RowIteratorAdapter;
 
@@ -150,20 +148,18 @@ public class QueryEngine {
         this.evaluator = new OperandEvaluator(valueFactory, variables);
     }
 
-    public QueryEngine(Session session) throws RepositoryException {
-        this(session, new HashMap<String, Value>());
-    }
-
     public QueryResult execute(
-            Column[] columns, Source source,
-            Constraint constraint, Ordering[] orderings)
+            Column[] columns, Source source, Constraint constraint,
+            Ordering[] orderings, long offset, long limit)
             throws RepositoryException {
         if (source instanceof Selector) {
             Selector selector = (Selector) source;
-            return execute(columns, selector, constraint, orderings);
+            return execute(
+                    columns, selector, constraint, orderings, offset, limit);
         } else if (source instanceof Join) {
             Join join = (Join) source;
-            return execute(columns, join, constraint, orderings);
+            return execute(
+                    columns, join, constraint, orderings, offset, limit);
         } else {
             throw new UnsupportedRepositoryOperationException(
                     "Unknown source type: " + source);
@@ -171,8 +167,8 @@ public class QueryEngine {
     }
 
     protected QueryResult execute(
-            Column[] columns, Join join,
-            Constraint constraint, Ordering[] orderings)
+            Column[] columns, Join join, Constraint constraint,
+            Ordering[] orderings, long offset, long limit)
             throws RepositoryException {
         JoinMerger merger = JoinMerger.getJoinMerger(
                 join, getColumnMap(columns, getSelectorNames(join)),
@@ -183,42 +179,42 @@ public class QueryEngine {
 
         Source left = join.getLeft();
         Constraint leftConstraint = splitter.getLeftConstraint();
-        System.out.println("FROM " + left + " WHERE " + leftConstraint);
-        QueryResult leftResult = execute(null, left, leftConstraint, null);
+        QueryResult leftResult =
+            execute(null, left, leftConstraint, null, 0, -1);
         List<Row> leftRows = new ArrayList<Row>();
         for (Row row : JcrUtils.getRows(leftResult)) {
-            System.out.println(row);
             leftRows.add(row);
         }
 
+        RowIterator rightRows;
         Source right = join.getRight();
-        Constraint rightConstraint = Constraints.and(
-                qomFactory,
-                merger.getRightJoinConstraint(leftRows),
-                splitter.getRightConstraint());
-        System.out.println("FROM " + right + " WHERE " + rightConstraint);
-        QueryResult rightResult = execute(null, right, rightConstraint, null);
-
-        return merger.merge(
-                new RowIteratorAdapter(leftRows), rightResult.getRows());
-    }
-
-    private Set<String> getPaths(
-            String selectorName, String relativePath, List<Row> rows)
-            throws RepositoryException {
-        Set<String> paths = new HashSet<String>();
-        for (Row row : rows) {
-            try {
-                Node node = row.getNode(selectorName);
-                if (relativePath != null) {
-                    node = node.getNode(relativePath);
+        List<Constraint> rightConstraints =
+            merger.getRightJoinConstraints(leftRows);
+        if (rightConstraints.size() < 500) {
+            Constraint rightConstraint = Constraints.and(
+                    qomFactory,
+                    Constraints.or(qomFactory, rightConstraints),
+                    splitter.getRightConstraint());
+            rightRows =
+                execute(null, right, rightConstraint, null, 0, -1).getRows();
+        } else {
+            List<Row> list = new ArrayList<Row>();
+            for (int i = 0; i < rightConstraints.size(); i += 500) {
+                Constraint rightConstraint = Constraints.and(
+                        qomFactory,
+                        Constraints.or(qomFactory, rightConstraints.subList(
+                                i, Math.min(i + 500, rightConstraints.size()))),
+                        splitter.getRightConstraint());
+                QueryResult rigthResult =
+                    execute(null, right, rightConstraint, null, 0, -1);
+                for (Row row : JcrUtils.getRows(rigthResult)) {
+                    list.add(row);
                 }
-                paths.add(node.getPath());
-            } catch (PathNotFoundException e) {
-                // Node at relative path not found, skip
             }
+            rightRows = new RowIteratorAdapter(list);
         }
-        return paths;
+        return merger.merge(
+                new RowIteratorAdapter(leftRows), rightRows, offset, limit);
     }
 
     private String toSqlConstraint(Constraint constraint)
@@ -302,8 +298,8 @@ public class QueryEngine {
     }
 
     protected QueryResult execute(
-            Column[] columns, Selector selector,
-            Constraint constraint, Ordering[] orderings)
+            Column[] columns, Selector selector, Constraint constraint,
+            Ordering[] orderings, long offset, long limit)
             throws RepositoryException {
         StringBuilder builder = new StringBuilder();
         builder.append("SELECT * FROM ");
@@ -312,7 +308,6 @@ public class QueryEngine {
             builder.append(" WHERE ");
             builder.append(toSqlConstraint(constraint));
         }
-        System.out.println(builder.toString());
 
         QueryManager manager = session.getWorkspace().getQueryManager();
         Query query = manager.createQuery(builder.toString(), Query.SQL);
@@ -326,8 +321,20 @@ public class QueryEngine {
         final String[] columnNames =
             columnMap.keySet().toArray(new String[columnMap.size()]);
 
+        NodeIterator nodes = query.execute().getNodes();
+        while ((offset-- > 0 || limit == 0) && nodes.hasNext()) {
+            nodes.next();
+        }
+        if (limit > 0) {
+            List<Node> list = new ArrayList<Node>((int) limit);
+            for (int i = 0; i < limit && nodes.hasNext(); i++) {
+                list.add(nodes.nextNode());
+            }
+            nodes = new NodeIteratorAdapter(list);
+        }
+
         final String selectorName = selector.getSelectorName();
-        RangeIterator rows = new RangeIteratorAdapter(query.execute().getNodes()) {
+        RangeIterator rows = new RangeIteratorAdapter(nodes) {
             @Override
             public Object next() {
                 Node node = (Node) super.next();

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java?rev=1024211&r1=1024210&r2=1024211&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java Tue Oct 19 12:03:19 2010
@@ -60,10 +60,10 @@ class SameNodeJoinMerger extends JoinMer
     }
 
     @Override
-    public Constraint getRightJoinConstraint(List<Row> leftRows)
+    public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
             throws RepositoryException {
         // TODO Auto-generated method stub
-        return null;
+        return Collections.emptyList();
     }
 
     private Set<String> getValues(Set<String> selectors, Row row)