Author: thomasm
Date: Fri Feb 13 10:53:00 2015
New Revision: 1659501

URL: http://svn.apache.org/r1659501
Log:
OAK-2475 Query Filter looses property constraints for multiple and conditions 
for same property

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.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/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/index/FilterTest.java
    
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/plugins/index/reference/ReferenceIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java?rev=1659501&r1=1659500&r2=1659501&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java
 Fri Feb 13 10:53:00 2015
@@ -51,7 +51,7 @@ import com.google.common.collect.Immutab
  */
 class ReferenceIndex implements QueryIndex {
 
-    private static ContentMirrorStoreStrategy STORE = new 
ContentMirrorStoreStrategy();
+    private static final ContentMirrorStoreStrategy STORE = new 
ContentMirrorStoreStrategy();
 
     @Override
     public String getIndexName() {
@@ -70,24 +70,31 @@ class ReferenceIndex implements QueryInd
             return Double.POSITIVE_INFINITY;
         }
         for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
-            if (pr.propertyType == REFERENCE
-                    || pr.propertyType == WEAKREFERENCE) {
+            if (isEqualityRestrictionOnType(pr, REFERENCE) ||
+                    isEqualityRestrictionOnType(pr, WEAKREFERENCE)) {
                 return 1;
             }
         }
         // not an appropriate index
         return POSITIVE_INFINITY;
     }
+    
+    private static boolean isEqualityRestrictionOnType(PropertyRestriction pr, 
int propertyType) {
+        if (pr.propertyType != propertyType) {
+            return false;
+        }
+        return pr.first != null && pr.first == pr.last;
+    }
 
     @Override
     public Cursor query(Filter filter, NodeState root) {
         for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
-            if (pr.propertyType == REFERENCE) {
+            if (isEqualityRestrictionOnType(pr, REFERENCE)) {
                 String uuid = pr.first.getValue(STRING);
                 String name = pr.propertyName;
                 return lookup(root, uuid, name, REF_NAME, filter);
             }
-            if (pr.propertyType == WEAKREFERENCE) {
+            if (isEqualityRestrictionOnType(pr, WEAKREFERENCE)) {
                 String uuid = pr.first.getValue(STRING);
                 String name = pr.propertyName;
                 return lookup(root, uuid, name, WEAK_REF_NAME, filter);

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=1659501&r1=1659500&r2=1659501&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
 Fri Feb 13 10:53:00 2015
@@ -127,10 +127,7 @@ public class PropertyValueImpl extends D
                     f.restrictPath(v.getValue(Type.STRING), 
PathRestriction.EXACT);
                 }
             } else {
-                f.restrictProperty(pn, operator, v);
-                if (propertyType != PropertyType.UNDEFINED) {
-                    f.restrictPropertyType(pn, operator, propertyType);
-                }
+                f.restrictProperty(pn, operator, v, propertyType);
             }
         }
     }

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=1659501&r1=1659500&r2=1659501&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
 Fri Feb 13 10:53:00 2015
@@ -20,7 +20,6 @@ package org.apache.jackrabbit.oak.query.
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
@@ -31,6 +30,8 @@ import javax.annotation.Nullable;
 import javax.jcr.PropertyType;
 import javax.jcr.Session;
 
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.query.QueryEngineSettings;
@@ -87,8 +88,15 @@ public class FilterImpl implements Filte
     
     private FullTextExpression fullTextConstraint;
 
-    private final HashMap<String, PropertyRestriction> propertyRestrictions =
-            new HashMap<String, PropertyRestriction>();
+    /**
+     * The list of restrictions for each property. A restriction may be x=1.
+     * <p>
+     * Each property may have multiple restrictions, which means all
+     * restrictions must apply, for example x=1 and x=2. For this case, only
+     * multi-valued properties match if it contains both the values 1 and 2.
+     */
+    private final ListMultimap<String, PropertyRestriction> 
propertyRestrictions =
+            ArrayListMultimap.create();
 
     /**
      * Only return distinct values.
@@ -239,15 +247,24 @@ public class FilterImpl implements Filte
         return propertyRestrictions.values();
     }
 
-    /**
-     * Get the restriction for the given property, if any.
-     *
-     * @param propertyName the property name
-     * @return the restriction or null
-     */
     @Override
     public PropertyRestriction getPropertyRestriction(String propertyName) {
-        return propertyRestrictions.get(propertyName);
+        List<PropertyRestriction> list = 
propertyRestrictions.get(propertyName);
+        if (list.isEmpty()) {
+            return null;
+        } else if (list.size() == 1) {
+            return list.get(0);
+        }
+        int bestSort = -1;
+        PropertyRestriction best = null;
+        for (PropertyRestriction x : list) {
+            int sort = x.sortOrder();
+            if (sort > bestSort) {
+                bestSort = sort;
+                best = x;
+            }
+        }
+        return best;
     }
 
     public boolean testPath(String path) {
@@ -270,52 +287,25 @@ public class FilterImpl implements Filte
         }
     }
 
