You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by al...@apache.org on 2011/07/06 18:03:02 UTC
svn commit: r1143477 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/query/lucene/join/
test/java/org/apache/jackrabbit/core/query/
Author: alexparvulescu
Date: Wed Jul 6 16:03:02 2011
New Revision: 1143477
URL: http://svn.apache.org/viewvc?rev=1143477&view=rev
Log:
JCR-3000 SQL2 Join with OR clause still has some issues
Modified:
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/RowPathComparator.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/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=1143477&r1=1143476&r2=1143477&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 Wed Jul 6 16:03:02 2011
@@ -137,6 +137,14 @@ abstract class JoinMerger {
this.evaluator = evaluator;
this.factory = factory;
}
+
+ public String[] getColumnNames(){
+ return columnNames;
+ }
+
+ public String[] getSelectorNames(){
+ return selectorNames;
+ }
public Set<String> getLeftSelectors() {
return leftSelectors;
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=1143477&r1=1143476&r2=1143477&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 Wed Jul 6 16:03:02 2011
@@ -64,11 +64,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class QueryEngine {
-
+
/**
* The logger instance for this class
*/
- private static final Logger log = LoggerFactory.getLogger(QueryEngine.class);
+ private static final Logger log = LoggerFactory
+ .getLogger(QueryEngine.class);
private static final int printIndentStep = 4;
@@ -80,7 +81,7 @@ public class QueryEngine {
private final ValueComparator comparator = new ValueComparator();
private final Ordering[] orderings;
-
+
private final OperandEvaluator evaluator;
private RowComparator(Ordering[] orderings, OperandEvaluator evaluator) {
@@ -105,8 +106,8 @@ public class QueryEngine {
}
return 0;
} catch (RepositoryException e) {
- throw new RuntimeException(
- "Unable to compare rows " + a + " and " + b, e);
+ throw new RuntimeException("Unable to compare rows " + a
+ + " and " + b, e);
}
}
@@ -150,10 +151,8 @@ public class QueryEngine {
long time = System.currentTimeMillis();
QueryResult qr = execute(columns, source, constraint, orderings,
offset, limit, 2);
- if (log.isDebugEnabled()) {
- time = System.currentTimeMillis() - time;
- log.debug("SQL2 QUERY execute took " + time + " ms.");
- }
+ log.debug("SQL2 QUERY execute took {} ms.", System.currentTimeMillis()
+ - time);
return qr;
}
@@ -177,10 +176,9 @@ public class QueryEngine {
long limit, int printIndentation) throws RepositoryException {
// Swap the join sources to normalize all outer joins to left
if (JCR_JOIN_TYPE_RIGHT_OUTER.equalsIgnoreCase(join.getJoinType())) {
- if (log.isDebugEnabled()) {
- log.debug(genString(printIndentation)
- + "SQL2 RIGHT OUTER JOIN transformed to LEFT OUTER JOIN.");
- }
+ log.debug(
+ "{} SQL2 RIGHT OUTER JOIN transformed to LEFT OUTER JOIN.",
+ genString(printIndentation));
Join betterJoin = qomFactory.join(join.getRight(), join.getLeft(),
JCR_JOIN_TYPE_LEFT_OUTER, join.getJoinCondition());
return execute(columns, betterJoin, constraint, orderings, offset,
@@ -196,9 +194,64 @@ public class QueryEngine {
logQueryAnalysis(csInfo, printIndentation);
- long timeJoinLeftSide = System.currentTimeMillis();
+ boolean isOuterJoin = JCR_JOIN_TYPE_LEFT_OUTER.equalsIgnoreCase(join
+ .getJoinType());
+ QueryResult result = execute(merger, csInfo, isOuterJoin,
+ printIndentation);
+
+ long sort = System.currentTimeMillis();
+ QueryResult sortedResult = sort(result, orderings, evaluator, offset,
+ limit);
+ log.debug(" {} SQL2 SORT took {} ms.", genString(printIndentation),
+ System.currentTimeMillis() - sort);
+ return sortedResult;
+ }
+
+ protected QueryResult execute(JoinMerger merger,
+ ConstraintSplitInfo csInfo, boolean isOuterJoin,
+ int printIndentation) throws RepositoryException {
+
Comparator<Row> leftCo = new RowPathComparator(
merger.getLeftSelectors());
+ long timeJoinLeftSide = System.currentTimeMillis();
+
+ if (csInfo.isMultiple()) {
+ log.debug("{} SQL2 JOIN execute: there are multiple inner splits.",
+ genString(printIndentation));
+
+ // first branch
+ long bTime = System.currentTimeMillis();
+ QueryResult branch1 = execute(merger,
+ csInfo.getLeftInnerConstraints(), isOuterJoin,
+ printIndentation + printIndentStep);
+ Set<Row> allRows = new TreeSet<Row>(new RowPathComparator(
+ Arrays.asList(merger.getSelectorNames())));
+ RowIterator ri1 = branch1.getRows();
+ while (ri1.hasNext()) {
+ Row r = ri1.nextRow();
+ allRows.add(r);
+ }
+ log.debug("{} SQL2 JOIN executed first branch, took {} ms.",
+ genString(printIndentation), System.currentTimeMillis()
+ - bTime);
+
+ // second branch
+ bTime = System.currentTimeMillis();
+ QueryResult branch2 = execute(merger,
+ csInfo.getRightInnerConstraints(), isOuterJoin,
+ printIndentation + printIndentStep);
+ RowIterator ri2 = branch2.getRows();
+ while (ri2.hasNext()) {
+ Row r = ri2.nextRow();
+ allRows.add(r);
+ }
+ log.debug("{} SQL2 JOIN executed second branch, took {} ms.",
+ genString(printIndentation), System.currentTimeMillis()
+ - bTime);
+ return new SimpleQueryResult(merger.getColumnNames(),
+ merger.getSelectorNames(), new RowIteratorAdapter(allRows));
+ }
+
Set<Row> leftRows = buildLeftRowsJoin(csInfo, leftCo, printIndentation
+ printIndentStep);
if (log.isDebugEnabled()) {
@@ -212,13 +265,15 @@ public class QueryEngine {
// - rightConstraints selects just the 'ON' constraints
// - csInfo has the 'WHERE' constraints
//
- // So, in the case of an OUTER JOIN we'll run 2 queries, one with 'ON'
+ // So, in the case of an OUTER JOIN we'll run 2 queries, one with
+ // 'ON'
// and one with 'ON' + 'WHERE' conditions
// this way, at merge time in case of an outer join we can tell if
// it's a 'null' row, or a bad row -> one that must not be returned.
// This way at the end we'll have:
// - rightRowsSet containing the 'ON' dataset
- // - excludingOuterJoinRowsSet: the 'ON' + 'WHERE' condition dataset, or
+ // - excludingOuterJoinRowsSet: the 'ON' + 'WHERE' condition
+ // dataset, or
// NULL if there is no 'WHERE' condition
long timeJoinRightSide = System.currentTimeMillis();
@@ -227,11 +282,8 @@ public class QueryEngine {
Comparator<Row> rightCo = new RowPathComparator(
merger.getRightSelectors());
- boolean isOuterJoin = JCR_JOIN_TYPE_LEFT_OUTER.equalsIgnoreCase(join
- .getJoinType());
-
- Set<Row> rightRows = buildRightRowsJoin(csInfo, rightConstraints, isOuterJoin,
- rightCo, printIndentation + printIndentStep);
+ Set<Row> rightRows = buildRightRowsJoin(csInfo, rightConstraints,
+ isOuterJoin, rightCo, printIndentation + printIndentStep);
// this has to be initialized as null
Set<Row> excludingOuterJoinRowsSet = null;
@@ -247,22 +299,11 @@ public class QueryEngine {
+ "SQL2 JOIN RIGHT SIDE took " + timeJoinRightSide
+ " ms. fetched " + rightRows.size() + " rows.");
}
-
- long timeMergeAndSort = System.currentTimeMillis();
-
// merge left with right datasets
- QueryResult result = merger.merge(new RowIteratorAdapter(leftRows),
+ return merger.merge(new RowIteratorAdapter(leftRows),
new RowIteratorAdapter(rightRows), excludingOuterJoinRowsSet,
rightCo);
- QueryResult sortedResult = sort(result, orderings, evaluator, offset,
- limit);
- if (log.isDebugEnabled()) {
- timeMergeAndSort = System.currentTimeMillis() - timeMergeAndSort;
- log.debug(genString(printIndentation)
- + "SQL2 JOIN MERGE and SORT took " + timeMergeAndSort
- + " ms.");
- }
- return sortedResult;
+
}
private Set<Row> buildLeftRowsJoin(ConstraintSplitInfo csi,
@@ -275,19 +316,13 @@ public class QueryEngine {
+ "SQL2 JOIN LEFT SIDE there are multiple inner splits.");
}
Set<Row> leftRows = new TreeSet<Row>(comparator);
- if (csi.getLeftInnerConstraints().isHasLeftConstraints()) {
- leftRows.addAll(buildLeftRowsJoin(
- csi.getLeftInnerConstraints(), comparator,
- printIndentation + printIndentStep));
- }
- if (csi.getRightInnerConstraints().isHasLeftConstraints()) {
- leftRows.addAll(buildLeftRowsJoin(
- csi.getRightInnerConstraints(), comparator,
- printIndentation + printIndentStep));
- }
+ leftRows.addAll(buildLeftRowsJoin(csi.getLeftInnerConstraints(),
+ comparator, printIndentation + printIndentStep));
+ leftRows.addAll(buildLeftRowsJoin(csi.getRightInnerConstraints(),
+ comparator, printIndentation + printIndentStep));
return leftRows;
}
-
+
Set<Row> leftRows = new TreeSet<Row>(comparator);
QueryResult leftResult = execute(null, csi.getSource().getLeft(),
csi.getLeftConstraint(), null, 0, -1, printIndentation);
@@ -321,14 +356,12 @@ public class QueryEngine {
+ "SQL2 JOIN RIGHT SIDE there are multiple inner splits.");
}
Set<Row> rightRows = new TreeSet<Row>(comparator);
- rightRows.addAll(buildRightRowsJoin(
- csi.getLeftInnerConstraints(), rightConstraints,
- ignoreWhereConstraints, comparator, printIndentation
- + printIndentStep));
- rightRows.addAll(buildRightRowsJoin(
- csi.getRightInnerConstraints(), rightConstraints,
- ignoreWhereConstraints, comparator, printIndentation
- + printIndentStep));
+ rightRows.addAll(buildRightRowsJoin(csi.getLeftInnerConstraints(),
+ rightConstraints, ignoreWhereConstraints, comparator,
+ printIndentation + printIndentStep));
+ rightRows.addAll(buildRightRowsJoin(csi.getRightInnerConstraints(),
+ rightConstraints, ignoreWhereConstraints, comparator,
+ printIndentation + printIndentStep));
return rightRows;
}
@@ -462,25 +495,24 @@ public class QueryEngine {
if (log.isDebugEnabled()) {
time = System.currentTimeMillis() - time;
log.debug(genString(printIndentation) + "SQL2 SELECT took "
- + time + " ms. selector: " + selector
- + ", columns: " + Arrays.toString(columnNames)
- + ", constraint: " + constraint);
+ + time + " ms. selector: " + selector + ", columns: "
+ + Arrays.toString(columnNames) + ", constraint: "
+ + constraint);
}
}
}
- private Map<String, PropertyValue> getColumnMap(
- Column[] columns, Map<String, NodeType> selectors)
- throws RepositoryException {
- Map<String, PropertyValue> map =
- new LinkedHashMap<String, PropertyValue>();
+ private Map<String, PropertyValue> getColumnMap(Column[] columns,
+ Map<String, NodeType> selectors) throws RepositoryException {
+ Map<String, PropertyValue> map = new LinkedHashMap<String, PropertyValue>();
if (columns != null && columns.length > 0) {
for (int i = 0; i < columns.length; i++) {
String name = columns[i].getColumnName();
if (name != null) {
- map.put(name, qomFactory.propertyValue(
- columns[i].getSelectorName(),
- columns[i].getPropertyName()));
+ map.put(name,
+ qomFactory.propertyValue(
+ columns[i].getSelectorName(),
+ columns[i].getPropertyName()));
} else {
String selector = columns[i].getSelectorName();
map.putAll(getColumnMap(selector, selectors.get(selector)));
@@ -488,17 +520,15 @@ public class QueryEngine {
}
} else {
for (Map.Entry<String, NodeType> selector : selectors.entrySet()) {
- map.putAll(getColumnMap(
- selector.getKey(), selector.getValue()));
+ map.putAll(getColumnMap(selector.getKey(), selector.getValue()));
}
}
return map;
}
- private Map<String, PropertyValue> getColumnMap(
- String selector, NodeType type) throws RepositoryException {
- Map<String, PropertyValue> map =
- new LinkedHashMap<String, PropertyValue>();
+ private Map<String, PropertyValue> getColumnMap(String selector,
+ NodeType type) throws RepositoryException {
+ Map<String, PropertyValue> map = new LinkedHashMap<String, PropertyValue>();
for (PropertyDefinition definition : type.getPropertyDefinitions()) {
String name = definition.getName();
if (!definition.isMultiple() && !"*".equals(name)) {
@@ -514,8 +544,8 @@ public class QueryEngine {
throws RepositoryException {
if (source instanceof Selector) {
Selector selector = (Selector) source;
- return Collections.singletonMap(
- selector.getSelectorName(), getNodeType(selector));
+ return Collections.singletonMap(selector.getSelectorName(),
+ getNodeType(selector));
} else if (source instanceof Join) {
Join join = (Join) source;
Map<String, NodeType> map = new LinkedHashMap<String, NodeType>();
@@ -538,23 +568,28 @@ public class QueryEngine {
}
/**
- * Sorts the given query results according to the given QOM orderings.
- * If one or more orderings have been specified, this method will iterate
+ * Sorts the given query results according to the given QOM orderings. If
+ * one or more orderings have been specified, this method will iterate
* through the entire original result set, order the collected rows, and
* return a new result set based on the sorted collection of rows.
- *
- * @param result original query results
- * @param orderings QOM orderings
- * @param offset result offset
- * @param limit result limit
+ *
+ * @param result
+ * original query results
+ * @param orderings
+ * QOM orderings
+ * @param offset
+ * result offset
+ * @param limit
+ * result limit
* @return sorted query results
- * @throws RepositoryException if the results can not be sorted
+ * @throws RepositoryException
+ * if the results can not be sorted
*/
protected static QueryResult sort(QueryResult result,
final Ordering[] orderings, OperandEvaluator evaluator,
long offset, long limit) throws RepositoryException {
- if ((orderings != null && orderings.length > 0)
- || offset != 0 || limit >= 0) {
+ if ((orderings != null && orderings.length > 0) || offset != 0
+ || limit >= 0) {
List<Row> rows = new ArrayList<Row>();
RowIterator iterator = result.getRows();
@@ -575,9 +610,8 @@ public class QueryEngine {
rows = rows.subList(0, (int) Math.min(limit, size));
}
- return new SimpleQueryResult(
- result.getColumnNames(), result.getSelectorNames(),
- new RowIteratorAdapter(rows));
+ return new SimpleQueryResult(result.getColumnNames(),
+ result.getSelectorNames(), new RowIteratorAdapter(rows));
} else {
return result;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/RowPathComparator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/RowPathComparator.java?rev=1143477&r1=1143476&r2=1143477&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/RowPathComparator.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/RowPathComparator.java Wed Jul 6 16:03:02 2011
@@ -16,8 +16,8 @@
*/
package org.apache.jackrabbit.core.query.lucene.join;
+import java.util.Collection;
import java.util.Comparator;
-import java.util.Set;
import javax.jcr.RepositoryException;
import javax.jcr.query.Row;
@@ -33,9 +33,9 @@ public class RowPathComparator implement
* a superset of selectors, in cases where there are joins and such, the
* possibility that a selector node does not exist in a row can happen
*/
- private Set<String> selectors = null;
+ private Collection<String> selectors = null;
- public RowPathComparator(Set<String> selectors) {
+ public RowPathComparator(Collection<String> selectors) {
this.selectors = selectors;
}
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=1143477&r1=1143476&r2=1143477&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 Wed Jul 6 16:03:02 2011
@@ -29,40 +29,52 @@ public class JoinTest extends AbstractQu
private Node node;
- private Node n1;
-
- private Node n2;
-
@Override
protected void setUp() throws Exception {
super.setUp();
node = testRootNode.addNode("jointest", "nt:unstructured");
- n1 = node.addNode("node1", "nt:unstructured");
- n1.addMixin(NodeType.MIX_REFERENCEABLE);
- n1.setProperty("type", "child");
- n1.setProperty("testJoinWithOR4", "testJoinWithOR4");
-
- n2 = node.addNode("node2", "nt:unstructured");
- n2.addMixin(NodeType.MIX_REFERENCEABLE);
- n2.setProperty("type", "child");
+ Node n1a = node.addNode("n1a", "nt:unstructured");
+ n1a.addMixin(NodeType.MIX_REFERENCEABLE);
+ n1a.setProperty("type", "parent");
+
+ Node n1b = node.addNode("n1b", "nt:unstructured");
+ n1b.addMixin(NodeType.MIX_REFERENCEABLE);
+ n1b.setProperty("type", "parent");
+ n1b.setProperty("testJoinWithOR4", "testJoinWithOR4");
+
+ Node n1c = node.addNode("n1c", "nt:unstructured");
+ n1c.addMixin(NodeType.MIX_REFERENCEABLE);
+ n1c.setProperty("type", "parent");
Node n3 = node.addNode("node3", "nt:unstructured");
n3.addMixin(NodeType.MIX_REFERENCEABLE);
- n3.setProperty("testref",
- new String[] { n1.getIdentifier(), n2.getIdentifier() },
+ n3.setProperty("testref", new String[] { n1a.getIdentifier() },
PropertyType.REFERENCE);
- n3.setProperty("type", "parent");
+ n3.setProperty("type", "child");
n3.setProperty("testJoinWithOR4", "testJoinWithOR4");
+ Node n4 = node.addNode("node4", "nt:unstructured");
+ n4.addMixin(NodeType.MIX_REFERENCEABLE);
+ n4.setProperty("testref", new String[] { n1b.getIdentifier() },
+ PropertyType.REFERENCE);
+ n4.setProperty("type", "child");
+
+ Node n5 = node.addNode("node5", "nt:unstructured");
+ n5.addMixin(NodeType.MIX_REFERENCEABLE);
+ n5.setProperty("testref", new String[] { n1c.getIdentifier() },
+ PropertyType.REFERENCE);
+ n5.setProperty("type", "child");
+
Node parent2 = testRootNode
.addNode("jointest_other", "nt:unstructured");
parent2.setProperty("p", "abc");
- Node p2n1 = parent2.addNode("node4", "nt:unstructured");
+ Node p2n1 = parent2.addNode("p2n1", "nt:unstructured");
p2n1.setProperty("p", "abc");
- parent2.addNode("node5", "nt:unstructured");
+ Node p2n2 = parent2.addNode("p2n2", "nt:unstructured");
+ p2n2.setProperty("p", "xyz");
testRootNode.getSession().save();
}
@@ -82,7 +94,7 @@ public class JoinTest extends AbstractQu
String join = "SELECT a.*, b.*"
+ " FROM [nt:unstructured] AS a"
+ " INNER JOIN [nt:unstructured] AS b ON a.[jcr:uuid] = b.testref";
- checkResult(qm.createQuery(join, Query.JCR_SQL2).execute(), 2);
+ checkResult(qm.createQuery(join, Query.JCR_SQL2).execute(), 3);
}
/**
@@ -95,10 +107,7 @@ public class JoinTest extends AbstractQu
+ " FROM [nt:unstructured] AS a"
+ " INNER JOIN [nt:unstructured] 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);
+ checkResult(qm.createQuery(join, Query.JCR_SQL2).execute(), 3);
}
public void testJoinWithOR2() throws Exception {
@@ -108,10 +117,8 @@ public class JoinTest extends AbstractQu
join.append(" INNER JOIN [nt:unstructured] AS b ON ISCHILDNODE(b, a) ");
join.append(" WHERE ");
join.append(" a.[p] = 'abc' OR b.[p] = 'abc' ");
-
- Query q = qm.createQuery(join.toString(), Query.JCR_SQL2);
- QueryResult result = q.execute();
- checkResult(result, 2);
+ checkResult(qm.createQuery(join.toString(), Query.JCR_SQL2).execute(),
+ 3);
}
public void testJoinWithOR3() throws Exception {
@@ -121,18 +128,16 @@ public class JoinTest extends AbstractQu
join.append(" WHERE ");
join.append(" ( CONTAINS(b.*, 'abc' ) OR CONTAINS(a.*, 'abc') ) ");
join.append(" AND ");
- join.append(" NAME(b) = 'node4' ");
-
- Query q = qm.createQuery(join.toString(), Query.JCR_SQL2);
- QueryResult result = q.execute();
- checkResult(result, 1);
+ join.append(" NAME(b) = 'p2n2' ");
+ checkResult(qm.createQuery(join.toString(), Query.JCR_SQL2).execute(),
+ 1);
}
public void testJoinWithOR4() throws Exception {
StringBuilder join = new StringBuilder(
- "SELECT a.*, b.* FROM [nt:unstructured] AS a");
- join.append(" INNER JOIN [nt:unstructured] AS b ON a.[jcr:uuid] = b.testref ");
+ "SELECT a.* FROM [nt:unstructured] AS a");
+ join.append(" INNER JOIN [nt:unstructured] AS b ON b.[jcr:uuid] = a.testref ");
join.append(" WHERE ");
join.append(" a.type = 'child' ");
join.append(" AND (");
@@ -149,46 +154,17 @@ public class JoinTest extends AbstractQu
}
- /**
- * 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'))
+ public void testJoinWithOR5() throws Exception {
StringBuilder join = new StringBuilder(
- "SELECT a.*, b.* FROM [nt:unstructured] AS a");
- join.append(" INNER JOIN [nt:unstructured] AS b ON a.[jcr:uuid] = b.testref ");
+ "SELECT a.* FROM [nt:unstructured] AS a");
+ join.append(" INNER JOIN [nt:unstructured] AS b ON b.[jcr:uuid] = a.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') ");
+ join.append(" a.type = 'child' AND CONTAINS(a.*, 'testJoinWithOR4') ");
+ join.append(" OR ");
+ join.append(" b.type = 'parent' AND CONTAINS(b.*, 'testJoinWithOR4') ");
- Query q = qm.createQuery(join.toString(), Query.JCR_SQL2);
- QueryResult result = q.execute();
- checkResult(result, 2);
+ checkResult(qm.createQuery(join.toString(), Query.JCR_SQL2).execute(),
+ 2);
}
}