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 2012/03/20 17:15:20 UTC
svn commit: r1302967 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/query/
main/java/org/apache/jackrabbit/oak/query/ast/
main/java/org/apache/jackrabbit/oak/query/index/
test/java/org/apache/jackrabbit/oak/query/index/
Author: thomasm
Date: Tue Mar 20 16:15:20 2012
New Revision: 1302967
URL: http://svn.apache.org/viewvc?rev=1302967&view=rev
Log:
OAK-28 Query implementation
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/LikePatternTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/TraversingCursorTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Value.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.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/EquiJoinConditionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/Operator.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/index/Filter.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1302967&r1=1302966&r2=1302967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Tue Mar 20 16:15:20 2012
@@ -278,17 +278,17 @@ public class SQL2Parser {
private ConstraintImpl parseCondition(DynamicOperandImpl left) throws ParseException {
ConstraintImpl c;
if (readIf("=")) {
- c = factory.comparison(left, Operator.EQ, parseStaticOperand());
+ c = factory.comparison(left, Operator.EQUAL, parseStaticOperand());
} else if (readIf("<>")) {
- c = factory.comparison(left, Operator.NE, parseStaticOperand());
+ c = factory.comparison(left, Operator.NOT_EQUAL, parseStaticOperand());
} else if (readIf("<")) {
- c = factory.comparison(left, Operator.LT, parseStaticOperand());
+ c = factory.comparison(left, Operator.LESS_THAN, parseStaticOperand());
} else if (readIf(">")) {
- c = factory.comparison(left, Operator.GT, parseStaticOperand());
+ c = factory.comparison(left, Operator.GREATER_THAN, parseStaticOperand());
} else if (readIf("<=")) {
- c = factory.comparison(left, Operator.LE, parseStaticOperand());
+ c = factory.comparison(left, Operator.LESS_OR_EQUAL, parseStaticOperand());
} else if (readIf(">=")) {
- c = factory.comparison(left, Operator.GE, parseStaticOperand());
+ c = factory.comparison(left, Operator.GREATER_OR_EQUAL, parseStaticOperand());
} else if (readIf("LIKE")) {
c = factory.comparison(left, Operator.LIKE, parseStaticOperand());
} else if (readIf("IS")) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Value.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Value.java?rev=1302967&r1=1302966&r2=1302967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Value.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Value.java Tue Mar 20 16:15:20 2012
@@ -105,4 +105,9 @@ public class Value implements Comparable
return value.toString().compareTo(o.toString());
}
+ @Override
+ public String toString() {
+ return getString();
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java?rev=1302967&r1=1302966&r2=1302967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java Tue Mar 20 16:15:20 2012
@@ -110,24 +110,25 @@ public abstract class AstVisitorBase imp
* <li>Orderings</li>
* <li>Columns</li>
* </ul>
+ *
+ * @param query the query to visit
*/
- public boolean visit(Query node) {
- node.getSource().accept(this);
- ConstraintImpl constraint = node.getConstraint();
+ public void visit(Query query) {
+ query.getSource().accept(this);
+ ConstraintImpl constraint = query.getConstraint();
if (constraint != null) {
constraint.accept(this);
}
- OrderingImpl[] orderings = node.getOrderings();
+ OrderingImpl[] orderings = query.getOrderings();
if (orderings != null) {
for (OrderingImpl ordering : orderings) {
ordering.accept(this);
}
}
- ColumnImpl[] columns = node.getColumns();
+ ColumnImpl[] columns = query.getColumns();
for (ColumnImpl column : columns) {
column.accept(this);
}
- return true;
}
/**
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=1302967&r1=1302966&r2=1302967&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 Tue Mar 20 16:15:20 2012
@@ -55,14 +55,14 @@ public class ComparisonImpl extends Cons
return false;
}
switch (operator) {
- case EQ:
+ case EQUAL:
return v1.equals(v2);
- case GE:
- case GT:
- case LE:
- case LT:
+ case GREATER_OR_EQUAL:
+ case GREATER_THAN:
+ case LESS_OR_EQUAL:
+ case LESS_THAN:
return operand1.currentValue() .equals(operand2.currentValue());
- case NE:
+ case NOT_EQUAL:
return !operand1.currentValue().equals(operand2.currentValue());
case LIKE:
return evaluateLike(v1, v2);
@@ -268,10 +268,10 @@ public class ComparisonImpl extends Cons
} else {
ValueFactory vf = query.getValueFactory();
if (lowerBound != null) {
- operand1.apply(f, Operator.GE, vf.createValue(lowerBound));
+ operand1.apply(f, Operator.GREATER_OR_EQUAL, vf.createValue(lowerBound));
}
if (upperBound != null) {
- operand1.apply(f, Operator.LE, vf.createValue(upperBound));
+ operand1.apply(f, Operator.LESS_OR_EQUAL, vf.createValue(upperBound));
}
}
} else {
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=1302967&r1=1302966&r2=1302967&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 Tue Mar 20 16:15:20 2012
@@ -93,10 +93,10 @@ public class EquiJoinConditionImpl exten
Value v1 = selector1.currentProperty(property1Name);
Value v2 = selector2.currentProperty(property2Name);
if (f.getSelector() == selector1 && v2 != null) {
- f.restrictProperty(property1Name, Operator.EQ, v2);
+ f.restrictProperty(property1Name, Operator.EQUAL, v2);
}
if (f.getSelector() == selector2 && v1 != null) {
- f.restrictProperty(property2Name, Operator.EQ, v1);
+ f.restrictProperty(property2Name, Operator.EQUAL, v1);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/Operator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/Operator.java?rev=1302967&r1=1302966&r2=1302967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/Operator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/Operator.java Tue Mar 20 16:15:20 2012
@@ -21,17 +21,17 @@ package org.apache.jackrabbit.oak.query.
*/
public enum Operator {
- EQ("="),
+ EQUAL("="),
- NE("<>"),
+ NOT_EQUAL("<>"),
- GT(">"),
+ GREATER_THAN(">"),
- GE(">="),
+ GREATER_OR_EQUAL(">="),
- LT("<"),
+ LESS_THAN("<"),
- LE("<="),
+ LESS_OR_EQUAL("<="),
LIKE("like");
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=1302967&r1=1302966&r2=1302967&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 Tue Mar 20 16:15:20 2012
@@ -67,7 +67,7 @@ public class PropertyExistenceImpl exten
@Override
public void apply(Filter f) {
if (f.getSelector() == selector) {
- f.restrictProperty(propertyName, Operator.NE, (Value) null);
+ f.restrictProperty(propertyName, Operator.NOT_EQUAL, (Value) null);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/Filter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/Filter.java?rev=1302967&r1=1302966&r2=1302967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/Filter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/Filter.java Tue Mar 20 16:15:20 2012
@@ -94,9 +94,9 @@ public class Filter {
*/
private String valuePrefix;
- private HashMap<String, PropertyValueCondition> propertyRanges = new HashMap<String, PropertyValueCondition>();
+ private HashMap<String, PropertyRestriction> propertyRestrictions = new HashMap<String, PropertyRestriction>();
- static class PropertyValueCondition {
+ static class PropertyRestriction {
/**
* The name of the property.
@@ -106,22 +106,28 @@ public class Filter {
/**
* The first value to read, or null to read from the beginning.
*/
- public String first;
+ public Value first;
/**
- * Whether only values bigger than the first value should be returned.
+ * Whether values that match the first should be returned.
*/
- public boolean firstExcluding;
+ public boolean firstIncluding;
/**
* The last value to read, or null to read until the end.
*/
- public String last;
+ public Value last;
/**
- * Whether only values smaller than the last value should be returned.
+ * Whether values that match the last should be returned.
*/
- public boolean lastExcluding;
+ public boolean lastIncluding;
+
+ @Override
+ public String toString() {
+ return (first == null ? "" : ((firstIncluding ? "[" : "(") + first)) + ".." +
+ (last == null ? "" : last + (lastIncluding ? "]" : ")"));
+ }
}
@@ -138,6 +144,8 @@ public class Filter {
/**
* Get the path.
+ *
+ * @return the path
*/
public String getPath() {
return path;
@@ -176,7 +184,7 @@ public class Filter {
}
public void setAlwaysFalse() {
- propertyRanges.clear();
+ propertyRestrictions.clear();
valuePrefix = "none";
nodeType = "none";
path = "none";
@@ -192,8 +200,14 @@ public class Filter {
return selector;
}
- public void restrictProperty(String propertyName, Operator op, Value value) {
- restrictProperty(propertyName, op, value == null ? null : value.getString());
+ /**
+ * Get the restriction for the given property, if any.
+ *
+ * @param propertyName the property name
+ * @return the restriction or null
+ */
+ public PropertyRestriction getPropertyRestriction(String propertyName) {
+ return propertyRestrictions.get(propertyName);
}
public boolean testPath(String path) {
@@ -214,53 +228,62 @@ public class Filter {
}
}
- public void restrictProperty(String propertyName, Operator op, String value) {
- PropertyValueCondition x = propertyRanges.get(propertyName);
+ public void restrictProperty(String propertyName, Operator op, Value value) {
+ PropertyRestriction x = propertyRestrictions.get(propertyName);
if (x == null) {
- x = new PropertyValueCondition();
+ x = new PropertyRestriction();
x.propertyName = propertyName;
- propertyRanges.put(propertyName, x);
+ propertyRestrictions.put(propertyName, x);
}
- String oldFirst = x.first, oldLast = x.last;
+ Value oldFirst = x.first, oldLast = x.last;
switch (op) {
- case EQ:
+ case EQUAL:
x.first = maxValue(oldFirst, value);
- x.firstExcluding = false;
+ x.firstIncluding = x.first == oldFirst ? x.firstIncluding : true;
x.last = minValue(oldLast, value);
- x.lastExcluding = false;
+ x.lastIncluding = x.last == oldLast ? x.lastIncluding : true;
break;
- case NE:
- // not null
+ case NOT_EQUAL:
+ if (value != null) {
+ throw new IllegalArgumentException("NOT_EQUAL only supported for NOT_EQUAL NULL");
+ }
break;
- case GT:
+ case GREATER_THAN:
x.first = maxValue(oldFirst, value);
- x.firstExcluding = true;
+ x.firstIncluding = false;
break;
- case GE:
+ case GREATER_OR_EQUAL:
x.first = maxValue(oldFirst, value);
- x.firstExcluding = x.first == oldFirst ? x.firstExcluding : false;
+ x.firstIncluding = x.first == oldFirst ? x.firstIncluding : true;
break;
- case LT:
+ case LESS_THAN:
x.last = minValue(oldLast, value);
- x.lastExcluding = true;
+ x.lastIncluding = false;
break;
- case LE:
+ case LESS_OR_EQUAL:
x.last = minValue(oldLast, value);
- x.lastExcluding = x.last == oldLast ? x.lastExcluding : false;
+ x.lastIncluding = x.last == oldLast ? x.lastIncluding : true;
break;
case LIKE:
- throw new RuntimeException("LIKE is not supported");
+ throw new IllegalArgumentException("LIKE is not supported");
+ }
+ if (x.first != null && x.last != null) {
+ if (x.first.compareTo(x.last) > 0) {
+ setAlwaysFalse();
+ } else if (x.first.compareTo(x.last) == 0 && (!x.firstIncluding || !x.lastIncluding)) {
+ setAlwaysFalse();
+ }
}
}
- static String maxValue(String a, String b) {
+ static Value maxValue(Value a, Value b) {
if (a == null) {
return b;
}
return a.compareTo(b) < 0 ? b : a;
}
- static String minValue(String a, String b) {
+ static Value minValue(Value a, Value b) {
if (a == null) {
return b;
}
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java?rev=1302967&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java Tue Mar 20 16:15:20 2012
@@ -0,0 +1,259 @@
+/*
+ * 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.index;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.util.ArrayList;
+import java.util.Random;
+import org.apache.jackrabbit.oak.query.Value;
+import org.apache.jackrabbit.oak.query.ValueFactory;
+import org.apache.jackrabbit.oak.query.ast.Operator;
+import org.apache.jackrabbit.oak.query.index.Filter.PathRestriction;
+import org.junit.Test;
+
+/**
+ * Tests the Filter class.
+ */
+public class FilterTest {
+
+ @Test
+ public void propertyRestriction() {
+ Value one = new ValueFactory().createValue("1");
+ Value two = new ValueFactory().createValue("2");
+
+ Filter f = new Filter(null);
+ assertTrue(null == f.getPropertyRestriction("x"));
+ f.restrictProperty("x", Operator.LESS_OR_EQUAL, two);
+ assertEquals("..2]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.GREATER_OR_EQUAL, one);
+ assertEquals("[1..2]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.GREATER_THAN, one);
+ assertEquals("(1..2]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.LESS_THAN, two);
+ assertEquals("(1..2)", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.EQUAL, two);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictProperty("x", Operator.EQUAL, one);
+ assertEquals("[1..1]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.EQUAL, one);
+ assertEquals("[1..1]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.GREATER_OR_EQUAL, one);
+ assertEquals("[1..1]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.LESS_OR_EQUAL, one);
+ assertEquals("[1..1]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.GREATER_THAN, one);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictProperty("x", Operator.EQUAL, one);
+ assertEquals("[1..1]", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.LESS_THAN, one);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictProperty("x", Operator.NOT_EQUAL, null);
+ assertEquals("..", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.LESS_THAN, one);
+ assertEquals("..1)", f.getPropertyRestriction("x").toString());
+ f.restrictProperty("x", Operator.EQUAL, two);
+ assertTrue(f.isAlwaysFalse());
+
+ }
+
+ @Test
+ public void pathRestrictionsRandomized() throws Exception {
+ ArrayList<String> paths = new ArrayList<String>();
+ // create paths /a, /b, /c, /a/a, /a/b, ... /c/c/c
+ paths.add("/");
+ for (int i = 'a'; i <= 'c'; i++) {
+ String p1 = "/" + (char) i;
+ paths.add(p1);
+ for (int j = 'a'; j <= 'c'; j++) {
+ String p2 = "/" + (char) j;
+ paths.add(p1 + p2);
+ for (int k = 'a'; k <= 'c'; k++) {
+ String p3 = "/" + (char) k;
+ paths.add(p1 + p2 + p3);
+ }
+ }
+ }
+ Random r = new Random(1);
+ for (int i = 0; i < 10000; i++) {
+ String p1 = paths.get(r.nextInt(paths.size()));
+ String p2 = paths.get(r.nextInt(paths.size()));
+ PathRestriction r1 = PathRestriction.values()[r.nextInt(PathRestriction.values().length)];
+ PathRestriction r2 = PathRestriction.values()[r.nextInt(PathRestriction.values().length)];
+ Filter f1 = new Filter(null);
+ f1.restrictPath(p1, r1);
+ Filter f2 = new Filter(null);
+ f2.restrictPath(p2, r2);
+ Filter fc = new Filter(null);
+ fc.restrictPath(p1, r1);
+ fc.restrictPath(p2, r2);
+ int tooMany = 0;
+ for (String p : paths) {
+ boolean expected = f1.testPath(p) && f2.testPath(p);
+ boolean got = fc.testPath(p);
+ if (expected == got) {
+ // good
+ } else if (expected && !got) {
+ fc = new Filter(null);
+ fc.restrictPath(p1, r1);
+ fc.restrictPath(p2, r2);
+ fail("not matched: " + p1 + "/" + r1.name() + " && " + p2 + "/" + r2.name());
+ } else {
+ // not great, but not a problem
+ tooMany++;
+ }
+ }
+ if (tooMany > 3) {
+ fail("too many matches: " + p1 + "/" + r1.name() + " && " + p2 + "/" + r2.name() + " superfluous: " + tooMany);
+ }
+ }
+ }
+
+ @Test
+ public void pathRestrictions() throws Exception {
+ Filter f = new Filter(null);
+ assertEquals("/", f.getPath());
+ assertEquals(PathRestriction.ALL_CHILDREN, f.getPathRestriction());
+
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ f.restrictPath("/test2", PathRestriction.ALL_CHILDREN);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ assertEquals("/test", f.getPath());
+ assertEquals(PathRestriction.ALL_CHILDREN, f.getPathRestriction());
+ f.restrictPath("/test/x", PathRestriction.DIRECT_CHILDREN);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+ f.restrictPath("/test/x/y", PathRestriction.PARENT);
+ assertEquals("/test/x/y", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+ f.restrictPath("/test/x/y", PathRestriction.PARENT);
+ assertEquals("/test/x/y", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test/y", PathRestriction.DIRECT_CHILDREN);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test/x/y", PathRestriction.PARENT);
+ f.restrictPath("/test/x", PathRestriction.EXACT);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.EXACT, f.getPathRestriction());
+ f.restrictPath("/test/y", PathRestriction.EXACT);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ f.restrictPath("/test", PathRestriction.PARENT);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test/x", PathRestriction.PARENT);
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test/x", PathRestriction.ALL_CHILDREN);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ f.restrictPath("/test", PathRestriction.EXACT);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+ f.restrictPath("/test/x", PathRestriction.EXACT);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.EXACT, f.getPathRestriction());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+ f.restrictPath("/test/x/y", PathRestriction.EXACT);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test/x", PathRestriction.PARENT);
+ f.restrictPath("/", PathRestriction.ALL_CHILDREN);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test/y", PathRestriction.EXACT);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+ assertEquals("/test", f.getPath());
+ assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+ f.restrictPath("/", PathRestriction.ALL_CHILDREN);
+ assertEquals("/test", f.getPath());
+ assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ assertEquals("/test", f.getPath());
+ assertEquals(PathRestriction.DIRECT_CHILDREN, f.getPathRestriction());
+ f.restrictPath("/test/x/y", PathRestriction.PARENT);
+ assertEquals("/test/x/y", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test2", PathRestriction.ALL_CHILDREN);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test/x", PathRestriction.EXACT);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.EXACT, f.getPathRestriction());
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+ f.restrictPath("/test/x/y", PathRestriction.PARENT);
+ f.restrictPath("/test/y", PathRestriction.DIRECT_CHILDREN);
+ assertTrue(f.isAlwaysFalse());
+
+ f = new Filter(null);
+ f.restrictPath("/test/x/y", PathRestriction.PARENT);
+ assertEquals("/test/x/y", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test/x", PathRestriction.PARENT);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test", PathRestriction.ALL_CHILDREN);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test", PathRestriction.DIRECT_CHILDREN);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test/x", PathRestriction.PARENT);
+ assertEquals("/test/x", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test", PathRestriction.PARENT);
+ assertEquals("/test", f.getPath());
+ assertEquals(PathRestriction.PARENT, f.getPathRestriction());
+ f.restrictPath("/test2", PathRestriction.EXACT);
+ assertTrue(f.isAlwaysFalse());
+
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/LikePatternTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/LikePatternTest.java?rev=1302967&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/LikePatternTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/LikePatternTest.java Tue Mar 20 16:15:20 2012
@@ -0,0 +1,49 @@
+/*
+ * 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.index;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import org.apache.jackrabbit.oak.query.ast.ComparisonImpl;
+import org.junit.Test;
+
+public class LikePatternTest {
+
+ @Test
+ public void pattern() {
+ pattern("%_", "X", "", null, null);
+ pattern("A%", "A", "X", "A", "B");
+ pattern("A%%", "A", "X", "A", "B");
+ pattern("%\\_%", "A_A", "AAA", null, null);
+ }
+
+ private void pattern(String pattern, String match, String noMatch, String lower, String upper) {
+ ComparisonImpl.LikePattern p = new ComparisonImpl.LikePattern(pattern);
+ if (match != null) {
+ assertTrue(p.matches(match));
+ }
+ if (noMatch != null) {
+ assertFalse(p.matches(noMatch));
+ }
+ assertEquals(lower, p.getLowerBound());
+ assertEquals(upper, p.getUpperBound());
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/TraversingCursorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/TraversingCursorTest.java?rev=1302967&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/TraversingCursorTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/TraversingCursorTest.java Tue Mar 20 16:15:20 2012
@@ -0,0 +1,83 @@
+/*
+ * 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.index;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.apache.jackrabbit.mk.MicroKernelFactory;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests the TraversingCursor.
+ */
+public class TraversingCursorTest {
+
+ MicroKernel mk;
+ String head;
+
+ @Before
+ public void setUp() {
+ mk = MicroKernelFactory.getInstance("simple:/target/temp;clear");
+ head = mk.getHeadRevision();
+ }
+
+ @After
+ public void tearDown() {
+ mk.dispose();
+ }
+
+ @Test
+ public void traverse() throws Exception {
+ TraversingReader r = new TraversingReader(mk);
+ traverse(r);
+ }
+
+ @Test
+ public void traverseBlockwise() throws Exception {
+ TraversingReader r = new TraversingReader(mk);
+ r.setChildBlockSize(2);
+ traverse(r);
+ }
+
+ private void traverse(TraversingReader r) {
+ head = mk.commit("/", "+ \"parents\": { \"p0\": {\"id\": \"0\"}, \"p1\": {\"id\": \"1\"}, \"p2\": {\"id\": \"2\"}}", head, "");
+ head = mk.commit("/", "+ \"children\": { \"c1\": {\"p\": \"1\"}, \"c2\": {\"p\": \"1\"}, \"c3\": {\"p\": \"2\"}, \"c4\": {\"p\": \"3\"}}", head, "");
+ Filter f = new Filter(null);
+ Cursor c;
+ f.setPath("/");
+ c = r.query(f, head);
+ String[] list = {"/", "/parents", "/parents/p0", "/parents/p1", "/parents/p2",
+ "/children", "/children/c1", "/children/c2", "/children/c3", "/children/c4"};
+ for (String s : list) {
+ assertTrue(c.next());
+ assertEquals(s, c.currentPath());
+ }
+ assertFalse(c.next());
+ assertFalse(c.next());
+ f.setPath("/nowhere");
+ c = r.query(f, head);
+ assertFalse(c.next());
+ assertFalse(c.next());
+ }
+
+}