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 2011/03/10 12:20:36 UTC
svn commit: r1080186 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/query/lucene/join/
test/java/org/apache/jackrabbit/core/query/
Author: jukka
Date: Thu Mar 10 11:20:36 2011
New Revision: 1080186
URL: http://svn.apache.org/viewvc?rev=1080186&view=rev
Log:
JCR-2852: Support multi-selector OR constraints in join queries
Patch by Alex Parvulescu
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitInfo.java
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/ConstraintSplitter.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
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.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=1080186&r1=1080185&r2=1080186&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 Thu Mar 10 11:20:36 2011
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.query.lucene.join;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -59,7 +60,7 @@ class ChildNodeJoinMerger extends JoinMe
}
@Override
- public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
+ public List<Constraint> getRightJoinConstraints(Collection<Row> leftRows)
throws RepositoryException {
Set<String> paths = new HashSet<String>();
for (Row row : leftRows) {
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitInfo.java?rev=1080186&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitInfo.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitInfo.java Thu Mar 10 11:20:36 2011
@@ -0,0 +1,118 @@
+/*
+ * 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.join;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.query.qom.Constraint;
+import javax.jcr.query.qom.Or;
+import javax.jcr.query.qom.QueryObjectModelFactory;
+
+class ConstraintSplitInfo {
+
+ private final QueryObjectModelFactory factory;
+
+ private final List<Constraint> leftConstraints = new ArrayList<Constraint>();
+
+ private final List<Constraint> rightConstraints = new ArrayList<Constraint>();
+
+ private boolean isMultiple;
+
+ private final List<ConstraintSplitInfo> innerConstraints = new ArrayList<ConstraintSplitInfo>();
+
+ public ConstraintSplitInfo(QueryObjectModelFactory factory) {
+ this.factory = factory;
+ this.isMultiple = false;
+ }
+
+ private ConstraintSplitInfo(QueryObjectModelFactory factory,
+ List<Constraint> leftConstraints, List<Constraint> rightConstraints) {
+ this.factory = factory;
+ this.isMultiple = false;
+ this.leftConstraints.addAll(leftConstraints);
+ this.rightConstraints.addAll(rightConstraints);
+ }
+
+ public void addLeftConstraint(Constraint c) {
+ if (isMultiple) {
+ for (ConstraintSplitInfo csi : innerConstraints) {
+ csi.addLeftConstraint(c);
+ }
+ return;
+ }
+ leftConstraints.add(c);
+ }
+
+ public void addRightConstraint(Constraint c) {
+ if (isMultiple) {
+ for (ConstraintSplitInfo csi : innerConstraints) {
+ csi.addRightConstraint(c);
+ }
+ return;
+ }
+ rightConstraints.add(c);
+ }
+
+ public void split(Or or) {
+ if (isMultiple) {
+ for (ConstraintSplitInfo csi : innerConstraints) {
+ csi.split(or);
+ }
+ return;
+ }
+
+ this.isMultiple = true;
+
+ ConstraintSplitInfo csi1 = new ConstraintSplitInfo(factory,
+ leftConstraints, rightConstraints);
+ csi1.addLeftConstraint(or.getConstraint1());
+ this.innerConstraints.add(csi1);
+
+ ConstraintSplitInfo csi2 = new ConstraintSplitInfo(factory,
+ leftConstraints, rightConstraints);
+ csi2.addLeftConstraint(or.getConstraint2());
+ this.innerConstraints.add(csi2);
+
+ // would null be better?
+ this.leftConstraints.clear();
+ this.rightConstraints.clear();
+ }
+
+ public boolean isMultiple() {
+ return isMultiple;
+ }
+
+ public List<ConstraintSplitInfo> getInnerConstraints() {
+ return innerConstraints;
+ }
+
+ /**
+ * @return the left constraint
+ */
+ public Constraint getLeftConstraint() throws RepositoryException {
+ return Constraints.and(factory, leftConstraints);
+ }
+
+ /**
+ * @return the right constraint
+ */
+ public Constraint getRightConstraint() throws RepositoryException {
+ return Constraints.and(factory, rightConstraints);
+ }
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitter.java?rev=1080186&r1=1080185&r2=1080186&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ConstraintSplitter.java Thu Mar 10 11:20:36 2011
@@ -16,10 +16,8 @@
*/
package org.apache.jackrabbit.core.query.lucene.join;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import javax.jcr.RepositoryException;
@@ -45,15 +43,17 @@ import javax.jcr.query.qom.SameNode;
import javax.jcr.query.qom.UpperCase;
/**
- * Returns a mapped constraint that only refers to the given set of
- * selectors. The returned constraint is guaranteed to match an as small
- * as possible superset of the node tuples matched by the given original
- * constraints.
+ * Returns a mapped constraint that only refers to the given set of selectors.
+ * The returned constraint is guaranteed to match an as small as possible
+ * superset of the node tuples matched by the given original constraints.
*
- * @param constraint original constraint
- * @param selectors target selectors
+ * @param constraint
+ * original constraint
+ * @param selectors
+ * target selectors
* @return mapped constraint
- * @throws RepositoryException if the constraint mapping fails
+ * @throws RepositoryException
+ * if the constraint mapping fails
*/
class ConstraintSplitter {
@@ -63,39 +63,21 @@ class ConstraintSplitter {
private final Set<String> rightSelectors;
- private final List<Constraint> leftConstraints =
- new ArrayList<Constraint>();
+ private final ConstraintSplitInfo constraintSplitInfo;
- private final List<Constraint> rightConstraints =
- new ArrayList<Constraint>();
-
- public ConstraintSplitter(
- Constraint constraint, QueryObjectModelFactory factory,
- Set<String> leftSelectors, Set<String> rightSelectors)
- throws RepositoryException {
+ public ConstraintSplitter(Constraint constraint,
+ QueryObjectModelFactory factory, Set<String> leftSelectors,
+ Set<String> rightSelectors) throws RepositoryException {
this.factory = factory;
this.leftSelectors = leftSelectors;
this.rightSelectors = rightSelectors;
+ constraintSplitInfo = new ConstraintSplitInfo(this.factory);
if (constraint != null) {
split(constraint);
}
}
- /**
- * @return the left constraint
- */
- public Constraint getLeftConstraint() throws RepositoryException {
- return Constraints.and(factory, leftConstraints);
- }
-
- /**
- * @return the right constraint
- */
- public Constraint getRightConstraint() throws RepositoryException {
- return Constraints.and(factory, rightConstraints);
- }
-
private void split(Constraint constraint) throws RepositoryException {
if (constraint instanceof Not) {
splitNot((Not) constraint);
@@ -103,24 +85,33 @@ class ConstraintSplitter {
And and = (And) constraint;
split(and.getConstraint1());
split(and.getConstraint2());
+ } else if (constraint instanceof Or) {
+ if (isReferencingBothSides(getSelectorNames(constraint))) {
+ constraintSplitInfo.split((Or) constraint);
+ } else {
+ splitBySelectors(constraint, getSelectorNames(constraint));
+ }
} else {
splitBySelectors(constraint, getSelectorNames(constraint));
}
}
+ private boolean isReferencingBothSides(Set<String> selectors) {
+ return !leftSelectors.containsAll(selectors)
+ && !rightSelectors.containsAll(selectors);
+ }
+
private void splitNot(Not not) throws RepositoryException {
Constraint constraint = not.getConstraint();
if (constraint instanceof Not) {
split(((Not) constraint).getConstraint());
} else if (constraint instanceof And) {
And and = (And) constraint;
- split(factory.or(
- factory.not(and.getConstraint1()),
+ split(factory.or(factory.not(and.getConstraint1()),
factory.not(and.getConstraint2())));
} else if (constraint instanceof Or) {
Or or = (Or) constraint;
- split(factory.and(
- factory.not(or.getConstraint1()),
+ split(factory.and(factory.not(or.getConstraint1()),
factory.not(or.getConstraint2())));
} else {
splitBySelectors(not, getSelectorNames(constraint));
@@ -130,23 +121,24 @@ class ConstraintSplitter {
private void splitBySelectors(Constraint constraint, Set<String> selectors)
throws UnsupportedRepositoryOperationException {
if (leftSelectors.containsAll(selectors)) {
- leftConstraints.add(constraint);
+ constraintSplitInfo.addLeftConstraint(constraint);
} else if (rightSelectors.containsAll(selectors)) {
- rightConstraints.add(constraint);
+ constraintSplitInfo.addRightConstraint(constraint);
} else {
throw new UnsupportedRepositoryOperationException(
"Unable to split a constraint that references"
- + " both sides of a join: " + constraint);
+ + " both sides of a join: " + constraint);
}
}
/**
* Returns the names of the selectors referenced by the given constraint.
*
- * @param constraint constraint
+ * @param constraint
+ * constraint
* @return referenced selector names
* @throws UnsupportedRepositoryOperationException
- * if the constraint type is unknown
+ * if the constraint type is unknown
*/
private Set<String> getSelectorNames(Constraint constraint)
throws UnsupportedRepositoryOperationException {
@@ -184,14 +176,16 @@ class ConstraintSplitter {
}
/**
- * Returns the combined set of selector names referenced by the given
- * two constraint.
+ * Returns the combined set of selector names referenced by the given two
+ * constraint.
*
- * @param a first constraint
- * @param b second constraint
+ * @param a
+ * first constraint
+ * @param b
+ * second constraint
* @return selector names
* @throws UnsupportedRepositoryOperationException
- * if the constraint types are unknown
+ * if the constraint types are unknown
*/
private Set<String> getSelectorNames(Constraint a, Constraint b)
throws UnsupportedRepositoryOperationException {
@@ -204,10 +198,11 @@ class ConstraintSplitter {
/**
* Returns the selector name referenced by the given dynamic operand.
*
- * @param operand dynamic operand
+ * @param operand
+ * dynamic operand
* @return selector name
* @throws UnsupportedRepositoryOperationException
- * if the operand type is unknown
+ * if the operand type is unknown
*/
private String getSelectorName(DynamicOperand operand)
throws UnsupportedRepositoryOperationException {
@@ -238,4 +233,8 @@ class ConstraintSplitter {
}
}
+ public ConstraintSplitInfo getConstraintSplitInfo() {
+ return constraintSplitInfo;
+ }
+
}
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=1080186&r1=1080185&r2=1080186&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 Thu Mar 10 11:20:36 2011
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.query.lucene.join;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -59,7 +60,7 @@ class DescendantNodeJoinMerger extends J
}
@Override
- public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
+ public List<Constraint> getRightJoinConstraints(Collection<Row> leftRows)
throws RepositoryException {
Set<String> paths = new HashSet<String>();
for (Row row : leftRows) {
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=1080186&r1=1080185&r2=1080186&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 Thu Mar 10 11:20:36 2011
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.core.query
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -76,7 +77,7 @@ class EquiJoinMerger extends JoinMerger
}
@Override
- public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
+ public List<Constraint> getRightJoinConstraints(Collection<Row> leftRows)
throws RepositoryException {
Map<String, Literal> literals = new HashMap<String, Literal>();
for (Row leftRow : leftRows) {
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=1080186&r1=1080185&r2=1080186&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 Thu Mar 10 11:20:36 2011
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.core.query
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -224,7 +225,7 @@ abstract class JoinMerger {
public abstract Set<String> getRightValues(Row row)
throws RepositoryException;
- public abstract List<Constraint> getRightJoinConstraints(List<Row> leftRows)
+ public abstract List<Constraint> getRightJoinConstraints(Collection<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=1080186&r1=1080185&r2=1080186&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 Thu Mar 10 11:20:36 2011
@@ -24,9 +24,12 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@@ -164,45 +167,98 @@ public class QueryEngine {
merger.getLeftSelectors(), merger.getRightSelectors());
Source left = join.getLeft();
- Constraint leftConstraint = splitter.getLeftConstraint();
- QueryResult leftResult =
- execute(null, left, leftConstraint, null, 0, -1);
- List<Row> leftRows = new ArrayList<Row>();
+ Set<Row> leftRows = buildLeftRowsJoin(left, splitter.getConstraintSplitInfo());
+
+ Source right = join.getRight();
+ List<Constraint> rightConstraints = merger.getRightJoinConstraints(leftRows);
+ RowIterator rightRows = new RowIteratorAdapter(buildRightRowsJoin(right, splitter.getConstraintSplitInfo(), rightConstraints));
+
+ QueryResult result = merger.merge(new RowIteratorAdapter(leftRows), rightRows);
+ return sort(result, orderings, offset, limit);
+ }
+
+ private Comparator<Row> buildSimplePathRowComparator() {
+ return new Comparator<Row>() {
+
+ public int compare(Row o1, Row o2) {
+ try {
+ return o1.getPath().compareTo(o2.getPath());
+ } catch (RepositoryException e) {
+ throw new RuntimeException("Unable to compare rows " + o1
+ + " and " + o2, e);
+ }
+ }
+ };
+ }
+
+ private Set<Row> buildLeftRowsJoin(Source left, ConstraintSplitInfo csi)
+ throws RepositoryException {
+
+ if (csi.isMultiple()) {
+ // this *needs* to merge automatically multiple sets of nodes
+ Set<Row> leftRows = new TreeSet<Row>(buildSimplePathRowComparator());
+ for (ConstraintSplitInfo child : csi.getInnerConstraints()) {
+ leftRows.addAll(buildLeftRowsJoin(left, child));
+ }
+ return leftRows;
+ }
+
+ Set<Row> leftRows = new HashSet<Row>();
+ Constraint leftConstraint = csi.getLeftConstraint();
+ QueryResult leftResult = execute(null, left, leftConstraint, null, 0,
+ -1);
for (Row row : JcrUtils.getRows(leftResult)) {
leftRows.add(row);
}
+ return leftRows;
+ }
- RowIterator rightRows;
- Source right = join.getRight();
- List<Constraint> rightConstraints =
- merger.getRightJoinConstraints(leftRows);
+ private Set<Row> buildRightRowsJoin(Source right, ConstraintSplitInfo csi,
+ List<Constraint> rightConstraints) throws RepositoryException {
+
+ if (csi.isMultiple()) {
+ // this *needs* to merge automatically multiple sets of nodes
+ Set<Row> rightRows = new TreeSet<Row>(
+ buildSimplePathRowComparator());
+ for (ConstraintSplitInfo child : csi.getInnerConstraints()) {
+ rightRows.addAll(buildRightRowsJoin(right, child,
+ rightConstraints));
+ }
+ return rightRows;
+ }
+
+ // TODO refactor to page automatically at 500 *if needed*
if (rightConstraints.size() < 500) {
- Constraint rightConstraint = Constraints.and(
- qomFactory,
+ Set<Row> rightRows = new HashSet<Row>();
+ 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 rightResult =
- execute(null, right, rightConstraint, null, 0, -1);
- for (Row row : JcrUtils.getRows(rightResult)) {
- list.add(row);
- }
+ csi.getRightConstraint());
+ QueryResult rightResult = execute(null, right, rightConstraint,
+ null, 0, -1);
+ for (Row row : JcrUtils.getRows(rightResult)) {
+ rightRows.add(row);
+ }
+ return rightRows;
+ }
+
+ Set<Row> rightRows = new HashSet<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()))),
+ csi.getRightConstraint());
+ QueryResult rightResult = execute(null, right, rightConstraint,
+ null, 0, -1);
+ for (Row row : JcrUtils.getRows(rightResult)) {
+ rightRows.add(row);
}
- rightRows = new RowIteratorAdapter(list);
}
-
- QueryResult result =
- merger.merge(new RowIteratorAdapter(leftRows), rightRows);
- return sort(result, orderings, offset, limit);
+ return rightRows;
}
protected QueryResult execute(
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=1080186&r1=1080185&r2=1080186&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 Thu Mar 10 11:20:36 2011
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.query.lucene.join;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -62,7 +63,7 @@ class SameNodeJoinMerger extends JoinMer
}
@Override
- public List<Constraint> getRightJoinConstraints(List<Row> leftRows)
+ public List<Constraint> getRightJoinConstraints(Collection<Row> leftRows)
throws RepositoryException {
Set<String> paths = new HashSet<String>();
for (Row row : leftRows) {
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.java?rev=1080186&r1=1080185&r2=1080186&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/JoinTest.java Thu Mar 10 11:20:36 2011
@@ -23,8 +23,7 @@ import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
/**
- * Test case for
- * <a href="https://issues.apache.org/jira/browse/JCR-2718">JCR-2718</a>
+ * Test case for JOIN queries with JCR_SQL2
*/
public class JoinTest extends AbstractQueryTest {
@@ -45,8 +44,7 @@ public class JoinTest extends AbstractQu
Node n3 = node.addNode("node3");
n3.addMixin(NodeType.MIX_REFERENCEABLE);
- n3.setProperty(
- "testref",
+ n3.setProperty("testref",
new String[] { n1.getIdentifier(), n2.getIdentifier() },
PropertyType.REFERENCE);
testRootNode.getSession().save();
@@ -59,12 +57,72 @@ public class JoinTest extends AbstractQu
super.tearDown();
}
+ /**
+ * Test case for <a
+ * href="https://issues.apache.org/jira/browse/JCR-2718">JCR-2718</a>
+ */
public void testMultiValuedReferenceJoin() throws Exception {
- String join =
- "SELECT a.*, b.*"
- + " FROM [nt:base] AS a"
- + " INNER JOIN [nt:base] AS b ON a.[jcr:uuid] = b.testref";
- QueryResult result = qm.createQuery(join, Query.JCR_SQL2).execute();
+ String join = "SELECT a.*, b.*" + " FROM [nt:base] AS a"
+ + " INNER JOIN [nt:base] AS b ON a.[jcr:uuid] = b.testref";
+ checkResult(qm.createQuery(join, Query.JCR_SQL2).execute(), 2);
+ }
+
+ /**
+ * Test case for <a
+ * href="https://issues.apache.org/jira/browse/JCR-2852">JCR-2852</a>
+ */
+ public void testJoinWithOR() throws Exception {
+
+ String join = "SELECT a.*, b.*"
+ + " FROM [nt:base] AS a"
+ + " INNER JOIN [nt:base] AS b ON a.[jcr:uuid] = b.testref WHERE "
+ + "a.[jcr:primaryType] IS NOT NULL OR b.[jcr:primaryType] IS NOT NULL";
+
+ Query q = qm.createQuery(join, Query.JCR_SQL2);
+ QueryResult result = q.execute();
+ checkResult(result, 2);
+ }
+
+ /**
+ * Test case for <a
+ * href="https://issues.apache.org/jira/browse/JCR-2852">JCR-2852</a> <br>
+ * <p>
+ * Test inspired by <a
+ * href="http://markmail.org/message/gee5yyygozestsml">this discussion</a>
+ */
+ public void testMegaJoin() throws Exception {
+
+ // WHERE
+ // ( (ISSAMENODE(projects,
+ // '/repository/projects/U970f5509-54de-46d8-88bd-bc1a94ab85eb')))
+ // AND
+ // ( ( ISDESCENDANTNODE( projects, '/repository/projects') AND
+ // eventclassassociations.active = true )
+ // or
+ // ( ISDESCENDANTNODE( projects, '/repository/template') )
+ // )
+ // AND ((NAME(parentRelationshipStatus) = 'parentRelationshipStatus'))
+
+ StringBuilder join = new StringBuilder(
+ "SELECT a.*, b.* FROM [nt:base] AS a");
+ join.append(" INNER JOIN [nt:base] AS b ON a.[jcr:uuid] = b.testref ");
+ join.append(" WHERE ");
+ join.append(" ISSAMENODE(b, '/testroot/jointest/node3') ");
+ join.append(" AND ");
+ join.append(" ( ");
+ join.append(" ( ");
+ join.append(" ISDESCENDANTNODE(b, '/testroot/jointest') ");
+ join.append(" AND ");
+ join.append(" b.testref IS NOT NULL ");
+ join.append(" ) ");
+ join.append(" OR ");
+ join.append(" ISDESCENDANTNODE(a, '/testroot/jointest') ");
+ join.append(" ) ");
+ join.append(" AND ");
+ join.append(" (NAME(b) = 'node3') ");
+
+ Query q = qm.createQuery(join.toString(), Query.JCR_SQL2);
+ QueryResult result = q.execute();
checkResult(result, 2);
}