Author: thomasm
Date: Mon Jul 1 11:15:05 2013
New Revision: 1498379
URL: http://svn.apache.org/r1498379
Log:
OAK-882 Query: support conditions of type "property in(value1, value2)"
(auto-convert from "x=1 or x=2" to "x in(1, 2)", possibly using an index)
Modified:
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/ast/AndImpl.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/ComparisonImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.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/DynamicOperandImpl.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/InImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LengthImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LowerCaseImpl.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/NotImpl.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/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/SelectorImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/UpperCaseImpl.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/xpath.txt
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -25,6 +25,7 @@ import org.apache.jackrabbit.oak.api.Tre
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.namepath.JcrPathParser;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.query.ast.AndImpl;
import org.apache.jackrabbit.oak.query.ast.AstVisitorBase;
import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
import org.apache.jackrabbit.oak.query.ast.ChildNodeImpl;
@@ -43,6 +44,8 @@ import org.apache.jackrabbit.oak.query.a
import org.apache.jackrabbit.oak.query.ast.LowerCaseImpl;
import org.apache.jackrabbit.oak.query.ast.NodeLocalNameImpl;
import org.apache.jackrabbit.oak.query.ast.NodeNameImpl;
+import org.apache.jackrabbit.oak.query.ast.NotImpl;
+import org.apache.jackrabbit.oak.query.ast.OrImpl;
import org.apache.jackrabbit.oak.query.ast.OrderingImpl;
import org.apache.jackrabbit.oak.query.ast.PropertyExistenceImpl;
import org.apache.jackrabbit.oak.query.ast.PropertyValueImpl;
@@ -124,8 +127,8 @@ public class Query {
bindVariableMap.put(node.getBindVariableName(), null);
return true;
}
-
- @Override
+
+ @Override
public boolean visit(ChildNodeImpl node) {
node.setQuery(query);
node.bindSelector(source);
@@ -268,6 +271,24 @@ public class Query {
node.setQuery(query);
return super.visit(node);
}
+
+ @Override
+ public boolean visit(AndImpl node) {
+ node.setQuery(query);
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(OrImpl node) {
+ node.setQuery(query);
+ return super.visit(node);
+ }
+
+ @Override
+ public boolean visit(NotImpl node) {
+ node.setQuery(query);
+ return super.visit(node);
+ }
}.visit(this);
source.setQueryConstraint(constraint);
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java
Mon Jul 1 11:15:05 2013
@@ -18,10 +18,13 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
@@ -52,6 +55,40 @@ public class AndImpl extends ConstraintI
result.addAll(s2);
return result;
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ Set<SelectorImpl> s1 = constraint1.getSelectors();
+ Set<SelectorImpl> s2 = constraint1.getSelectors();
+ if (s1.isEmpty()) {
+ return s2;
+ } else if (s2.isEmpty()) {
+ return s1;
+ }
+ return Sets.union(s1, s2);
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> m1 =
constraint1.getInMap();
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> m2 =
constraint2.getInMap();
+ if (m1.isEmpty()) {
+ return m2;
+ } else if (m2.isEmpty()) {
+ return m1;
+ }
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> result =
Maps.newHashMap();
+ result.putAll(m1);
+ for (Entry<DynamicOperandImpl, Set<StaticOperandImpl>> e2 :
m2.entrySet()) {
+ Set<StaticOperandImpl> s = result.get(e2.getKey());
+ if (s != null) {
+ s.retainAll(e2.getValue());
+ } else {
+ result.put(e2.getKey(), e2.getValue());
+ }
+ }
+ return result;
+ }
@Override
public boolean evaluate() {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -57,7 +58,17 @@ public class ChildNodeImpl extends Const
public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
return Collections.emptySet();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
+
@Override
public boolean evaluate() {
String p = selector.currentPath();
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import javax.jcr.PropertyType;
@@ -70,7 +71,20 @@ public class ComparisonImpl extends Cons
}
return Collections.singleton(p);
}
-
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return operand1.getSelectors();
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ if (operator == Operator.EQUAL) {
+ return Collections.singletonMap(operand1,
Collections.singleton(operand2));
+ }
+ return Collections.emptyMap();
+ }
+
@Override
public boolean evaluate() {
// JCR 2.0 spec, 6.7.16 Comparison:
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
Mon Jul 1 11:15:05 2013
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -42,6 +43,20 @@ public abstract class ConstraintImpl ext
* @return the common property existence condition (possibly empty)
*/
public abstract Set<PropertyExistenceImpl>
getPropertyExistenceConditions();
+
+ /**
+ * Get the set of selectors for the given condition.
+ *
+ * @return the set of selectors (possibly empty)
+ */
+ public abstract Set<SelectorImpl> getSelectors();
+
+ /**
+ * Get the map of "in(..)" conditions.
+ *
+ * @return the map
+ */
+ public abstract Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap();
/**
* Apply the condition to the filter, further restricting the filter if
@@ -54,7 +69,12 @@ public abstract class ConstraintImpl ext
/**
* Push as much of the condition down to this selector, further restricting
- * the selector condition if possible.
+ * the selector condition if possible. This is important for a join: for
+ * example, the query
+ * "select * from a inner join b on a.x=b.x where a.y=1 and b.y=1", the
+ * condition "a.y=1" can be pushed down to "a", and the condition "b.y=1"
+ * can be pushed down to "b". That means it is possible to use an index in
+ * this case.
*
* @param s the selector
*/
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -43,6 +44,16 @@ public class DescendantNodeImpl extends
public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
return Collections.emptySet();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
@Override
public boolean evaluate() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DynamicOperandImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DynamicOperandImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DynamicOperandImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DynamicOperandImpl.java
Mon Jul 1 11:15:05 2013
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.List;
+import java.util.Set;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -57,4 +58,27 @@ public abstract class DynamicOperandImpl
*/
public abstract PropertyExistenceImpl getPropertyExistence();
+ /**
+ * Get the set of selectors for this operand.
+ *
+ * @return the set of selectors
+ */
+ public abstract Set<SelectorImpl> getSelectors();
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (!(other instanceof DynamicOperandImpl)) {
+ return false;
+ }
+ DynamicOperandImpl o = (DynamicOperandImpl) other;
+ return o.toString().equals(toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
}
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -24,6 +24,7 @@ import static org.apache.jackrabbit.oak.
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.api.PropertyState;
@@ -108,6 +109,16 @@ public class FullTextSearchImpl extends
}
return Collections.singleton(new PropertyExistenceImpl(selector,
selectorName, propertyName));
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
@Override
public boolean evaluate() {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -18,7 +18,9 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -53,6 +55,11 @@ public class FullTextSearchScoreImpl ext
public PropertyExistenceImpl getPropertyExistence() {
return null;
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
@Override
public PropertyValue currentProperty() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java
Mon Jul 1 11:15:05 2013
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.query.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.jcr.PropertyType;
@@ -29,6 +30,8 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import com.google.common.collect.Sets;
+
/**
* A "in" comparison operation.
*/
@@ -58,6 +61,17 @@ public class InImpl extends ConstraintIm
}
return Collections.singleton(p);
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return operand1.getSelectors();
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ Set<StaticOperandImpl> set = Sets.newHashSet(operand2List);
+ return Collections.singletonMap(operand1, set);
+ }
@Override
public boolean evaluate() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LengthImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LengthImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LengthImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LengthImpl.java
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -55,6 +56,11 @@ public class LengthImpl extends DynamicO
public PropertyExistenceImpl getPropertyExistence() {
return propertyValue.getPropertyExistence();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return propertyValue.getSelectors();
+ }
@Override
public PropertyValue currentProperty() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LowerCaseImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LowerCaseImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LowerCaseImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/LowerCaseImpl.java
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -57,6 +58,11 @@ public class LowerCaseImpl extends Dynam
public PropertyExistenceImpl getPropertyExistence() {
return operand.getPropertyExistence();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return operand.getSelectors();
+ }
@Override
public PropertyValue currentProperty() {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -18,7 +18,9 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -58,6 +60,11 @@ public class NodeLocalNameImpl extends D
public PropertyExistenceImpl getPropertyExistence() {
return null;
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
@Override
public PropertyValue currentProperty() {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -18,7 +18,9 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -65,6 +67,11 @@ public class NodeNameImpl extends Dynami
public PropertyExistenceImpl getPropertyExistence() {
return null;
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
@Override
public PropertyValue currentProperty() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -47,6 +48,16 @@ public class NotImpl extends ConstraintI
public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
return Collections.emptySet();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return constraint.getSelectors();
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
@Override
boolean accept(AstVisitor v) {
@@ -61,12 +72,11 @@ public class NotImpl extends ConstraintI
@Override
public void restrict(FilterImpl f) {
if (f.getSelector().outerJoinRightHandSide) {
- // we need to be careful with the condition
+ // we need to be careful with the condition
// "NOT (property IS NOT NULL)"
- // (which is the same as
- // "property IS NULL") because
- // this might cause an index to ignore
- // the join condition "property = x"
+ // (which is the same as "property IS NULL")
+ // because this might cause an index
+ // to ignore the join condition "property = x"
// for example in:
// "select * from a left outer join b on a.x = b.y
// where not b.y is not null"
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -18,10 +18,14 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
@@ -47,6 +51,8 @@ public class OrImpl extends ConstraintIm
@Override
public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
+ // for the condition "x=1 or x=2", the existence condition
+ // "x is not null" be be derived
Set<PropertyExistenceImpl> s1 =
constraint1.getPropertyExistenceConditions();
if (s1.isEmpty()) {
return s1;
@@ -57,6 +63,39 @@ public class OrImpl extends ConstraintIm
}
return Sets.intersection(s1, s2);
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ Set<SelectorImpl> s1 = constraint1.getSelectors();
+ Set<SelectorImpl> s2 = constraint1.getSelectors();
+ if (s1.isEmpty()) {
+ return s2;
+ } else if (s2.isEmpty()) {
+ return s1;
+ }
+ return Sets.union(s1, s2);
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> m1 =
constraint1.getInMap();
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> m2 =
constraint2.getInMap();
+ if (m1.isEmpty()) {
+ return m1;
+ } else if (m2.isEmpty()) {
+ return m2;
+ }
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> result =
Maps.newHashMap();
+ result.putAll(m1);
+ for (Entry<DynamicOperandImpl, Set<StaticOperandImpl>> e2 :
m2.entrySet()) {
+ Set<StaticOperandImpl> l2 = e2.getValue();
+ Set<StaticOperandImpl> l1 = m1.get(e2.getKey());
+ // l1 might be null (l2 not, as it's from the iterator)
+ Set<StaticOperandImpl> list = l1 == null ? l2 : Sets.union(l1, l2);
+ result.put(e2.getKey(), list);
+ }
+ return result;
+ }
@Override
public boolean evaluate() {
@@ -86,11 +125,71 @@ public class OrImpl extends ConstraintIm
@Override
public void restrictPushDown(SelectorImpl s) {
- // ignore
- // TODO some OR conditions can be applied to a selector,
- // for example WHERE X.ID = 1 OR X.ID = 2
- // can be applied to X as a whole,
- // but X.ID = 1 OR Y.ID = 2 can't be applied to either
+ restrictPushDownNotExists(s);
+ restrictPushDownInList(s);
+ }
+
+ /**
+ * Push down the "property in(1, 2, 3)" conditions to the selector, if
there
+ * are any that can be derived.
+ *
+ * @param s the selector
+ */
+ private void restrictPushDownInList(SelectorImpl s) {
+ if (isOnlySelector(s)) {
+ Map<DynamicOperandImpl, Set<StaticOperandImpl>> m = getInMap();
+ for (Entry<DynamicOperandImpl, Set<StaticOperandImpl>> e :
m.entrySet()) {
+ Set<StaticOperandImpl> set = e.getValue();
+ if (set.size() > 1) {
+ InImpl in = new InImpl(e.getKey(),
Lists.newArrayList(set));
+ in.setQuery(query);
+ in.restrictPushDown(s);
+ }
+ }
+ }
+ }
+
+ /**
+ * Push down the "not exists" conditions to the selector.
+ *
+ * @param s the selector
+ */
+ private void restrictPushDownNotExists(SelectorImpl s) {
+ Set<PropertyExistenceImpl> set = getPropertyExistenceConditions();
+ if (set.isEmpty()) {
+ return;
+ }
+ for (PropertyExistenceImpl p : set) {
+ p.restrictPushDown(s);
+ }
+ }
+
+ /**
+ * Check whether there are no other selectors in this "or" condition.
+ *
+ * @param s the selector
+ * @return true if there are no other selectors
+ */
+ private boolean isOnlySelector(SelectorImpl s) {
+ Set<SelectorImpl> set = getSelectors();
+ if (set.size() == 0) {
+ // conditions without selectors, for example "1=0":
+ // the condition can be pushed down;
+ // (currently there are no such conditions,
+ // but in the future we might add them)
+ return true;
+ } else if (set.size() > 1) {
+ // "x.a=1 or y.a=2" can't be pushed down to either "x" or "y"
+ return false;
+ } else {
+ // exactly one selector: check if it's the right one
+ SelectorImpl s2 = set.iterator().next();
+ if (s2 != s) {
+ // a different selector
+ return false;
+ }
+ }
+ return true;
}
}
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -52,6 +53,16 @@ public class PropertyExistenceImpl exten
public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
return Collections.singleton(this);
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
@Override
boolean accept(AstVisitor v) {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -19,8 +19,10 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -97,6 +99,11 @@ public class PropertyValueImpl extends D
}
return new PropertyExistenceImpl(selector, selectorName, propertyName);
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
@Override
public PropertyValue currentProperty() {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -49,6 +50,16 @@ public class SameNodeImpl extends Constr
public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
return Collections.emptySet();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return Collections.singleton(selector);
+ }
+
+ @Override
+ public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+ return Collections.emptyMap();
+ }
@Override
boolean accept(AstVisitor v) {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -351,5 +351,20 @@ public class SelectorImpl extends Source
selectorCondition = new AndImpl(selectorCondition, constraint);
}
}
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (!(this instanceof SelectorImpl)) {
+ return false;
+ }
+ return selectorName.equals(((SelectorImpl) other).selectorName);
+ }
+
+ @Override
+ public int hashCode() {
+ return selectorName.hashCode();
+ }
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/UpperCaseImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/UpperCaseImpl.java?rev=1498379&r1=1498378&r2=1498379&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/UpperCaseImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/UpperCaseImpl.java
Mon Jul 1 11:15:05 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.ast;
import java.util.List;
+import java.util.Set;
import javax.jcr.PropertyType;
@@ -57,6 +58,11 @@ public class UpperCaseImpl extends Dynam
public PropertyExistenceImpl getPropertyExistence() {
return operand.getPropertyExistence();
}
+
+ @Override
+ public Set<SelectorImpl> getSelectors() {
+ return operand.getSelectors();
+ }
@Override
public PropertyValue currentProperty() {
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -31,17 +31,20 @@ 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') 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])
+
explain select * from [nt:base] where length([jcr:uuid])=1 or
upper([jcr:uuid])='1' or lower([jcr:uuid])='3'
-[nt:base] as [nt:base] /* property jcr:uuid */
+[nt:base] as [nt:base] /* property jcr:uuid where [nt:base].[jcr:uuid] is not
null */
explain select * from [nt:base] where [jcr:uuid] = '1' or ([jcr:uuid] = '2'
and [b] = '3')
-[nt:base] as [nt:base] /* property jcr:uuid */
+[nt:base] as [nt:base] /* property jcr:uuid where ([nt:base].[jcr:uuid] is not
null) and ([nt:base].[jcr:uuid] in(cast('1' as string), cast('2' as string))) */
explain select * from [nt:base] where [jcr:uuid] in('1', '2')
[nt:base] as [nt:base] /* property jcr:uuid where [nt:base].[jcr:uuid]
in(cast('1' as string), cast('2' as string)) */
explain select * from [nt:base] where [jcr:uuid] = '1' or [jcr:uuid] = '2'
-[nt:base] as [nt:base] /* property jcr:uuid */
+[nt:base] as [nt:base] /* property jcr:uuid where ([nt:base].[jcr:uuid] is not
null) and ([nt:base].[jcr:uuid] in(cast('1' as string), cast('2' as string))) */
explain select * from [nt:base] where [jcr:uuid] = '123'
[nt:base] as [nt:base] /* property jcr:uuid=123 where [nt:base].[jcr:uuid] =
cast('123' as string) */
@@ -52,6 +55,9 @@ explain select * from [nt:base] where [j
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.[jcr:uuid] is not
null
[nt:base] as [a] /* property jcr:uuid where [a].[jcr:uuid] is not null */
inner join [nt:base] as [b] /* property jcr:uuid where [b].[jcr:uuid] is not
null */ 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]=1 or a.[jcr:uuid]=2) and
(b.[jcr:uuid]=3 or b.[jcr:uuid]=4)
+[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])
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=1498379&r1=1498378&r2=1498379&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
Mon Jul 1 11:15:05 2013
@@ -28,6 +28,9 @@
xpath2sql testroot//child/..[@foo1]
select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.* from
[nt:base] as a inner join [nt:base] as b on ischildnode(a, b) where name(a) =
'child' and isdescendantnode(a, '/testroot') and b.[foo1] is not null /* xpath:
testroot//child/..[@foo1] */
+xpath2sql //*[@jcr:uuid='1' or @jcr:uuid='2']//*[@jcr:uuid]/(@jcr:uuid)
+select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.[jcr:uuid]
as [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 /* xpath: //*[@jcr:uuid='1' or
@jcr:uuid='2']//*[@jcr:uuid]/(@jcr:uuid) */
+
xpath2sql testroot//child/.[@foo1]
select [jcr:path], [jcr:score], * from [nt:base] as a where [foo1] is not null
and name(a) = 'child' and isdescendantnode(a, '/testroot') /* xpath:
testroot//child/.[@foo1] */