-    public void restrictPropertyType(String propertyName, Operator operator,
-            int propertyType) {
-        if (propertyType == PropertyType.UNDEFINED) {
-            // not restricted
-            return;
-        }
-        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 = new PropertyRestriction();
+        x.propertyName = propertyName;
+        x.list = list;
+        addRestriction(x);
     }
     
-    public void restrictPropertyAsList(String propertyName, 
List<PropertyValue> list) {
-        PropertyRestriction x = addRestricition(propertyName);
-        if (x.list == null) {
-            x.list = list;
-        } else {
-            // this is required for multi-valued properties:
-            // for example, if a multi-value property p contains {1, 2},
-            // and we search using "p in (1, 3) and p in (2, 4)", then
-            // this needs to match - so we search for "p in (1, 2, 3, 4)"
-            x.list.removeAll(list);
-            x.list.addAll(list);
-        }
+    public void restrictProperty(String propertyName, Operator op, 
PropertyValue v) {
+        restrictProperty(propertyName, op, v, PropertyType.UNDEFINED);
     }
 
-    public void restrictProperty(String propertyName, Operator op, 
PropertyValue v) {
-        PropertyRestriction x = addRestricition(propertyName);
-        PropertyValue oldFirst = x.first;
-        PropertyValue oldLast = x.last;
+    public void restrictProperty(String propertyName, Operator op, 
PropertyValue v, int propertyType) {
+        PropertyRestriction x = new PropertyRestriction();
+        x.propertyName = propertyName;
+        x.propertyType = propertyType;
         switch (op) {
         case EQUAL:
-            if (x.first != null && x.last == x.first && x.firstIncluding && 
x.lastIncluding) {
-                // we keep the old equality condition if there is one;
-                // we can not use setAlwaysFalse, as this would not be correct
-                // for multi-valued properties:
-                // unlike in databases, "x = 1 and x = 2" can match a node
-                // if x is a multi-valued property with value {1, 2}
-            } else {
-                // all other conditions (range conditions) are replaced with 
this one
-                // (we can not use setAlwaysFalse for the same reason as above)
-                x.first = x.last = v;
-                x.firstIncluding = x.lastIncluding = true;
-            }
+            x.first = x.last = v;
+            x.firstIncluding = x.lastIncluding = true;
             break;
         case NOT_EQUAL:
             if (v != null) {
@@ -323,61 +313,51 @@ public class FilterImpl implements Filte
             }
             break;
         case GREATER_THAN:
-            // we don't narrow the range because of multi-valued properties
-            if (x.first == null) {
-                x.first = maxValue(oldFirst, v);
-                x.firstIncluding = false;
-            }
+            x.first = v;
+            x.firstIncluding = false;
             break;
         case GREATER_OR_EQUAL:
-            // we don't narrow the range because of multi-valued properties
-            if (x.first == null) {
-                x.first = maxValue(oldFirst, v);
-                x.firstIncluding = x.first == oldFirst ? x.firstIncluding : 
true;
-            }
+            x.first = v;
+            x.firstIncluding = true;
             break;
         case LESS_THAN:
-            // we don't narrow the range because of multi-valued properties
-            if (x.last == null) {
-                x.last = minValue(oldLast, v);
-                x.lastIncluding = false;
-            }
+            x.last = v;
+            x.lastIncluding = false;
             break;
         case LESS_OR_EQUAL:
-            // we don't narrow the range because of multi-valued properties
-            if (x.last == null) {
-                x.last = minValue(oldLast, v);
-                x.lastIncluding = x.last == oldLast ? x.lastIncluding : true;
-            }
+            x.last = v;
+            x.lastIncluding = true;
             break;
         case LIKE:
-            // we don't narrow the range because of multi-valued properties
-            if (x.first == null) {
-                // LIKE is handled in the fulltext index
-                x.isLike = true;
-                x.first = v;
-            }
+            // LIKE is handled in the fulltext index
+            x.isLike = true;
+            x.first = v;
             break;
         }
-        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();
-            }
-        }
+        addRestriction(x);
     }
     
