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/08/18 17:21:43 UTC

svn commit: r986736 - in /jackrabbit/branches/2.1: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ jackrabbit-core/src/test/java/org/apache/jackrabbit...

Author: jukka
Date: Wed Aug 18 15:21:43 2010
New Revision: 986736

URL: http://svn.apache.org/viewvc?rev=986736&view=rev
Log:
2.1: Merged revisions 986682, 986686 and 986715 (JCR-2719 and JCR-2718)

Added:
    jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.java
      - copied unchanged from r986686, jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.java
Modified:
    jackrabbit/branches/2.1/   (props changed)
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactoryImpl.java
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoin.java
    jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/Join.java
    jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
    jackrabbit/branches/2.1/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/qom/EquiJoinConditionTest.java

Propchange: jackrabbit/branches/2.1/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Aug 18 15:21:43 2010
@@ -2,4 +2,4 @@
 /jackrabbit/sandbox/JCR-1456:774917-886178
 /jackrabbit/sandbox/JCR-2170:812417-816332
 /jackrabbit/sandbox/tripod-JCR-2209:795441-795863
-/jackrabbit/trunk:931121,931479,931483-931484,931504,931609,931613,931838,931919,932318-932319,933144,933197,933203,933213,933216,933554,933646,933694,934405,934412,934849,935557,936668,938099,955222,955229,955307,955852,961487,961626,964362,965539
+/jackrabbit/trunk:931121,931479,931483-931484,931504,931609,931613,931838,931919,932318-932319,933144,933197,933203,933213,933216,933554,933646,933694,934405,934412,934849,935557,936668,938099,955222,955229,955307,955852,961487,961626,964362,965539,986682,986686,986715

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java Wed Aug 18 15:21:43 2010
@@ -23,7 +23,6 @@ import org.apache.jackrabbit.core.Hierar
 import org.apache.jackrabbit.core.query.lucene.join.Join;
 import org.apache.jackrabbit.spi.commons.query.qom.JoinConditionImpl;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.search.SortComparatorSource;
 
 /**
  * <code>JoinQuery</code> implements a query that performs a join.
@@ -51,9 +50,9 @@ public class JoinQuery implements MultiC
     private final JoinConditionImpl joinCondition;
 
     /**
-     * The sort comparator source of the index.
+     * Namespace mappings of this index.
      */
-    private final SortComparatorSource scs;
+    private final NamespaceMappings nsMappings;
 
     /**
      * The hierarchy manager of the workspace.
@@ -67,20 +66,20 @@ public class JoinQuery implements MultiC
      * @param right         the right side of the query.
      * @param joinType      the join type.
      * @param joinCondition the join condition.
-     * @param scs           the sort comparator source of the index.
+     * @param nsMappings namespace mappings of this index
      * @param hmgr          the hierarchy manager of the workspace.
      */
     public JoinQuery(MultiColumnQuery left,
                      MultiColumnQuery right,
                      JoinType joinType,
                      JoinConditionImpl joinCondition,
-                     SortComparatorSource scs,
+                     NamespaceMappings nsMappings,
                      HierarchyManager hmgr) {
         this.left = left;
         this.right = right;
         this.joinType = joinType;
         this.joinCondition = joinCondition;
-        this.scs = scs;
+        this.nsMappings = nsMappings;
         this.hmgr = hmgr;
     }
 
@@ -95,6 +94,6 @@ public class JoinQuery implements MultiC
         HierarchyResolver resolver = (HierarchyResolver) reader;
         return Join.create(left.execute(searcher, orderings, resultFetchHint),
                 right.execute(searcher, orderings, resultFetchHint),
-                joinType, joinCondition, reader, resolver, scs, hmgr);
+                joinType, joinCondition, reader, resolver, nsMappings, hmgr);
     }
 }

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactoryImpl.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactoryImpl.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryFactoryImpl.java Wed Aug 18 15:21:43 2010
@@ -50,7 +50,6 @@ import org.apache.lucene.queryParser.Que
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
-import org.apache.lucene.search.SortComparatorSource;
 
 /**
  * <code>LuceneQueryFactoryImpl</code> implements a lucene query factory.
@@ -63,11 +62,6 @@ public class LuceneQueryFactoryImpl impl
     private final SessionImpl session;
 
     /**
-     * The source comparator source.
-     */
-    private final SortComparatorSource scs;
-
-    /**
      * The hierarchy manager.
      */
     private final HierarchyManager hmgr;
