You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2014/02/19 14:50:49 UTC
svn commit: r1569740 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/api/
main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
main/java/org/apache/jackrabbit/oak/query/
main/java/org/apache/jackrabbit/oak/q...
Author: thomasm
Date: Wed Feb 19 13:50:48 2014
New Revision: 1569740
URL: http://svn.apache.org/r1569740
Log:
OAK-1372 XPath queries with both path and property restrictions are slow
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/ExecutionPlan.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/JoinExecutionPlan.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/Permutations.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/SelectorExecutionPlan.java
- copied, changed from r1568919, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SelectorExecutionPlan.java
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SelectorExecutionPlan.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeJoinConditionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeJoinConditionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/EquiJoinConditionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchScoreImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinConditionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeLocalNameImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyExistenceImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyInexistenceImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyValueImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeJoinConditionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java Wed Feb 19 13:50:48 2014
@@ -29,6 +29,21 @@ import java.util.Set;
* What query languages are supported depends on the registered query parsers.
*/
public interface QueryEngine {
+
+ /**
+ * Empty set of variables bindings. Useful as an argument to
+ * {@link #executeQuery(String, String, long, long, Map, Map)} when
+ * there are no variables in a query.
+ */
+ Map<String, PropertyValue> NO_BINDINGS = emptyMap();
+
+ /**
+ * Empty set of namespace prefix mappings. Useful as an argument to
+ * {@link #getBindVariableNames(String, String, Map)} and
+ * {@link #executeQuery(String, String, long, long, Map, Map)} when
+ * there are no local namespace mappings.
+ */
+ Map<String, String> NO_MAPPINGS = emptyMap();
/**
* Get the set of supported query languages.
@@ -68,19 +83,4 @@ public interface QueryEngine {
Map<String, ? extends PropertyValue> bindings,
Map<String, String> mappings) throws ParseException;
- /**
- * Empty set of variables bindings. Useful as an argument to
- * {@link #executeQuery(String, String, long, long, Map, Map)} when
- * there are no variables in a query.
- */
- Map<String, PropertyValue> NO_BINDINGS = emptyMap();
-
- /**
- * Empty set of namespace prefix mappings. Useful as an argument to
- * {@link #getBindVariableNames(String, String, Map)} and
- * {@link #executeQuery(String, String, long, long, Map, Map)} when
- * there are no local namespace mappings.
- */
- Map<String, String> NO_MAPPINGS = emptyMap();
-
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java Wed Feb 19 13:50:48 2014
@@ -150,7 +150,7 @@ public class UniqueEntryStoreStrategy im
if (ec != null) {
return ec.getValue(Type.LONG);
}
- count = index.getChildNodeCount(max);
+ count = 1 + index.getChildNodeCount(max);
// "is not null" queries typically read more data
count *= 10;
} else if (values.size() == 1) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Wed Feb 19 13:50:48 2014
@@ -41,8 +41,6 @@ public interface Query {
void setTraversalEnabled(boolean traversalEnabled);
- void prepare();
-
Result executeQuery();
List<String> getBindVariableNames();
@@ -63,17 +61,33 @@ public interface Query {
void setMeasure(boolean measure);
- void init();
-
void setOrderings(OrderingImpl[] orderings);
/**
+ * Initialize the query. This will 'wire' selectors into constraints bind
+ * variables into expressions. It will also simplify expressions if
+ * possible, but will not prepare the query.
+ */
+ void init();
+
+ /**
+ * Prepare the query. The cost is estimated and the execution plan is
+ * decided here.
+ */
+ void prepare();
+
+ /**
* Get the query plan. The query must already be prepared.
*
* @return the query plan
*/
String getPlan();
-
+
+ /**
+ * Get the estimated cost.
+ *
+ * @return the estimated cost
+ */
double getEstimatedCost();
Tree getTree(String path);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Wed Feb 19 13:50:48 2014
@@ -61,6 +61,8 @@ import org.apache.jackrabbit.oak.query.a
import org.apache.jackrabbit.oak.query.ast.UpperCaseImpl;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.query.index.TraversingIndex;
+import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
+import org.apache.jackrabbit.oak.query.plan.SelectorExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
@@ -317,7 +319,6 @@ public class QueryImpl implements Query
constraint = constraint.simplify();
}
source.setQueryConstraint(constraint);
- source.init(this);
for (ColumnImpl column : columns) {
column.bindSelector(source);
}
@@ -446,36 +447,42 @@ public class QueryImpl implements Query
List<SourceImpl> sources = source.getInnerJoinSelectors();
List<JoinConditionImpl> conditions = source.getInnerJoinConditions();
-// if (sources.size() <= 1) {
+ if (sources.size() <= 1) {
// simple case (no join)
- estimatedCost = source.prepare();
-// return;
-// }
-
-// if (sources.size() < 6) {
-// // TODO iterate over all permutations
-// }
-//
-// // use a greedy algorithm
-// SourceImpl result = null;
-// Set<SourceImpl> available = new HashSet<SourceImpl>();
-// while (sources.size() > 0) {
-// int bestIndex = 0;
-// double bestCost = Double.POSITIVE_INFINITY;
-// for (int i = 0; i < sources.size(); i++) {
-// SourceImpl source = buildJoin(result, sources.get(i).createClone(), conditions);
-// double cost = source.prepare();
-// if (cost <= bestCost) {
-// bestCost = cost;
-// bestIndex = i;
-// }
-// }
-// SourceImpl s = sources.get(bestIndex).createClone();
-// available.add(s);
-// sources.remove(bestIndex);
-// result = buildJoin(result, s, conditions);
-// }
-// source = result;
+ estimatedCost = source.prepare().getEstimatedCost();
+ return;
+ }
+
+ // use a greedy algorithm
+ SourceImpl result = null;
+ Set<SourceImpl> available = new HashSet<SourceImpl>();
+ while (sources.size() > 0) {
+ int bestIndex = 0;
+ double bestCost = Double.POSITIVE_INFINITY;
+ ExecutionPlan bestPlan = null;
+ SourceImpl best = null;
+ for (int i = 0; i < sources.size(); i++) {
+ SourceImpl test = buildJoin(result, sources.get(i), conditions);
+ if (test == null) {
+ // no join condition
+ continue;
+ }
+ ExecutionPlan testPlan = test.prepare();
+ double cost = testPlan.getEstimatedCost();
+ if (best == null || cost < bestCost) {
+ bestPlan = testPlan;
+ bestCost = cost;
+ bestIndex = i;
+ best = test;
+ }
+ test.unprepare();
+ }
+ available.add(sources.remove(bestIndex));
+ result = best;
+ best.prepare(bestPlan);
+ }
+ estimatedCost = result.prepare().getEstimatedCost();
+ source = result;
}
@@ -483,17 +490,22 @@ public class QueryImpl implements Query
if (result == null) {
return last;
}
- Set<SourceImpl> available = new HashSet<SourceImpl>();
- available.addAll(result.getInnerJoinSelectors());
- available.add(last);
+ List<SourceImpl> selectors = result.getInnerJoinSelectors();
+ Set<SourceImpl> oldSelectors = new HashSet<SourceImpl>();
+ oldSelectors.addAll(selectors);
+ Set<SourceImpl> newSelectors = new HashSet<SourceImpl>();
+ newSelectors.addAll(selectors);
+ newSelectors.add(last);
for (JoinConditionImpl j : conditions) {
- if (j.canEvaluate(available)) {
+ // only join conditions can now be evaluated,
+ // but couldn't be evaluated before
+ if (!j.canEvaluate(oldSelectors) && j.canEvaluate(newSelectors)) {
JoinImpl join = new JoinImpl(result, last, JoinType.INNER, j);
return join;
}
}
- // this is an internal error
- throw new IllegalArgumentException("No join condition was found");
+ // no join condition was found
+ return null;
}
/**
@@ -681,7 +693,6 @@ public class QueryImpl implements Query
}
}
-
if (traversalEnabled) {
QueryIndex traversal = new TraversingIndex();
double cost = traversal.getCost(filter, rootState);
@@ -690,12 +701,7 @@ public class QueryImpl implements Query
best = traversal;
}
}
- SelectorExecutionPlan plan = new SelectorExecutionPlan();
- plan.filter = filter;
- plan.estimatedCost = bestCost;
- plan.index = best;
- plan.selector = filter.getSelector();
- return plan;
+ return new SelectorExecutionPlan(filter.getSelector(), best, bestCost);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java Wed Feb 19 13:50:48 2014
@@ -88,7 +88,7 @@ public class ChildNodeImpl extends Const
@Override
public void restrict(FilterImpl f) {
- if (selector == f.getSelector()) {
+ if (selector.equals(f.getSelector())) {
String path = normalizePath(parentPath);
f.restrictPath(path, Filter.PathRestriction.DIRECT_CHILDREN);
}
@@ -96,7 +96,7 @@ public class ChildNodeImpl extends Const
@Override
public void restrictPushDown(SelectorImpl s) {
- if (s == selector) {
+ if (s.equals(selector)) {
s.restrictSelector(this);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeJoinConditionImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeJoinConditionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeJoinConditionImpl.java Wed Feb 19 13:50:48 2014
@@ -66,25 +66,23 @@ public class ChildNodeJoinConditionImpl
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == parentSelector) {
+ if (f.getSelector().equals(parentSelector)) {
String c = childSelector.currentPath();
- if (c == null && f.isPreparing() && childSelector.isPrepared()) {
+ if (c == null && f.isPreparing() && f.isPrepared(childSelector)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
- c = KNOWN_PATH;
- }
- if (c != null) {
+ f.restrictPath(KNOWN_PARENT_PATH, Filter.PathRestriction.EXACT);
+ } else if (c != null) {
f.restrictPath(PathUtils.getParentPath(c), Filter.PathRestriction.EXACT);
}
}
- if (f.getSelector() == childSelector) {
+ if (f.getSelector().equals(childSelector)) {
String p = parentSelector.currentPath();
- if (p == null && f.isPreparing() && parentSelector.isPrepared()) {
+ if (p == null && f.isPreparing() && f.isPrepared(parentSelector)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
- p = KNOWN_PATH;
- }
- if (p != null) {
+ f.restrictPath(KNOWN_PATH, Filter.PathRestriction.DIRECT_CHILDREN);
+ } else if (p != null) {
f.restrictPath(p, Filter.PathRestriction.DIRECT_CHILDREN);
}
}
@@ -97,7 +95,7 @@ public class ChildNodeJoinConditionImpl
@Override
public boolean isParent(SourceImpl source) {
- return source == parentSelector;
+ return source.equals(parentSelector);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java Wed Feb 19 13:50:48 2014
@@ -85,7 +85,7 @@ public class DescendantNodeImpl extends
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
String path = normalizePath(ancestorPath);
f.restrictPath(path, Filter.PathRestriction.ALL_CHILDREN);
}
@@ -93,7 +93,7 @@ public class DescendantNodeImpl extends
@Override
public void restrictPushDown(SelectorImpl s) {
- if (s == selector) {
+ if (s.equals(selector)) {
s.restrictSelector(this);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeJoinConditionImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeJoinConditionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeJoinConditionImpl.java Wed Feb 19 13:50:48 2014
@@ -66,25 +66,23 @@ public class DescendantNodeJoinCondition
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == ancestorSelector) {
+ if (f.getSelector().equals(ancestorSelector)) {
String d = descendantSelector.currentPath();
- if (d == null && f.isPreparing() && descendantSelector.isPrepared()) {
+ if (d == null && f.isPreparing() && f.isPrepared(descendantSelector)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
- d = KNOWN_PATH;
- }
- if (d != null) {
+ f.restrictPath(KNOWN_PARENT_PATH, Filter.PathRestriction.PARENT);
+ } else if (d != null) {
f.restrictPath(PathUtils.getParentPath(d), Filter.PathRestriction.PARENT);
}
}
- if (f.getSelector() == descendantSelector) {
+ if (f.getSelector().equals(descendantSelector)) {
String a = ancestorSelector.currentPath();
- if (a == null && f.isPreparing() && ancestorSelector.isPrepared()) {
+ if (a == null && f.isPreparing() && f.isPrepared(ancestorSelector)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
- a = KNOWN_PATH;
- }
- if (a != null) {
+ f.restrictPath(KNOWN_PATH, Filter.PathRestriction.ALL_CHILDREN);
+ } else if (a != null) {
f.restrictPath(a, Filter.PathRestriction.ALL_CHILDREN);
}
}
@@ -97,7 +95,7 @@ public class DescendantNodeJoinCondition
@Override
public boolean isParent(SourceImpl source) {
- return source == ancestorSelector;
+ return source.equals(ancestorSelector);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/EquiJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/EquiJoinConditionImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/EquiJoinConditionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/EquiJoinConditionImpl.java Wed Feb 19 13:50:48 2014
@@ -93,9 +93,9 @@ public class EquiJoinConditionImpl exten
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == selector1) {
+ if (f.getSelector().equals(selector1)) {
PropertyValue p2 = selector2.currentProperty(property2Name);
- if (p2 == null && f.isPreparing() && selector2.isPrepared()) {
+ if (p2 == null && f.isPreparing() && f.isPrepared(selector2)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
p2 = PropertyValues.newString(KNOWN_VALUE);
@@ -110,9 +110,9 @@ public class EquiJoinConditionImpl exten
String p1n = normalizePropertyName(property1Name);
f.restrictProperty(p1n, Operator.EQUAL, p2);
}
- if (f.getSelector() == selector2) {
+ if (f.getSelector().equals(selector2)) {
PropertyValue p1 = selector1.currentProperty(property1Name);
- if (p1 == null && f.isPreparing() && selector1.isPrepared()) {
+ if (p1 == null && f.isPreparing() && f.isPrepared(selector1)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
p1 = PropertyValues.newString(KNOWN_VALUE);
@@ -132,11 +132,11 @@ public class EquiJoinConditionImpl exten
@Override
public void restrictPushDown(SelectorImpl s) {
// both properties may not be null
- if (s == selector1) {
+ if (s.equals(selector1)) {
PropertyExistenceImpl ex = new PropertyExistenceImpl(s.getSelectorName(), property1Name);
ex.bindSelector(s);
s.restrictSelector(ex);
- } else if (s == selector2) {
+ } else if (s.equals(selector2)) {
PropertyExistenceImpl ex = new PropertyExistenceImpl(s.getSelectorName(), property2Name);
ex.bindSelector(s);
s.restrictSelector(ex);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java Wed Feb 19 13:50:48 2014
@@ -126,7 +126,7 @@ public class FullTextSearchImpl extends
@Override
public FullTextExpression getFullTextConstraint(SelectorImpl s) {
- if (s != selector) {
+ if (!s.equals(selector)) {
return null;
}
PropertyValue v = fullTextSearchExpression.currentValue();
@@ -230,7 +230,7 @@ public class FullTextSearchImpl extends
@Override
public void restrict(FilterImpl f) {
if (propertyName != null) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
String pn = normalizePropertyName(propertyName);
f.restrictProperty(pn, Operator.NOT_EQUAL, null);
}
@@ -240,7 +240,7 @@ public class FullTextSearchImpl extends
@Override
public void restrictPushDown(SelectorImpl s) {
- if (s == selector) {
+ if (s.equals(selector)) {
selector.restrictSelector(this);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchScoreImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchScoreImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchScoreImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchScoreImpl.java Wed Feb 19 13:50:48 2014
@@ -77,7 +77,7 @@ public class FullTextSearchScoreImpl ext
@Override
public void restrict(FilterImpl f, Operator operator, PropertyValue v) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
if (operator == Operator.NOT_EQUAL && v != null) {
// not supported
return;
@@ -93,7 +93,7 @@ public class FullTextSearchScoreImpl ext
@Override
public boolean canRestrictSelector(SelectorImpl s) {
- return s == selector;
+ return s.equals(selector);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinConditionImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinConditionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinConditionImpl.java Wed Feb 19 13:50:48 2014
@@ -23,10 +23,20 @@ import org.apache.jackrabbit.oak.query.i
public abstract class JoinConditionImpl extends AstElement {
/**
- * A path with 6 elements, which is the expected average for a join.
+ * The prefix for known paths.
*/
- protected static final String KNOWN_PATH = "/path/from/the/join/selector";
+ public static final String SPECIAL_PATH_PREFIX = "//";
+
+ /**
+ * A path for a join.
+ */
+ protected static final String KNOWN_PATH = "//path/from/join";
+ /**
+ * The parent path of the joined selector
+ */
+ protected static final String KNOWN_PARENT_PATH = "//parent/of/join";
+
protected static final String KNOWN_VALUE = "valueFromTheJoinSelector";
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java Wed Feb 19 13:50:48 2014
@@ -16,7 +16,8 @@ package org.apache.jackrabbit.oak.query.
import java.util.ArrayList;
import java.util.List;
-import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
+import org.apache.jackrabbit.oak.query.plan.JoinExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -36,6 +37,8 @@ public class JoinImpl extends SourceImpl
private boolean foundJoinedRow;
private boolean end;
private NodeState rootState;
+
+ private JoinExecutionPlan plan;
public JoinImpl(SourceImpl left, SourceImpl right, JoinType joinType,
JoinConditionImpl joinCondition) {
@@ -45,14 +48,6 @@ public class JoinImpl extends SourceImpl
this.joinCondition = joinCondition;
}
- private JoinImpl(JoinImpl clone) {
- this.left = clone.left;
- this.right = clone.right;
- this.joinType = clone.joinType;
- this.joinCondition = clone.joinCondition;
- this.query = clone.query;
- }
-
@Override
public ArrayList<SourceImpl> getInnerJoinSelectors() {
ArrayList<SourceImpl> list = new ArrayList<SourceImpl>();
@@ -63,11 +58,9 @@ public class JoinImpl extends SourceImpl
break;
case LEFT_OUTER:
list.addAll(left.getInnerJoinSelectors());
- list.add(right);
break;
case RIGHT_OUTER:
list.addAll(right.getInnerJoinSelectors());
- list.add(left);
}
return list;
}
@@ -85,11 +78,6 @@ public class JoinImpl extends SourceImpl
return set;
}
- @Override
- public JoinImpl createClone() {
- return new JoinImpl(this);
- }
-
public JoinConditionImpl getJoinCondition() {
return joinCondition;
}
@@ -125,9 +113,15 @@ public class JoinImpl extends SourceImpl
return left + " " + joinType +
" " + right + " on " + joinCondition;
}
-
+
@Override
- public void init(QueryImpl query) {
+ public void unprepare() {
+ left.unprepare();
+ right.unprepare();
+ plan = null;
+ }
+
+ private void applyJoinConditions() {
switch (joinType) {
case INNER:
left.addJoinCondition(joinCondition, false);
@@ -153,26 +147,38 @@ public class JoinImpl extends SourceImpl
right.addJoinCondition(joinCondition, true);
break;
}
- setParent(joinCondition);
- right.init(query);
- left.init(query);
}
@Override
- protected void setParent(JoinConditionImpl joinCondition) {
- left.setParent(joinCondition);
- right.setParent(joinCondition);
+ public void prepare(ExecutionPlan p) {
+ if (!(p instanceof JoinExecutionPlan)) {
+ throw new IllegalArgumentException("Not a join plan");
+ }
+ JoinExecutionPlan joinPlan = (JoinExecutionPlan) p;
+ if (joinPlan.getJoin() != this) {
+ throw new IllegalArgumentException("Not a plan for this join");
+ }
+ this.plan = joinPlan;
+ applyJoinConditions();
+ left.prepare(joinPlan.getLeftPlan());
+ right.prepare(joinPlan.getRightPlan());
}
@Override
- public double prepare() {
+ public ExecutionPlan prepare() {
+ if (plan != null) {
+ return plan;
+ }
+ applyJoinConditions();
// the estimated cost is the cost of the left selector,
// plus twice the cost of the right selector (we expect
// two rows for the right selector for each node
// on the left selector)
- double cost = left.prepare();
- cost += 2 * right.prepare();
- return cost;
+ ExecutionPlan leftPlan = left.prepare();
+ ExecutionPlan rightPlan = right.prepare();
+ double cost = leftPlan.getEstimatedCost() + 2 * rightPlan.getEstimatedCost();
+ plan = new JoinExecutionPlan(this, leftPlan, rightPlan, cost);
+ return plan;
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeLocalNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeLocalNameImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeLocalNameImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeLocalNameImpl.java Wed Feb 19 13:50:48 2014
@@ -87,7 +87,7 @@ public class NodeLocalNameImpl extends D
@Override
public boolean canRestrictSelector(SelectorImpl s) {
- return s == selector;
+ return s.equals(selector);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java Wed Feb 19 13:50:48 2014
@@ -100,7 +100,7 @@ public class NodeNameImpl extends Dynami
@Override
public boolean canRestrictSelector(SelectorImpl s) {
- return s == selector;
+ return s.equals(selector);
}
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java Wed Feb 19 13:50:48 2014
@@ -210,7 +210,7 @@ public class OrImpl extends ConstraintIm
} else {
// exactly one selector: check if it's the right one
SelectorImpl s2 = set.iterator().next();
- if (s2 != s) {
+ if (!s2.equals(s)) {
// a different selector
return false;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyExistenceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyExistenceImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyExistenceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyExistenceImpl.java Wed Feb 19 13:50:48 2014
@@ -80,7 +80,7 @@ public class PropertyExistenceImpl exten
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
String pn = normalizePropertyName(propertyName);
f.restrictProperty(pn, Operator.NOT_EQUAL, null);
}
@@ -88,7 +88,7 @@ public class PropertyExistenceImpl exten
@Override
public void restrictPushDown(SelectorImpl s) {
- if (s == selector) {
+ if (s.equals(selector)) {
s.restrictSelector(this);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyInexistenceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyInexistenceImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyInexistenceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyInexistenceImpl.java Wed Feb 19 13:50:48 2014
@@ -134,7 +134,7 @@ public class PropertyInexistenceImpl ext
// because that would alter the result
return;
}
- if (s == selector) {
+ if (s.equals(selector)) {
s.restrictSelector(this);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyValueImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyValueImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/PropertyValueImpl.java Wed Feb 19 13:50:48 2014
@@ -26,9 +26,11 @@ import java.util.Set;
import javax.jcr.PropertyType;
import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.query.QueryImpl;
import org.apache.jackrabbit.oak.query.SQL2Parser;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.query.Filter.PathRestriction;
/**
* A property expression.
@@ -114,22 +116,28 @@ public class PropertyValueImpl extends D
@Override
public void restrict(FilterImpl f, Operator operator, PropertyValue v) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
if (operator == Operator.NOT_EQUAL && v != null) {
// not supported
return;
}
- String pn = normalizePropertyName(propertyName);
- f.restrictProperty(pn, operator, v);
- if (propertyType != PropertyType.UNDEFINED) {
- f.restrictPropertyType(pn, operator, propertyType);
+ String pn = normalizePropertyName(propertyName);
+ if (pn.equals(QueryImpl.JCR_PATH)) {
+ if (operator == Operator.EQUAL) {
+ f.restrictPath(v.getValue(Type.STRING), PathRestriction.EXACT);
+ }
+ } else {
+ f.restrictProperty(pn, operator, v);
+ if (propertyType != PropertyType.UNDEFINED) {
+ f.restrictPropertyType(pn, operator, propertyType);
+ }
}
}
}
@Override
public void restrictList(FilterImpl f, List<PropertyValue> list) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
String pn = normalizePropertyName(propertyName);
f.restrictPropertyAsList(pn, list);
}
@@ -137,7 +145,7 @@ public class PropertyValueImpl extends D
@Override
public boolean canRestrictSelector(SelectorImpl s) {
- return s == selector;
+ return s.equals(selector);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java Wed Feb 19 13:50:48 2014
@@ -77,7 +77,7 @@ public class SameNodeImpl extends Constr
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == selector) {
+ if (f.getSelector().equals(selector)) {
String p = normalizePath(path);
f.restrictPath(p, Filter.PathRestriction.EXACT);
}
@@ -85,7 +85,7 @@ public class SameNodeImpl extends Constr
@Override
public void restrictPushDown(SelectorImpl s) {
- if (s == selector) {
+ if (s.equals(selector)) {
s.restrictSelector(this);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeJoinConditionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeJoinConditionImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeJoinConditionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeJoinConditionImpl.java Wed Feb 19 13:50:48 2014
@@ -81,14 +81,13 @@ public class SameNodeJoinConditionImpl e
@Override
public void restrict(FilterImpl f) {
- if (f.getSelector() == selector1) {
+ if (f.getSelector().equals(selector1)) {
String p2 = selector2.currentPath();
- if (p2 == null && f.isPreparing() && selector2.isPrepared()) {
+ if (p2 == null && f.isPreparing() && f.isPrepared(selector2)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
- p2 = KNOWN_PATH;
- }
- if (p2 != null) {
+ f.restrictPath(KNOWN_PATH, Filter.PathRestriction.EXACT);
+ } else if (p2 != null) {
if (selector2Path.equals(".")) {
f.restrictPath(p2, Filter.PathRestriction.EXACT);
} else {
@@ -98,14 +97,13 @@ public class SameNodeJoinConditionImpl e
}
}
}
- if (f.getSelector() == selector2) {
+ if (f.getSelector().equals(selector2)) {
String p1 = selector1.currentPath();
- if (p1 == null && f.isPreparing() && selector1.isPrepared()) {
+ if (p1 == null && f.isPreparing() && f.isPrepared(selector1)) {
// during the prepare phase, if the selector is already
// prepared, then we would know the value
- p1 = KNOWN_PATH;
- }
- if (p1 != null) {
+ f.restrictPath(KNOWN_PATH, Filter.PathRestriction.EXACT);
+ } else if (p1 != null) {
if (selector2Path.equals(".")) {
f.restrictPath(p1, Filter.PathRestriction.EXACT);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Wed Feb 19 13:50:48 2014
@@ -43,9 +43,10 @@ import org.apache.jackrabbit.oak.api.Tre
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.query.QueryImpl;
-import org.apache.jackrabbit.oak.query.SelectorExecutionPlan;
import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
+import org.apache.jackrabbit.oak.query.plan.SelectorExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Cursor;
import org.apache.jackrabbit.oak.spi.query.Cursors;
import org.apache.jackrabbit.oak.spi.query.IndexRow;
@@ -131,6 +132,7 @@ public class SelectorImpl extends Source
* "select * from nt:base as a inner join nt:base as b on a.x =
* b.x", the join condition "a.x = b.x" is set for both selectors a and b,
* so both can check if the property x is set.
+ * The join conditions are added during the init phase.
*/
private ArrayList<JoinConditionImpl> allJoinConditions =
new ArrayList<JoinConditionImpl>();
@@ -177,41 +179,6 @@ public class SelectorImpl extends Source
this.mixinTypes = ImmutableSet.of();
}
}
-
- private SelectorImpl(SelectorImpl clone) {
- this.nodeType = clone.nodeType;
- this.selectorName = clone.selectorName;
- this.nodeTypeName = clone.nodeTypeName;
- this.matchesAllTypes = clone.matchesAllTypes;
- this.supertypes = clone.supertypes;
- this.primaryTypes = clone.primaryTypes;
- this.mixinTypes = clone.mixinTypes;
- this.query = clone.query;
- this.isParent = clone.isParent;
- this.outerJoinLeftHandSide = clone.outerJoinLeftHandSide;
- this.outerJoinRightHandSide = clone.outerJoinRightHandSide;
- this.allJoinConditions = clone.allJoinConditions;
- }
-
-
-// queryConstraint;
-// protected JoinConditionImpl joinCondition;
-// protected ArrayList<JoinConditionImpl> allJoinConditions =
-// new ArrayList<JoinConditionImpl>();
-// protected boolean join;
-// protected boolean outerJoinLeftHandSide;
-// protected boolean outerJoinRightHandSide;
-// protected boolean isParent;
-
- /**
- * Create a shallow clone of this instance.
- *
- * @return the clone
- */
- @Override
- public SelectorImpl createClone() {
- return new SelectorImpl(this);
- }
public String getSelectorName() {
return selectorName;
@@ -265,9 +232,30 @@ public class SelectorImpl extends Source
public boolean isPrepared() {
return plan != null;
}
-
+
@Override
- public double prepare() {
+ public void unprepare() {
+ plan = null;
+ selectorCondition = null;
+ isParent = false;
+ joinCondition = null;
+ allJoinConditions.clear();
+ }
+
+ @Override
+ public void prepare(ExecutionPlan p) {
+ if (!(p instanceof SelectorExecutionPlan)) {
+ throw new IllegalArgumentException("Not a selector plan");
+ }
+ SelectorExecutionPlan selectorPlan = (SelectorExecutionPlan) p;
+ if (selectorPlan.getSelector() != this) {
+ throw new IllegalArgumentException("Not a plan for this selector");
+ }
+ pushDown();
+ this.plan = selectorPlan;
+ }
+
+ private void pushDown() {
if (queryConstraint != null) {
queryConstraint.restrictPushDown(this);
}
@@ -276,8 +264,16 @@ public class SelectorImpl extends Source
c.restrictPushDown(this);
}
}
+ }
+
+ @Override
+ public ExecutionPlan prepare() {
+ if (plan != null) {
+ return plan;
+ }
+ pushDown();
plan = query.getBestSelectorExecutionPlan(createFilter(true));
- return plan.estimatedCost;
+ return plan;
}
@Override
@@ -297,12 +293,15 @@ public class SelectorImpl extends Source
this.joinCondition = joinCondition;
}
allJoinConditions.add(joinCondition);
+ if (joinCondition.isParent(this)) {
+ isParent = true;
+ }
}
@Override
public void execute(NodeState rootState) {
- if (plan.index != null) {
- cursor = plan.index.query(createFilter(false), rootState);
+ if (plan.getIndex() != null) {
+ cursor = plan.getIndex().query(createFilter(false), rootState);
} else {
cursor = Cursors.newPathCursor(new ArrayList<String>());
}
@@ -342,7 +341,7 @@ public class SelectorImpl extends Source
// "rep:excerpt is not null" to let the index know that
// we will need the excerpt
for (ColumnImpl c : query.getColumns()) {
- if (c.getSelector() == this) {
+ if (c.getSelector().equals(this)) {
if (c.getColumnName().equals("rep:excerpt")) {
f.restrictProperty("rep:excerpt", Operator.NOT_EQUAL, null);
}
@@ -615,11 +614,6 @@ public class SelectorImpl extends Source
}
@Override
- public void init(QueryImpl query) {
- // nothing to do
- }
-
- @Override
public SelectorImpl getSelector(String selectorName) {
if (selectorName.equals(this.selectorName)) {
return this;
@@ -654,15 +648,8 @@ public class SelectorImpl extends Source
return selectorName.hashCode();
}
- @Override
- protected void setParent(JoinConditionImpl joinCondition) {
- if (joinCondition.isParent(this)) {
- isParent = true;
- }
- }
-
QueryIndex getIndex() {
- return plan == null ? null : plan.index;
+ return plan == null ? null : plan.getIndex();
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java Wed Feb 19 13:50:48 2014
@@ -21,7 +21,7 @@ package org.apache.jackrabbit.oak.query.
import java.util.Collections;
import java.util.List;
-import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -55,14 +55,6 @@ public abstract class SourceImpl extends
public abstract void setOuterJoin(boolean outerJoinLeftHandSide, boolean outerJoinRightHandSide);
/**
- * Initialize the query. This will 'wire' the selectors with the
- * constraints.
- *
- * @param query the query
- */
- public abstract void init(QueryImpl query);
-
- /**
* Get the selector with the given name, or null if not found.
*
* @param selectorName the selector name
@@ -93,12 +85,25 @@ public abstract class SourceImpl extends
public abstract String getPlan(NodeState rootState);
/**
- * Prepare executing the query (recursively). This method will decide which
- * index to use.
+ * Prepare executing the query (recursively). This will 'wire' the
+ * selectors with the join constraints, and decide which index to use.
+ *
+ * @return the execution plan
+ */
+ public abstract ExecutionPlan prepare();
+
+ /**
+ * Undo a prepare.
+ */
+ public abstract void unprepare();
+
+ /**
+ * Re-apply a previously prepared plan. This will also 're-wire' the
+ * selectors with the join constraints
*
- * @return the estimated cost
+ * @param p the plan to use
*/
- public abstract double prepare();
+ public abstract void prepare(ExecutionPlan p);
/**
* Execute the query. The current node is set to before the first row.
@@ -114,15 +119,6 @@ public abstract class SourceImpl extends
* @return true if there is a next row
*/
public abstract boolean next();
-
- /**
- * Create a shallow clone of this instance.
- *
- * @return the clone
- */
- public abstract SourceImpl createClone();
-
- abstract void setParent(JoinConditionImpl joinCondition);
/**
* <b>!Test purpose only! <b>
@@ -156,5 +152,5 @@ public abstract class SourceImpl extends
* @return true if there is any
*/
public abstract boolean isOuterJoinRightHandSide();
-
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/FilterImpl.java Wed Feb 19 13:50:48 2014
@@ -32,6 +32,7 @@ import javax.jcr.PropertyType;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.query.ast.JoinConditionImpl;
import org.apache.jackrabbit.oak.query.ast.Operator;
import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression;
@@ -64,10 +65,16 @@ public class FilterImpl implements Filte
* The path, or "/" (the root node, meaning no filter) if not set.
*/
private String path = "/";
-
+
private PathRestriction pathRestriction = PathRestriction.NO_RESTRICTION;
/**
+ * Additional path restrictions whose values are known only at runtime,
+ * for example paths set by other (join-) selectors.
+ */
+ private String pathPlan;
+
+ /**
* The fulltext search conditions, if any.
*/
private final ArrayList<String> fulltextConditions = new ArrayList<String>();
@@ -93,6 +100,12 @@ public class FilterImpl implements Filte
this(null, null);
}
+ /**
+ * Create a filter.
+ *
+ * @param selector the selector for the given filter
+ * @param queryStatement the query statement
+ */
public FilterImpl(SelectorImpl selector, String queryStatement) {
this.selector = selector;
this.queryStatement = queryStatement;
@@ -122,6 +135,18 @@ public class FilterImpl implements Filte
public boolean isPreparing() {
return preparing;
}
+
+ /**
+ * Whether the given selector is already prepared during the prepare phase
+ * of a join. That means, check whether the passed selector can already
+ * provide data.
+ *
+ * @param selector the selector to test
+ * @return true if it is already prepared
+ */
+ public boolean isPrepared(SelectorImpl selector) {
+ return selector.isPrepared();
+ }
/**
* Get the path.
@@ -137,6 +162,20 @@ public class FilterImpl implements Filte
public PathRestriction getPathRestriction() {
return pathRestriction;
}
+
+ @Override
+ public String getPathPlan() {
+ StringBuilder buff = new StringBuilder();
+ String p = path;
+ if (PathUtils.denotesRoot(path)) {
+ p = "";
+ }
+ buff.append(p).append(pathRestriction);
+ if (pathPlan != null) {
+ buff.append(" && ").append(pathPlan);
+ }
+ return buff.toString();
+ }
public void setPath(String path) {
this.path = path;
@@ -354,7 +393,7 @@ public class FilterImpl implements Filte
if (fullTextConstraint != null) {
buff.append("fullText=").append(fullTextConstraint);
}
- buff.append(", path=").append(path).append(pathRestriction);
+ buff.append(", path=").append(getPathPlan());
if (!propertyRestrictions.isEmpty()) {
buff.append(", property=[");
Iterator<Entry<String, PropertyRestriction>> iterator = propertyRestrictions
@@ -377,6 +416,18 @@ public class FilterImpl implements Filte
// currently unknown (prepare time)
addedPath = "/";
}
+ if (addedPath.startsWith(JoinConditionImpl.SPECIAL_PATH_PREFIX)) {
+ // not a real path, that means we only adapt the plan
+ // and that's it
+ if (pathPlan == null) {
+ pathPlan = "";
+ } else {
+ pathPlan += " && ";
+ }
+ pathPlan += addedPath + addedPathRestriction;
+ return;
+ }
+
// calculating the intersection of path restrictions
// this is ugly code, but I don't currently see a radically simpler method
switch (addedPathRestriction) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java Wed Feb 19 13:50:48 2014
@@ -46,6 +46,8 @@ public class TraversingIndex implements
return 0;
}
double nodeCount = 10000000;
+ // if the path is from a join, then the depth is not correct
+ // (the path might be the root node), but that's OK
String path = filter.getPath();
PathRestriction restriction = filter.getPathRestriction();
switch (restriction) {
@@ -81,12 +83,7 @@ public class TraversingIndex implements
@Override
public String getPlan(Filter filter, NodeState rootState) {
- String p = filter.getPath();
- String r = filter.getPathRestriction().toString();
- if (PathUtils.denotesRoot(p)) {
- p = "";
- }
- return "traverse \"" + p + r + '"';
+ return "traverse \"" + filter.getPathPlan() + '"';
}
@Override
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/ExecutionPlan.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/ExecutionPlan.java?rev=1569740&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/ExecutionPlan.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/ExecutionPlan.java Wed Feb 19 13:50:48 2014
@@ -0,0 +1,26 @@
+/*
+ * 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.oak.query.plan;
+
+/**
+ * An execution plan for a join or a selector.
+ */
+public interface ExecutionPlan {
+
+ double getEstimatedCost();
+
+}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/JoinExecutionPlan.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/JoinExecutionPlan.java?rev=1569740&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/JoinExecutionPlan.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/JoinExecutionPlan.java Wed Feb 19 13:50:48 2014
@@ -0,0 +1,55 @@
+/*
+ * 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.oak.query.plan;
+
+import org.apache.jackrabbit.oak.query.ast.JoinImpl;
+
+
+/**
+ * An execution plan for a join.
+ */
+public class JoinExecutionPlan implements ExecutionPlan {
+
+ private final JoinImpl join;
+ private final ExecutionPlan leftPlan, rightPlan;
+ private final double estimatedCost;
+
+ public JoinExecutionPlan(JoinImpl join, ExecutionPlan leftPlan, ExecutionPlan rightPlan, double estimatedCost) {
+ this.join = join;
+ this.leftPlan = leftPlan;
+ this.rightPlan = rightPlan;
+ this.estimatedCost = estimatedCost;
+ }
+
+ @Override
+ public double getEstimatedCost() {
+ return estimatedCost;
+ }
+
+ public JoinImpl getJoin() {
+ return join;
+ }
+
+ public ExecutionPlan getLeftPlan() {
+ return leftPlan;
+ }
+
+ public ExecutionPlan getRightPlan() {
+ return rightPlan;
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/Permutations.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/Permutations.java?rev=1569740&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/Permutations.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/Permutations.java Wed Feb 19 13:50:48 2014
@@ -0,0 +1,168 @@
+/*
+ * 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.oak.query.plan;
+
+/**
+ * A class to iterate over all permutations of an array.
+ * The algorithm is from Applied Combinatorics, by Alan Tucker.
+ *
+ * @param <T> the element type
+ */
+public class Permutations<T> {
+
+ private final T[] in;
+ private final T[] out;
+ private final int n, m;
+ private final int[] index;
+ private boolean hasNext = true;
+
+ private Permutations(T[] in, T[] out, int m) {
+ this.n = in.length;
+ this.m = m;
+ if (n < m || m < 0) {
+ throw new IllegalArgumentException("n < m or m < 0");
+ }
+ this.in = in;
+ this.out = out;
+ index = new int[n];
+ for (int i = 0; i < n; i++) {
+ index[i] = i;
+ }
+
+ // The elements from m to n are always kept ascending right to left.
+ // This keeps the dip in the interesting region.
+ reverseAfter(m - 1);
+ }
+
+ /**
+ * Create a new permutations object.
+ *
+ * @param <T> the type
+ * @param in the source array
+ * @param out the target array
+ * @return the generated permutations object
+ */
+ public static <T> Permutations<T> create(T[] in, T[] out) {
+ return new Permutations<T>(in, out, in.length);
+ }
+
+ /**
+ * Create a new permutations object.
+ *
+ * @param <T> the type
+ * @param in the source array
+ * @param out the target array
+ * @param m the number of output elements to generate
+ * @return the generated permutations object
+ */
+ public static <T> Permutations<T> create(T[] in, T[] out, int m) {
+ return new Permutations<T>(in, out, m);
+ }
+
+ /**
+ * Move the index forward a notch. The algorithm first finds the rightmost
+ * index that is less than its neighbor to the right. This is the dip point.
+ * The algorithm next finds the least element to the right of the dip that
+ * is greater than the dip. That element is switched with the dip. Finally,
+ * the list of elements to the right of the dip is reversed.
+ * For example, in a permutation of 5 items, the index may be {1, 2, 4, 3,
+ * 0}. The dip is 2 the rightmost element less than its neighbor on its
+ * right. The least element to the right of 2 that is greater than 2 is 3.
+ * These elements are swapped, yielding {1, 3, 4, 2, 0}, and the list right
+ * of the dip point is reversed, yielding {1, 3, 0, 2, 4}.
+ */
+ private void moveIndex() {
+ // find the index of the first element that dips
+ int i = rightmostDip();
+ if (i < 0) {
+ hasNext = false;
+ return;
+ }
+
+ // find the least greater element to the right of the dip
+ int leastToRightIndex = i + 1;
+ for (int j = i + 2; j < n; j++) {
+ if (index[j] < index[leastToRightIndex] && index[j] > index[i]) {
+ leastToRightIndex = j;
+ }
+ }
+
+ // switch dip element with least greater element to its right
+ int t = index[i];
+ index[i] = index[leastToRightIndex];
+ index[leastToRightIndex] = t;
+
+ if (m - 1 > i) {
+ // reverse the elements to the right of the dip
+ reverseAfter(i);
+
+ // reverse the elements to the right of m - 1
+ reverseAfter(m - 1);
+ }
+ }
+
+ /**
+ * Get the index of the first element from the right that is less
+ * than its neighbor on the right.
+ *
+ * @return the index or -1 if non is found
+ */
+ private int rightmostDip() {
+ for (int i = n - 2; i >= 0; i--) {
+ if (index[i] < index[i + 1]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Reverse the elements to the right of the specified index.
+ *
+ * @param i the index
+ */
+ private void reverseAfter(int i) {
+ int start = i + 1;
+ int end = n - 1;
+ while (start < end) {
+ int t = index[start];
+ index[start] = index[end];
+ index[end] = t;
+ start++;
+ end--;
+ }
+ }
+
+ /**
+ * Go to the next lineup, and if available, fill the target array.
+ *
+ * @return if a new lineup is available
+ */
+ public boolean next() {
+ if (!hasNext) {
+ return false;
+ }
+ for (int i = 0; i < m; i++) {
+ out[i] = in[index[i]];
+ }
+ moveIndex();
+ return true;
+ }
+
+}
Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/SelectorExecutionPlan.java (from r1568919, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SelectorExecutionPlan.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/SelectorExecutionPlan.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/SelectorExecutionPlan.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SelectorExecutionPlan.java&r1=1568919&r2=1569740&rev=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SelectorExecutionPlan.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/plan/SelectorExecutionPlan.java Wed Feb 19 13:50:48 2014
@@ -14,10 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.jackrabbit.oak.query;
+package org.apache.jackrabbit.oak.query.plan;
import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
-import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
/**
@@ -26,14 +25,29 @@ import org.apache.jackrabbit.oak.spi.que
* is to use a certain query index, which will result in an estimated cost to
* use that index to retrieve nodes for this index.
*/
-public class SelectorExecutionPlan {
+public class SelectorExecutionPlan implements ExecutionPlan {
- public SelectorImpl selector;
-
- public Filter filter;
-
- public double estimatedCost;
+ private final SelectorImpl selector;
+ private final double estimatedCost;
+ private final QueryIndex index;
+
+ public SelectorExecutionPlan(SelectorImpl selector, QueryIndex index, double estimatedCost) {
+ this.selector = selector;
+ this.index = index;
+ this.estimatedCost = estimatedCost;
+ }
- public QueryIndex index;
+ @Override
+ public double getEstimatedCost() {
+ return estimatedCost;
+ }
+
+ public SelectorImpl getSelector() {
+ return selector;
+ }
+
+ public QueryIndex getIndex() {
+ return index;
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Filter.java Wed Feb 19 13:50:48 2014
@@ -85,6 +85,13 @@ public interface Filter {
* @return the path
*/
String getPath();
+
+ /**
+ * Get the plan for the path.
+ *
+ * @return the plan
+ */
+ String getPathPlan();
/**
* Checks whether nodes of all types can match this filter.
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt Wed Feb 19 13:50:48 2014
@@ -23,8 +23,11 @@
# * new tests are typically be added on top, after the syntax docs
# * use ascii character only
-explain select e.[jcr:path] from [nt:base] as a inner join [nt:base] as b on ischildnode(b, a) inner join [nt:base] as c on ischildnode(c, b) inner join [nt:base] as d on ischildnode(d, c) inner join [nt:base] as e on ischildnode(e, d) where name(a) = 'a' and isdescendantnode(a, '/b') and name(b) = 'c' and name(c) = 'd' and name(d) = 'e' and (e.[type] = '1' or e.[type] = '2' or e.[type] = '3' or e.[type] = '4')
-[nt:base] as [a] /* traverse "/b//*" where (name([a]) = cast('a' as string)) and (isdescendantnode([a], [/b])) */ inner join [nt:base] as [b] /* traverse "/path/from/the/join/selector/*" where name([b]) = cast('c' as string) */ on ischildnode([b], [a]) inner join [nt:base] as [c] /* traverse "/path/from/the/join/selector/*" where name([c]) = cast('d' as string) */ on ischildnode([c], [b]) inner join [nt:base] as [d] /* traverse "/path/from/the/join/selector/*" where name([d]) = cast('e' as string) */ on ischildnode([d], [c]) inner join [nt:base] as [e] /* traverse "/path/from/the/join/selector/*" where ([e].[type] is not null) and ([e].[type] in(cast('1' as string), cast('2' as string), cast('3' as string), cast('4' as string))) */ on ischildnode([e], [d])
+explain select e.[jcr:path] from [nt:base] as a inner join [nt:base] as b on ischildnode(b, a) inner join [nt:base] as c on ischildnode(c, b) inner join [nt:base] as d on ischildnode(d, c) inner join [nt:base] as e on ischildnode(e, d) where name(a) = 'a' and isdescendantnode(a, '/b') and name(b) = 'c' and name(c) = 'd' and name(d) = 'e' and (e.[jcr:uuid] = '1' or e.[jcr:uuid] = '2' or e.[jcr:uuid] = '3' or e.[jcr:uuid] = '4')
+[nt:base] as [e] /* property jcr:uuid where ([e].[jcr:uuid] is not null) and ([e].[jcr:uuid] in(cast('1' as string), cast('2' as string), cast('3' as string), cast('4' as string))) */ inner join [nt:base] as [d] /* traverse "* && //parent/of/join" where name([d]) = cast('e' as string) */ on ischildnode([e], [d]) inner join [nt:base] as [c] /* traverse "* && //parent/of/join" where name([c]) = cast('d' as string) */ on ischildnode([d], [c]) inner join [nt:base] as [b] /* traverse "* && //parent/of/join" where name([b]) = cast('c' as string) */ on ischildnode([c], [b]) inner join [nt:base] as [a] /* traverse "/b//* && //parent/of/join" where (name([a]) = cast('a' as string)) and (isdescendantnode([a], [/b])) */ on ischildnode([b], [a])
+
+explain select e.[jcr:path] from [nt:base] as a inner join [nt:base] as b on ischildnode(b, a) inner join [nt:base] as c on ischildnode(c, b) inner join [nt:base] as d on ischildnode(d, c) inner join [nt:base] as e on ischildnode(e, d) where name(a) = 'a' and isdescendantnode(a, '/b') and name(b) = 'c' and name(c) = 'd' and name(d) = 'e' and (e.[jcr:uuid] = '1' or e.[jcr:uuid] = '2' or e.[jcr:uuid] = '3' or e.[jcr:uuid] = '4')
+[nt:base] as [e] /* property jcr:uuid where ([e].[jcr:uuid] is not null) and ([e].[jcr:uuid] in(cast('1' as string), cast('2' as string), cast('3' as string), cast('4' as string))) */ inner join [nt:base] as [d] /* traverse "* && //parent/of/join" where name([d]) = cast('e' as string) */ on ischildnode([e], [d]) inner join [nt:base] as [c] /* traverse "* && //parent/of/join" where name([c]) = cast('d' as string) */ on ischildnode([d], [c]) inner join [nt:base] as [b] /* traverse "* && //parent/of/join" where name([b]) = cast('c' as string) */ on ischildnode([c], [b]) inner join [nt:base] as [a] /* traverse "/b//* && //parent/of/join" where (name([a]) = cast('a' as string)) and (isdescendantnode([a], [/b])) */ on ischildnode([b], [a])
explain select excerpt(.) from [nt:resource] where contains(*, 'jackrabbit')
[nt:resource] as [nt:resource] /* traverse "*" where contains([nt:resource].[*], cast('jackrabbit' as string)) */
@@ -38,6 +41,9 @@ explain select excerpt(.) from [nt:resou
explain select * from [nt:base] where [jcr:uuid]=1 or [b]=2
[nt:base] as [nt:base] /* traverse "*" */
+explain select b.[jcr:uuid] from [nt:base] as a inner join [nt:base] as b on isdescendantnode(b, a) where (a.[jcr:uuid] = '1' or a.[jcr:uuid] = '2')
+[nt:base] as [a] /* property jcr:uuid where ([a].[jcr:uuid] is not null) and ([a].[jcr:uuid] in(cast('1' as string), cast('2' as string))) */ inner join [nt:base] as [b] /* traverse "* && //path/from/join//*" */ on isdescendantnode([b], [a])
+
explain select b.[jcr:uuid] from [nt:base] as a inner join [nt:base] as b on isdescendantnode(b, a) where (a.[jcr:uuid] = '1' or a.[jcr:uuid] = '2') and b.[jcr:uuid] is not null
[nt:base] as [a] /* property jcr:uuid where ([a].[jcr:uuid] is not null) and ([a].[jcr:uuid] in(cast('1' as string), cast('2' as string))) */ inner join [nt:base] as [b] /* property jcr:uuid where [b].[jcr:uuid] is not null */ on isdescendantnode([b], [a])
@@ -66,7 +72,7 @@ explain select * from [nt:base] as a inn
[nt:base] as [a] /* property jcr:uuid where ([a].[jcr:uuid] is not null) and ([a].[jcr:uuid] in(cast('1' as long), cast('2' as long))) */ inner join [nt:base] as [b] /* property jcr:uuid where ([b].[jcr:uuid] is not null) and ([b].[jcr:uuid] in(cast('3' as long), cast('4' as long))) */ on isdescendantnode([b], [a])
explain select * from [nt:base] as a inner join [nt:base] as b on isdescendantnode(b, a) where a.[jcr:uuid] is not null and b.[x] is not null
-[nt:base] as [a] /* property jcr:uuid where [a].[jcr:uuid] is not null */ inner join [nt:base] as [b] /* traverse "/path/from/the/join/selector//*" where [b].[x] is not null */ on isdescendantnode([b], [a])
+[nt:base] as [a] /* property jcr:uuid where [a].[jcr:uuid] is not null */ inner join [nt:base] as [b] /* traverse "* && //path/from/join//*" where [b].[x] is not null */ on isdescendantnode([b], [a])
explain select [rep:excerpt] from [nt:base] where [jcr:uuid] is not null
[nt:base] as [nt:base] /* property jcr:uuid (rep:excerpt) where [nt:base].[jcr:uuid] is not null */
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_measure.txt Wed Feb 19 13:50:48 2014
@@ -27,6 +27,11 @@ commit / + "testRoot": { }
commit /testRoot + "parents": { "p0": {"id": "0"}, "p1": {"id": "1"}, "p2": {"id": "2"}}
commit /testRoot + "children": { "c1": {"p": "1"}, "c2": {"p": "1"}, "c3": {"p": "2"}, "c4": {"p": "3"}}
+select p.[jcr:path], c.[jcr:path] from [nt:base] as p inner join [nt:base] as c on p.id = c.p where isdescendantnode(p, '/testRoot') and isdescendantnode(c, '/testRoot')
+/testRoot/parents/p1, /testRoot/children/c1
+/testRoot/parents/p1, /testRoot/children/c2
+/testRoot/parents/p2, /testRoot/children/c3
+
select [jcr:path] from [nt:base] as p where p.[testRoot/children/*/*] = '3'
/
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt?rev=1569740&r1=1569739&r2=1569740&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt Wed Feb 19 13:50:48 2014
@@ -23,6 +23,10 @@
# * new tests are typically be added on top, after the syntax docs
# * use ascii character only
+# "or" problem (OAK-1432)
+#Â xpath2sql /jcr:root/content/dam//element(*, nt:unstructured)[((@sling:resourceType = 'dam/smartcollection' or @sling:resourceType = 'dam/collection') or @sling:resourceSuperType = 'dam/collection')]
+# select
+
# property names with missing @
xpath2sql /jcr:root/testroot//b/c/d/*[@jcr:uuid='1' or @jcr:uuid='2']