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 2013/06/26 17:28:07 UTC

svn commit: r1496967 - 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/ main/java/org/apache/jackrabbit/oak/spi/query/ test...

Author: thomasm
Date: Wed Jun 26 15:28:06 2013
New Revision: 1496967

URL: http://svn.apache.org/r1496967
Log:
OAK-882 Query: support conditions of type "property in(value1, value2)"

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java
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/SQL2Parser.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.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/DynamicOperandImpl.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/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/Operator.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/UpperCaseImpl.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/spi/query/Filter.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -37,6 +37,7 @@ import org.apache.jackrabbit.oak.query.a
 import org.apache.jackrabbit.oak.query.ast.EquiJoinConditionImpl;
 import org.apache.jackrabbit.oak.query.ast.FullTextSearchImpl;
 import org.apache.jackrabbit.oak.query.ast.FullTextSearchScoreImpl;
+import org.apache.jackrabbit.oak.query.ast.InImpl;
 import org.apache.jackrabbit.oak.query.ast.LengthImpl;
 import org.apache.jackrabbit.oak.query.ast.LiteralImpl;
 import org.apache.jackrabbit.oak.query.ast.LowerCaseImpl;
@@ -262,6 +263,12 @@ public class Query {
                 return super.visit(node);
             }
 
+            @Override
+            public boolean visit(InImpl node) {
+                node.setQuery(query);
+                return super.visit(node);
+            }
+
         }.visit(this);
         source.setQueryConstraint(constraint);
         source.init(this);

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -367,6 +367,15 @@ public class SQL2Parser {
                     }
                 }
             }