@@ -115,7 +109,6 @@ public class LuceneQueryFactoryImpl impl
      * @param bindVariables   the bind variable values of the query
      */
     public LuceneQueryFactoryImpl(SessionImpl session,
-                                  SortComparatorSource scs,
                                   HierarchyManager hmgr,
                                   NamespaceMappings nsMappings,
                                   Analyzer analyzer,
@@ -123,7 +116,6 @@ public class LuceneQueryFactoryImpl impl
                                   IndexFormatVersion version,
                                   Map<Name, Value> bindVariables) {
         this.session = session;
-        this.scs = scs;
         this.hmgr = hmgr;
         this.nsMappings = nsMappings;
         this.analyzer = analyzer;
@@ -277,6 +269,6 @@ public class LuceneQueryFactoryImpl impl
         MultiColumnQuery left = create((SourceImpl) join.getLeft());
         MultiColumnQuery right = create((SourceImpl) join.getRight());
         return new JoinQuery(left, right, join.getJoinTypeInstance(),
-                (JoinConditionImpl) join.getJoinCondition(), scs, hmgr);
+                (JoinConditionImpl) join.getJoinCondition(), nsMappings, hmgr);
     }
 }

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java Wed Aug 18 15:21:43 2010
@@ -96,10 +96,8 @@ public class QueryObjectModelImpl extend
      */
     public QueryResult execute(long offset, long limit)
             throws RepositoryException {
-
-        LuceneQueryFactory factory = new LuceneQueryFactoryImpl(session,
-                index.getSortComparatorSource(),
-                index.getContext().getHierarchyManager(),
+        LuceneQueryFactory factory = new LuceneQueryFactoryImpl(
+                session, index.getContext().getHierarchyManager(),
                 index.getNamespaceMappings(), index.getTextAnalyzer(),
                 index.getSynonymProvider(), index.getIndexFormatVersion(),
                 getBindVariableValues());

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoin.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoin.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoin.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/EquiJoin.java Wed Aug 18 15:21:43 2010
@@ -17,14 +17,23 @@
 package org.apache.jackrabbit.core.query.lucene.join;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
+import org.apache.jackrabbit.core.query.lucene.FieldNames;
 import org.apache.jackrabbit.core.query.lucene.MultiColumnQueryHits;
+import org.apache.jackrabbit.core.query.lucene.NamespaceMappings;
 import org.apache.jackrabbit.core.query.lucene.ScoreNode;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.search.SortComparatorSource;
-import org.apache.lucene.search.ScoreDocComparator;
-import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
+import org.apache.lucene.index.TermEnum;
 
 /**
  * <code>EquiJoin</code> implements an equi join condition.
@@ -32,24 +41,15 @@ import org.apache.lucene.search.ScoreDoc
 public class EquiJoin extends AbstractCondition {
 
     /**
-     * Reusable score doc for value lookups.
-     */
-    private final ScoreDoc sDoc = new ScoreDoc(-1, 1.0f);
-
-    /**
      * The index reader.
      */
     private final IndexReader reader;
 
-    /**
-     * Map of inner score nodes indexed by the value of their join property.
-     */
-    private final ScoreNodeMap innerScoreNodes = new ScoreNodeMap();
+    private final Map<String, List<ScoreNode[]>> rowsByInnerNodeValue =
+        new HashMap<String, List<ScoreNode[]>>();
 
-    /**
-     * The score doc comparator for the outer query hits.
-     */
-    private final ScoreDocComparator outerLookup;
+    private final Map<Integer, Set<String>> valuesByOuterNodeDocument =
+        new HashMap<Integer, Set<String>>();
 
     /**
      * Creates a new equi join condition.
@@ -63,24 +63,63 @@ public class EquiJoin extends AbstractCo
      * @param outerProperty       the name of the property of the outer query
      *                            hits.
      * @throws IOException if an error occurs while reading from the index.
+     * @throws IllegalNameException 
      */
-    public EquiJoin(MultiColumnQueryHits inner,
-                    int innerScoreNodeIndex,
-                    SortComparatorSource scs,
-                    IndexReader reader,
-                    Name innerProperty,
-                    Name outerProperty) throws IOException {
+    public EquiJoin(
+            MultiColumnQueryHits inner, int innerScoreNodeIndex,
+            NamespaceMappings nsMappings, IndexReader reader,
+            Name innerProperty, Name outerProperty)
+            throws IOException, IllegalNameException {
         super(inner);
         this.reader = reader;
-        this.outerLookup = scs.newComparator(reader, outerProperty.toString());
-        ScoreDocComparator comparator = scs.newComparator(reader, innerProperty.toString());
-        ScoreNode[] nodes;
+
         // create lookup map
-        while ((nodes = inner.nextScoreNodes()) != null) {
-            sDoc.doc = nodes[innerScoreNodeIndex].getDoc(reader);
-            Comparable value = comparator.sortValue(sDoc);
-            if (value != null) {
-                innerScoreNodes.addScoreNodes(value, nodes);
+        Map<Integer, List<ScoreNode[]>> rowsByInnerDocument =
+            new HashMap<Integer, List<ScoreNode[]>>();
+        ScoreNode[] row = inner.nextScoreNodes();
+        while (row != null) {
+            int document = row[innerScoreNodeIndex].getDoc(reader);
+            List<ScoreNode[]> rows = rowsByInnerDocument.get(document);
+            if (rows == null) {
+                rows = new ArrayList<ScoreNode[]>();
+                rowsByInnerDocument.put(document, rows);
+            }
+            rows.add(row);
+            row = inner.nextScoreNodes();
+        }
+
+        // Build the rowsByInnerNodeValue map for efficient lookup in
+        // the getMatchingScoreNodes() method
+        String innerName = nsMappings.translateName(innerProperty);
+        for (Map.Entry<Term, String> entry : getPropertyTerms(innerName)) {
+            String value = entry.getValue();
+            TermDocs docs = reader.termDocs(entry.getKey());
+            while (docs.next()) {
+                List<ScoreNode[]> match = rowsByInnerDocument.get(docs.doc());
+                if (match != null) {
+                    List<ScoreNode[]> rows = rowsByInnerNodeValue.get(value); 
+                    if (rows == null) {
+                        rows = new ArrayList<ScoreNode[]>();
+                        rowsByInnerNodeValue.put(value, rows);
+                    }
+                    rows.addAll(match);
+                }
+            }
+        }
+
+        // Build the valuesByOuterNodeDocument map for efficient lookup in
+        // the getMatchingScoreNodes() method
+        String outerName = nsMappings.translateName(outerProperty);
+        for (Map.Entry<Term, String> entry : getPropertyTerms(outerName)) {
+            String value = entry.getValue();
+            TermDocs docs = reader.termDocs(entry.getKey());
+            while (docs.next()) {
+                Set<String> values = valuesByOuterNodeDocument.get(docs.doc());
+                if (values == null) {
+                    values = new HashSet<String>();
+                    valuesByOuterNodeDocument.put(docs.doc(), values);
+                }
+                values.add(value);
             }
         }
     }
@@ -90,8 +129,40 @@ public class EquiJoin extends AbstractCo
      */
     public ScoreNode[][] getMatchingScoreNodes(ScoreNode outer)
             throws IOException {
-        sDoc.doc = outer.getDoc(reader);
-        Comparable value = outerLookup.sortValue(sDoc);
-        return innerScoreNodes.getScoreNodes(value);
+        List<ScoreNode[]> list = new ArrayList<ScoreNode[]>();
+
+        Set<String> values = valuesByOuterNodeDocument.get(outer.getDoc(reader));
+        if (values != null) {
+            for (String value : values) {
+                List<ScoreNode[]> rows = rowsByInnerNodeValue.get(value);
+                if (rows != null) {
+                    list.addAll(rows);
+                }
+            }
+        }
+
+        return list.toArray(new ScoreNode[list.size()][]);
+    }
+
+    private Set<Map.Entry<Term, String>> getPropertyTerms(String property)
+            throws IOException {
+        Map<Term, String> map = new HashMap<Term, String>();
+
+        Term prefix = new Term(
+                FieldNames.PROPERTIES,
+                FieldNames.createNamedValue(property, ""));
+        TermEnum terms = reader.terms(prefix);
+        do {
+            Term term = terms.term();
+            if (term == null
+                    || !term.field().equals(prefix.field())
+                    || !term.text().startsWith(prefix.text())) {
+                break;
+            }
+            map.put(term, term.text().substring(prefix.text().length()));
+        } while (terms.next());
+
+        return map.entrySet();
     }
+
 }

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/Join.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/Join.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/Join.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/Join.java Wed Aug 18 15:21:43 2010
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.commons.que
 import org.apache.jackrabbit.core.HierarchyManager;
 import org.apache.jackrabbit.core.query.lucene.HierarchyResolver;
 import org.apache.jackrabbit.core.query.lucene.MultiColumnQueryHits;
+import org.apache.jackrabbit.core.query.lucene.NamespaceMappings;
 import org.apache.jackrabbit.core.query.lucene.ScoreNode;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
@@ -35,7 +36,6 @@ import org.apache.jackrabbit.spi.commons
 import org.apache.jackrabbit.spi.commons.query.qom.JoinConditionImpl;
 import org.apache.jackrabbit.spi.commons.query.qom.SameNodeJoinConditionImpl;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.search.SortComparatorSource;
 
 /**
  * <code>Join</code> implements the result of a join.
@@ -113,7 +113,7 @@ public class Join implements MultiColumn
      * @param condition the QOM join condition.
      * @param reader    the index reader.
      * @param resolver  the hierarchy resolver.
-     * @param scs       the sort comparator source of the index.
+     * @param nsMappings namespace mappings of this index
      * @param hmgr      the hierarchy manager of the workspace.
      * @return the join result.
      * @throws IOException if an error occurs while executing the join.
@@ -124,7 +124,7 @@ public class Join implements MultiColumn
                               final JoinConditionImpl condition,
                               final IndexReader reader,
                               final HierarchyResolver resolver,
-                              final SortComparatorSource scs,
+                              final NamespaceMappings nsMappings,
                               final HierarchyManager hmgr)
             throws IOException {
         try {
@@ -183,8 +183,9 @@ public class Join implements MultiColumn
                         outerPropName = node.getProperty2QName();
                     }
 
-                    Condition c = new EquiJoin(inner, getIndex(inner, innerName),
-                            scs, reader, innerPropName, outerPropName);
+                    Condition c = new EquiJoin(
+                            inner, getIndex(inner, innerName), nsMappings,
+                            reader, innerPropName, outerPropName);
                     return new Join(outer, outerIdx, isInner, c);
                 }
 

Modified: jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java Wed Aug 18 15:21:43 2010
@@ -42,6 +42,7 @@ public class TestAll extends TestCase {
         suite.addTestSuite(FulltextQueryTest.class);
         suite.addTestSuite(SelectClauseTest.class);
         suite.addTestSuite(SQLTest.class);
+        suite.addTestSuite(JoinTest.class);
         suite.addTestSuite(OrderByTest.class);
         suite.addTestSuite(XPathAxisTest.class);
         suite.addTestSuite(SkipDeletedNodesTest.class);

Modified: jackrabbit/branches/2.1/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/qom/EquiJoinConditionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/qom/EquiJoinConditionTest.java?rev=986736&r1=986735&r2=986736&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/qom/EquiJoinConditionTest.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/qom/EquiJoinConditionTest.java Wed Aug 18 15:21:43 2010
@@ -63,7 +63,7 @@ public class EquiJoinConditionTest exten
         JoinCondition c = qf.equiJoinCondition(
                 LEFT, propertyName1, RIGHT, propertyName2);
         QueryObjectModel qom = createQuery(QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER, c);
-        checkQOM(qom, new Node[][]{{null, n1}, {n1, n2}, {n2, n2}});
+        checkQOM(qom, new Node[][]{{n1, n2}, {n2, n2}});
     }
 
     public void testRightOuterJoin2() throws RepositoryException {
@@ -85,6 +85,6 @@ public class EquiJoinConditionTest exten
         JoinCondition c = qf.equiJoinCondition(
                 LEFT, propertyName2, RIGHT, propertyName1);
         QueryObjectModel qom = createQuery(QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER, c);
-        checkQOM(qom, new Node[][]{{n1, null}, {n2, n1}, {n2, n2}});
+        checkQOM(qom, new Node[][]{{n2, n1}, {n2, n2}});
     }
 }