-    private PropertyRestriction addRestricition(String propertyName) {
-        PropertyRestriction x = propertyRestrictions.get(propertyName);
-        if (x == null) {
-            x = new PropertyRestriction();
-            x.propertyName = propertyName;
-            propertyRestrictions.put(propertyName, x);
+    /**
+     * Add a restriction for the given property, unless the exact same
+     * restriction is already set.
+     * 
+     * @param restriction the restriction to add
+     */
+    private void addRestriction(PropertyRestriction restriction) {
+        List<PropertyRestriction> list = 
getPropertyRestrictions(restriction.propertyName);
+        for (PropertyRestriction old : list) {
+            if (old.equals(restriction)) {
+                return;
+            }
         }
-        return x;
+        list.add(restriction);
     }
     
+    @Override
+    public List<PropertyRestriction> getPropertyRestrictions(String 
propertyName) {
+        return propertyRestrictions.get(propertyName);
+    }
+
     static PropertyValue maxValue(PropertyValue a, PropertyValue b) {
         if (a == null) {
             return b;
@@ -408,10 +388,10 @@ public class FilterImpl implements Filte
         buff.append(", path=").append(getPathPlan());
         if (!propertyRestrictions.isEmpty()) {
             buff.append(", property=[");
-            Iterator<Entry<String, PropertyRestriction>> iterator = 
propertyRestrictions
-                    .entrySet().iterator();
+            Iterator<Entry<String, Collection<PropertyRestriction>>> iterator 
= propertyRestrictions
+                    .asMap().entrySet().iterator();
             while (iterator.hasNext()) {
-                Entry<String, PropertyRestriction> p = iterator.next();
+                Entry<String, Collection<PropertyRestriction>> p = 
iterator.next();
                 buff.append(p.getKey()).append("=").append(p.getValue());
                 if (iterator.hasNext()) {
                     buff.append(", ");

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=1659501&r1=1659500&r2=1659501&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
 Fri Feb 13 10:53:00 2015
@@ -52,8 +52,10 @@ public interface Filter {
     SelectorImpl getSelector();
 
     /**
-     * Get the list of property restrictions, if any.
-     *
+     * Get the list of property restrictions, if any. Each property may contain
+     * multiple restrictions, for example x=1 and x=2. For this case, only
+     * multi-valued properties match that contain both 1 and 2.
+     * 
      * @return the conditions (an empty collection if not used)
      */
     Collection<PropertyRestriction> getPropertyRestrictions();
@@ -90,12 +92,22 @@ public interface Filter {
     boolean containsNativeConstraint();
 
     /**
-     * Get the property restriction for the given property, if any.
-     *
+     * Get the most restrictive property restriction for the given property, if
+     * any.
+     * 
      * @param propertyName the property name
-     * @return the restriction, or null if there is no restriction for this 
property
+     * @return the first restriction, or null if there is no restriction for
+     *         this property
      */
     PropertyRestriction getPropertyRestriction(String propertyName);
+    
+    /**
+     * Get the all property restriction for the given property.
+     * 
+     * @param propertyName the property name
+     * @return the list of restrictions (possibly empty, never null)
+     */
+    List<PropertyRestriction> getPropertyRestrictions(String propertyName);
 
     /**
      * Get the path restriction type.
@@ -245,7 +257,99 @@ public interface Filter {
             String li = last == null ? "" : (lastIncluding ? "]" : ")");
             return fi + f + ".." + l + li;
         }
+        
+        /**
+         * How restrictive a condition is.
+         * 
+         * @return 0 for "is not null", 10 for equality, and 5 for everything
+         *         else
+         */
+        public int sortOrder() {
+            if (first == null && last == null) {
+                if (list == null) {
+                    return 0;
+                }
+                return 5;
+            }
+            if (first == last) {
+                return 10;
+            }
+            return 5;
+        }
+
+        @Override
+        public int hashCode() {
+            // generated code (Eclipse)
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((first == null) ? 0 : first.hashCode());
+            result = prime * result + (firstIncluding ? 1231 : 1237);
+            result = prime * result + (isLike ? 1231 : 1237);
+            result = prime * result + ((last == null) ? 0 : last.hashCode());
+            result = prime * result + (lastIncluding ? 1231 : 1237);
+            result = prime * result + ((list == null) ? 0 : list.hashCode());
+            result = prime * result +
+                    ((propertyName == null) ? 0 : propertyName.hashCode());
+            result = prime * result + propertyType;
+            return result;
+        }
 
+        @Override
+        public boolean equals(Object obj) {
+            // generated code (Eclipse)
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            PropertyRestriction other = (PropertyRestriction) obj;
+            if (first == null) {
+                if (other.first != null) {
+                    return false;
+                }
+            } else if (!first.equals(other.first)) {
+                return false;
+            }
+            if (firstIncluding != other.firstIncluding) {
+                return false;
+            }
+            if (isLike != other.isLike) {
+                return false;
+            }
+            if (last == null) {
+                if (other.last != null) {
+                    return false;
+                }
+            } else if (!last.equals(other.last)) {
+                return false;
+            }
+            if (lastIncluding != other.lastIncluding) {
+                return false;
+            }
+            if (list == null) {
+                if (other.list != null) {
+                    return false;
+                }
+            } else if (!list.equals(other.list)) {
+                return false;
+            }
+            if (propertyName == null) {
+                if (other.propertyName != null) {
+                    return false;
+                }
+            } else if (!propertyName.equals(other.propertyName)) {
+                return false;
+            }
+            if (propertyType != other.propertyType) {
+                return false;
+            }
+            return true;
+        }
+        
     }
 
     /**

Modified: 
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=1659501&r1=1659500&r2=1659501&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/FilterTest.java
 Fri Feb 13 10:53:00 2015
@@ -45,56 +45,97 @@ public class FilterTest {
         FilterImpl f = new FilterImpl();
         assertTrue(null == f.getPropertyRestriction("x"));
         f.restrictProperty("x", Operator.LESS_OR_EQUAL, two);
-        assertEquals("..2]", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2]]])", 
+                f.toString());
         f.restrictProperty("x", Operator.GREATER_OR_EQUAL, one);
-        assertEquals("[1..2]", f.getPropertyRestriction("x").toString());
-        
-        // further narrowing will not change the restriction, 
-        // to account for multi-valued properties
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2], [1..]])", 
+                f.toString());
+
+        // no change, as the same restrictions already were added
+        f.restrictProperty("x", Operator.LESS_OR_EQUAL, two);
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2], [1..]])", 
+                f.toString());
+        f.restrictProperty("x", Operator.GREATER_OR_EQUAL, one);
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2], [1..]])", 
+                f.toString());
+
         f.restrictProperty("x", Operator.GREATER_THAN, one);
-        assertEquals("[1..2]", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2], [1.., (1..]])", 
+                f.toString());
         f.restrictProperty("x", Operator.LESS_THAN, two);
-        assertEquals("[1..2]", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2], [1.., (1.., ..2)]])", 
+                f.toString());
 
-        // this should replace the range with an equality
-        // (which is faster, and correct even when using multi-valued 
properties)
+        // TODO could replace / remove the old range conditions,
+        // if there is an overlap
         f.restrictProperty("x", Operator.EQUAL, two);
-        assertEquals("2", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[..2], [1.., (1.., ..2), 2]])", 
+                f.toString());
 
         f = new FilterImpl();
         f.restrictProperty("x", Operator.EQUAL, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1]])", 
+                f.toString());
         f.restrictProperty("x", Operator.EQUAL, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1]])", 
+                f.toString());
+        
+        // TODO could replace / remove the old range conditions,
+        // if there is an overlap
         f.restrictProperty("x", Operator.GREATER_OR_EQUAL, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1, [1..]])", 
+                f.toString());
         f.restrictProperty("x", Operator.LESS_OR_EQUAL, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1, [1.., ..1]]])", 
+                f.toString());
         
-        // further narrowing will not change the restriction, 
-        // to account for multi-valued properties
+        // TODO could replace / remove the old range conditions,
+        // if there is an overlap
         f.restrictProperty("x", Operator.GREATER_THAN, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1, [1.., ..1], (1..]])", 
+                f.toString());
 
         f = new FilterImpl();
         f.restrictProperty("x", Operator.EQUAL, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1]])", 
+                f.toString());
 
-        // further narrowing will not change the restriction, 
-        // to account for multi-valued properties
+        // TODO could replace / remove the old range conditions,
+        // if there is an overlap
         f.restrictProperty("x", Operator.LESS_THAN, one);
-        assertEquals("1", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[1, ..1)]])", 
+                f.toString());
 
         f = new FilterImpl();
         f.restrictProperty("x", Operator.NOT_EQUAL, null);
-        assertEquals("", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[]])", 
+                f.toString());
         f.restrictProperty("x", Operator.LESS_THAN, one);
-        assertEquals("..1)", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[, ..1)]])", 
+                f.toString());
         
         // this should replace the range with an equality
         // (which is faster, and correct even when using multi-valued 
properties)
         f.restrictProperty("x", Operator.EQUAL, two);
-        assertEquals("2", f.getPropertyRestriction("x").toString());
+        assertEquals(
+                "Filter(, path=*, property=[x=[, ..1), 2]])", 
+                f.toString());
 
     }
 

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=1659501&r1=1659500&r2=1659501&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
 Fri Feb 13 10:53:00 2015
@@ -24,6 +24,11 @@
 # * new tests are typically be added on top, after the syntax docs
 # * use ascii character only
 
+explain select * from [nt:base] where (p=1 or p=2) and (p=3 or p=4)
+[nt:base] as [nt:base] /* traverse "*"
+  where ([nt:base].[p] in(1, 2))
+  and ([nt:base].[p] in(3, 4)) */
+
 explain select *
   from [nt:base]
   where [jcr:uuid] like '%'


Reply via email to