+        } else if (readIf("IN")) {
+            read("(");
+            ArrayList<StaticOperandImpl> list = new ArrayList<StaticOperandImpl>();
+            do {
+                StaticOperandImpl x = parseStaticOperand();
+                list.add(x);
+            } while (readIf(","));
+            read(")");
+            c = factory.in(left, list);
         } else if (readIf("IS")) {
             boolean not = readIf("NOT");
             read("NULL");

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java?rev=1496967&r1=1496966&r2=1496967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java Wed Jun 26 15:28:06 2013
@@ -13,6 +13,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.ArrayList;
+
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
@@ -137,4 +139,9 @@ public class AstElementFactory {
         return new UpperCaseImpl(operand);
     }
 
+    public ConstraintImpl in(DynamicOperandImpl left,
+            ArrayList<StaticOperandImpl> list) {
+        return new InImpl(left, list);
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java?rev=1496967&r1=1496966&r2=1496967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java Wed Jun 26 15:28:06 2013
@@ -35,6 +35,8 @@ public interface AstVisitor {
 
     boolean visit(ComparisonImpl node);
 
+    boolean visit(InImpl node);
+
     boolean visit(DescendantNodeImpl node);
 
     boolean visit(DescendantNodeJoinConditionImpl node);

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -42,6 +42,18 @@ public abstract class AstVisitorBase imp
         node.getOperand2().accept(this);
         return true;
     }
+    
+    /**
+     * Calls accept on the all operands in the "in" node.
+     */
+    @Override
+    public boolean visit(InImpl node) {
+        node.getOperand1().accept(this);
+        for (StaticOperandImpl s : node.getOperand2List()) {
+            s.accept(this);
+        }
+        return true;
+    }
 
     /**
      * Calls accept on the static operand in the fulltext search constraint.

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
 
@@ -27,6 +29,8 @@ public abstract class DynamicOperandImpl
     public abstract PropertyValue currentProperty();
 
     public abstract void restrict(FilterImpl f, Operator operator, PropertyValue v);
+    
+    public abstract void restrictList(FilterImpl f, List<PropertyValue> list);
 
     /**
      * Check whether the condition can be applied to a selector (to restrict the

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -76,6 +78,11 @@ public class FullTextSearchScoreImpl ext
             f.restrictProperty(Query.JCR_SCORE, operator, v);
         }
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        // optimizations of the type "jcr:score() in(a, b, c)" are not supported
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

Added: 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=1496967&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/InImpl.java Wed Jun 26 15:28:06 2013
@@ -0,0 +1,142 @@
+/*
+ * 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.ast;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+
+/**
+ * A "in" comparison operation.
+ */
+public class InImpl extends ConstraintImpl {
+
+    private final DynamicOperandImpl operand1;
+    private final List<StaticOperandImpl> operand2List;
+
+    public InImpl(DynamicOperandImpl operand1, List<StaticOperandImpl> operand2List) {
+        this.operand1 = operand1;
+        this.operand2List = operand2List;
+    }
+
+    public DynamicOperandImpl getOperand1() {
+        return operand1;
+    }
+
+    public List<StaticOperandImpl> getOperand2List() {
+        return operand2List;
+    }
+    
+    @Override
+    public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
+        PropertyExistenceImpl p = operand1.getPropertyExistence();
+        if (p == null) {
+            return Collections.emptySet();
+        }
+        return Collections.singleton(p);
+    }
+
+    @Override
+    public boolean evaluate() {
+        // JCR 2.0 spec, 6.7.16 Comparison:
+        // "operand1 may evaluate to an array of values"
+        PropertyValue p1 = operand1.currentProperty();
+        if (p1 == null) {
+            return false;
+        }
+        for (StaticOperandImpl operand2 : operand2List) {
+            PropertyValue p2 = operand2.currentValue();
+            if (p2 == null) {
+                // if the property doesn't exist, the result is false
+                continue;
+            }
+            int v1Type = ComparisonImpl.getType(p1, p2.getType().tag());
+            if (v1Type != p2.getType().tag()) {
+                // "the value of operand2 is converted to the
+                // property type of the value of operand1"
+                p2 = PropertyValues.convert(p2, v1Type, query.getNamePathMapper());
+            }
+            if (PropertyValues.match(p1, p2)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    boolean accept(AstVisitor v) {
+        return v.visit(this);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buff = new StringBuilder();
+        buff.append(operand1).append(" in(");
+        int i = 0;
+        for (StaticOperandImpl operand2 : operand2List) {
+            if (i++ > 0) {
+                buff.append(", ");
+            }
+            buff.append(operand2);
+        }
+        buff.append(")");
+        return buff.toString();
+    }
+
+    @Override
+    public void restrict(FilterImpl f) {
+        ArrayList<PropertyValue> list = new ArrayList<PropertyValue>();
+        for (StaticOperandImpl s : operand2List) {
+            if (!PropertyValues.canConvert(
+                    s.getPropertyType(), 
+                    operand1.getPropertyType())) {
+                throw new IllegalArgumentException(
+                        "Unsupported conversion from property type " + 
+                                PropertyType.nameFromValue(s.getPropertyType()) + 
+                                " to property type " +
+                                PropertyType.nameFromValue(operand1.getPropertyType()));
+            }
+            list.add(s.currentValue());
+        }
+        if (list != null) {
+            operand1.restrictList(f, list);
+        }
+    }
+
+    @Override
+    public void restrictPushDown(SelectorImpl s) {
+        for (StaticOperandImpl op : operand2List) {
+            if (op.currentValue() == null) {
+                // one unknown value means it is not pushed down
+                return;
+            }
+        }
+        if (operand1.canRestrictSelector(s)) {
+            s.restrictSelector(this);
+        }
+    }
+    
+}

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -92,6 +94,11 @@ public class LengthImpl extends DynamicO
         // LENGTH(x) implies x is not null
         propertyValue.restrict(f, Operator.NOT_EQUAL, null);
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        // optimizations of the type "length(x) in(1, 2, 3)" are not supported
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -73,6 +75,12 @@ public class LowerCaseImpl extends Dynam
         // LOWER(x) implies x is not null
         operand.restrict(f, Operator.NOT_EQUAL, null);
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        // "LOWER(x) IN (A, B)" implies x is not null
+        operand.restrict(f, Operator.NOT_EQUAL, null);
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -72,6 +74,11 @@ public class NodeLocalNameImpl extends D
     public void restrict(FilterImpl f, Operator operator, PropertyValue v) {
         // TODO support LOCALNAME index conditions
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        // optimizations of type "LOCALNAME(..) IN(A, B)" are not supported
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -83,6 +85,11 @@ public class NodeNameImpl extends Dynami
         }
         // TODO support NAME(..) index conditions
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        // optimizations of type "NAME(..) IN(A, B)" are not supported
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -33,7 +33,9 @@ public enum Operator {
 
     LESS_OR_EQUAL("<="),
 
-    LIKE("like");
+    LIKE("like"),
+    
+    IN("in");
 
     /**
      * The name of this operator.

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -170,6 +170,13 @@ public class PropertyValueImpl extends D
             }
         }
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        if (f.getSelector() == selector) {
+            f.restrictPropertyAsList(propertyName, list);
+        }
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

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=1496967&r1=1496966&r2=1496967&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 Wed Jun 26 15:28:06 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import java.util.List;
+
 import javax.jcr.PropertyType;
 
 import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -73,6 +75,12 @@ public class UpperCaseImpl extends Dynam
         // UPPER(x) implies x is not null
         operand.restrict(f, Operator.NOT_EQUAL, null);
     }
+    
+    @Override
+    public void restrictList(FilterImpl f, List<PropertyValue> list) {
+        // "UPPER(x) IN (A, B)" implies x is not null
+        operand.restrict(f, Operator.NOT_EQUAL, null);
+    }
 
     @Override
     public boolean canRestrictSelector(SelectorImpl s) {

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -198,26 +198,25 @@ public class FilterImpl implements Filte
             // not restricted
             return;
         }
-        PropertyRestriction x = propertyRestrictions.get(propertyName);
-        if (x == null) {
-            x = new PropertyRestriction();
-            x.propertyName = propertyName;
-            propertyRestrictions.put(propertyName, x);
-        }
+        PropertyRestriction x = addRestricition(propertyName);
         if (x.propertyType != PropertyType.UNDEFINED && x.propertyType != propertyType) {
             // already restricted to another property type - always false
             setAlwaysFalse();
         }
         x.propertyType = propertyType;
     }
+    
+    public void restrictPropertyAsList(String propertyName, List<PropertyValue> list) {
+        PropertyRestriction x = addRestricition(propertyName);
+        if (x.list == null) {
+            x.list = list;
+        } else {
+            x.list.retainAll(list);
+        }
+    }
 
     public void restrictProperty(String propertyName, Operator op, PropertyValue v) {
-        PropertyRestriction x = propertyRestrictions.get(propertyName);
-        if (x == null) {
-            x = new PropertyRestriction();
-            x.propertyName = propertyName;
-            propertyRestrictions.put(propertyName, x);
-        }
+        PropertyRestriction x = addRestricition(propertyName);
         PropertyValue oldFirst = x.first;
         PropertyValue oldLast = x.last;
         switch (op) {
@@ -253,6 +252,8 @@ public class FilterImpl implements Filte
             x.isLike = true;
             x.first = v;
             break;
+        case IN:
+            
         }
         if (x.first != null && x.last != null) {
             if (x.first.compareTo(x.last) > 0) {
@@ -262,7 +263,17 @@ public class FilterImpl implements Filte
             }
         }
     }
-
+    
+    private PropertyRestriction addRestricition(String propertyName) {
+        PropertyRestriction x = propertyRestrictions.get(propertyName);
+        if (x == null) {
+            x = new PropertyRestriction();
+            x.propertyName = propertyName;
+            propertyRestrictions.put(propertyName, x);
+        }
+        return x;
+    }
+    
     static PropertyValue maxValue(PropertyValue a, PropertyValue b) {
         if (a == null) {
             return b;

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.oak.spi.query;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 import javax.annotation.Nonnull;
@@ -159,6 +160,12 @@ public interface Filter {
          * value should be taken into consideration
          */
         public boolean isLike;
+        
+        /**
+         * A list of possible values, for conditions of the type
+         * "x=1 or x=2 or x=3".
+         */
+        public List<PropertyValue> list;
 
         /**
          * The property type, if restricted.
@@ -168,6 +175,26 @@ public interface Filter {
 
         @Override
         public String toString() {
+            return (toStringFromTo() + " " + toStringList()).trim();
+        }
+        
+        private String toStringList() {
+            if (list == null) {
+                return "";
+            }
+            StringBuilder buff = new StringBuilder("in(");
+            int i = 0;
+            for (PropertyValue p : list) {
+                if (i++ > 0) {
+                    buff.append(", ");
+                }
+                buff.append(p.toString());
+            }
+            buff.append(' ');
+            return buff.toString();
+        }
+        
+        private String toStringFromTo() {
             String f = first == null ? "" : first.toString();
             String l = last == null ? "" : last.toString();
             if (f.equals(l)) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java?rev=1496967&r1=1496966&r2=1496967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java Wed Jun 26 15:28:06 2013
@@ -114,8 +114,10 @@ public abstract class AbstractQueryTest 
     protected void test(String file) throws Exception {
         InputStream in = AbstractQueryTest.class.getResourceAsStream(file);
         LineNumberReader r = new LineNumberReader(new InputStreamReader(in));
+        String className = getClass().getName();
+        String shortClassName = className.replaceAll("org.apache.jackrabbit.oak.plugins.index.", "oajopi.");
         PrintWriter w = new PrintWriter(new OutputStreamWriter(
-                new FileOutputStream("target/" + getClass().getName() + "_"
+                new FileOutputStream("target/" + shortClassName + "_"
                         + file)));
         HashSet<String> knownQueries = new HashSet<String>();
         boolean errors = false;

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt?rev=1496967&r1=1496966&r2=1496967&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt Wed Jun 26 15:28:06 2013
@@ -292,4 +292,4 @@ select [jcr:path] from [nt:base] where n
 java.text.ParseException: Query: select [jcr:path] from [nt:base] where name =+ 'Hello(*)'; expected: Illegal operation: + Hello
 
 select [jcr:path] from [nt:base] where name => 'Hello'
-java.text.ParseException: Query: select [jcr:path] from [nt:base] where name =>(*)'Hello'; expected: (, ., =, <>, <, >, <=, >=, LIKE, IS, NOT
+java.text.ParseException: Query: select [jcr:path] from [nt:base] where name =>(*)'Hello'; expected: (, ., =, <>, <, >, <=, >=, LIKE, IN, IS, NOT

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=1496967&r1=1496966&r2=1496967&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 Jun 26 15:28:06 2013
@@ -37,6 +37,9 @@ explain select * from [nt:base] where le
 explain select * from [nt:base] where [jcr:uuid] = '1' or ([jcr:uuid] = '2' and [b] = '3')
 [nt:base] as [nt:base] /* property jcr:uuid */
 
+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 */