Author: mduerig
Date: Mon May 19 12:03:29 2014
New Revision: 1595856

URL: http://svn.apache.org/r1595856
Log:
OAK-1745: OrderedIndex should serve range queries regardless of direction
Patch from Davide

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndex.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndex.java?rev=1595856&r1=1595855&r2=1595856&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndex.java
 Mon May 19 12:03:29 2014
@@ -81,10 +81,12 @@ public class OrderedPropertyIndex extend
 
     @Override
     public List<IndexPlan> getPlans(Filter filter, List<OrderEntry> sortOrder, 
NodeState root) {
-        LOG.debug("getPlans(Filter, List<OrderEntry>, NodeState)");
-        LOG.debug("getPlans() - filter: {} - ", filter);
-        LOG.debug("getPlans() - sortOrder: {} - ", sortOrder);
-        LOG.debug("getPlans() - rootState: {} - ", root);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("getPlans(Filter, List<OrderEntry>, NodeState)");
+            LOG.debug("getPlans() - filter: {} - ", filter);
+            LOG.debug("getPlans() - sortOrder: {} - ", sortOrder);
+            LOG.debug("getPlans() - rootState: {} - ", root);
+        }
         List<IndexPlan> plans = new ArrayList<IndexPlan>();
 
         PropertyIndexLookup pil = getLookup(root);
@@ -131,20 +133,12 @@ public class OrderedPropertyIndex extend
                         createPlan = true;
                     } else if (pr.first != null && !pr.first.equals(pr.last)) {
                         // '>' & '>=' use cases
-                        if (lookup.isAscending(root, propertyName, filter)) {
-                            value = pr.first;
-                            createPlan = true;
-                        } else {
-                            createPlan = false;
-                        }
+                        value = pr.first;
+                        createPlan = true;
                     } else if (pr.last != null && !pr.last.equals(pr.first)) {
                         // '<' & '<='
-                        if (!lookup.isAscending(root, propertyName, filter)) {
-                            value = pr.last;
-                            createPlan = true;
-                        } else {
-                            createPlan = false;
-                        }
+                        value = pr.last;
+                        createPlan = true;
                     }
                     if (createPlan) {
                         // we always return a sorted set

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java?rev=1595856&r1=1595855&r2=1595856&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java
 Mon May 19 12:03:29 2014
@@ -276,25 +276,69 @@ public class OrderedContentMirrorStoreSt
     public Iterable<String> query(final Filter filter, final String indexName,
                                   final NodeState indexMeta, final String 
indexStorageNodeName,
                                   final PropertyRestriction pr) {
-
+        
         final NodeState index = indexMeta.getChildNode(indexStorageNodeName);
 
         if (pr.first != null && !pr.first.equals(pr.last)) {
-            // '>' & '>=' use case
-            ChildNodeEntry firstValueableItem = seek(index,
-                new PredicateGreaterThan(pr.first.getValue(Type.STRING), 
pr.firstIncluding));
+            // '>' & '>=' and between use case
+            ChildNodeEntry firstValueableItem;
             Iterable<String> it = Collections.emptyList();
-            if (firstValueableItem != null) {
-                Iterable<ChildNodeEntry> childrenIterable = (pr.last == null) 
? new SeekedIterable(
-                    index, firstValueableItem) : new BetweenIterable(index, 
firstValueableItem,
-                    pr.last.getValue(Type.STRING), pr.lastIncluding);
-                it = new QueryResultsWrapper(filter, indexName, 
childrenIterable);
+            Iterable<ChildNodeEntry> childrenIterable;
+            
+            if (pr.last == null) {
+                LOG.debug("> & >= case.");
+                firstValueableItem = seek(index,
+                    new PredicateGreaterThan(pr.first.getValue(Type.STRING), 
pr.firstIncluding));
+                if (firstValueableItem != null) {
+                    childrenIterable = new SeekedIterable(index, 
firstValueableItem);
+                    it = new QueryResultsWrapper(filter, indexName, 
childrenIterable);
+                }
+            } else {
+                String first, last;
+                boolean includeFirst, includeLast;
+                first = pr.first.getValue(Type.STRING);
+                last = pr.last.getValue(Type.STRING);
+                includeFirst = pr.firstIncluding;
+                includeLast = pr.lastIncluding;
+
+                if (LOG.isDebugEnabled()) {
+                    final String op1 = includeFirst ? ">=" : ">";
+                    final String op2 = includeLast ? "<=" : "<";
+                    LOG.debug("in between case. direction: {} - Condition: (x 
{} {} AND x {} {})",
+                        new Object[] { direction, op1, first, op2, last });
+                }
+
+                if (direction.equals(OrderDirection.ASC)) {
+                    firstValueableItem = seek(index,
+                        new PredicateGreaterThan(first, includeFirst));
+                } else {
+                    firstValueableItem = seek(index,
+                        new PredicateLessThan(last, includeLast));
+                }
+                
+                LOG.debug("firstValueableItem: {}", firstValueableItem);
+                
+                if (firstValueableItem != null) {
+                    childrenIterable = new BetweenIterable(index, 
firstValueableItem, last,
+                        includeLast, direction);
+                    it = new QueryResultsWrapper(filter, indexName, 
childrenIterable);
+                }
             }
+
             return it;
         } else if (pr.last != null && !pr.last.equals(pr.first)) {
             // '<' & '<=' use case
-            ChildNodeEntry firstValueableItem = seek(index,
-                new PredicateLessThan(pr.last.getValue(Type.STRING), 
pr.lastIncluding));
+            final String searchfor = pr.last.getValue(Type.STRING);
+            final boolean include = pr.lastIncluding;
+            Predicate<ChildNodeEntry> predicate = new 
PredicateLessThan(searchfor, include);
+            
+            LOG.debug("< & <= case. - searchfor: {} - include: {} - predicate: 
{}",
+                new Object[] { searchfor, include, predicate });
+
+            ChildNodeEntry firstValueableItem = seek(index, predicate);
+            
+            LOG.debug("firstValuableItem: {}", firstValueableItem);
+            
             Iterable<String> it = Collections.emptyList();
             if (firstValueableItem != null) {
                 it = new QueryResultsWrapper(filter, indexName, new 
SeekedIterable(index,
@@ -376,18 +420,41 @@ public class OrderedContentMirrorStoreSt
                     v.visit(content);
                     count = v.getEstimatedCount();
                 }
-            } else if (lpr.first != null && !lpr.first.equals(lpr.last)
-                       && OrderDirection.ASC.equals(direction)) {
+            } else if (lpr.first != null && !lpr.first.equals(lpr.last)) {
                 // > & >= in ascending index
+                value = lpr.first.getValue(Type.STRING);
+                final String vv = value;
+                final boolean include = lpr.firstIncluding;
+                final OrderDirection dd = direction;
+
                 Iterable<? extends ChildNodeEntry> children = 
getChildNodeEntries(content);
+                Predicate<String> predicate = new Predicate<String>() {
+                    private String v = vv;
+                    private boolean i = include;
+                    private OrderDirection d = dd;
+                    
+                    @Override
+                    public boolean apply(String input) {
+                        boolean b;
+                        
+                        if (d.equals(OrderDirection.ASC)) {
+                            b = v.compareTo(input) > 0;
+                        } else {
+                            b = v.compareTo(input) < 0;
+                        }
+                        
+                        b = b || (i && v.equals(input));
+                        
+                        return b;
+                    }
+                };
+
                 CountingNodeVisitor v;
-                value = lpr.first.getValue(Type.STRING);
                 int depthTotal = 0;
                 // seeking the right starting point
                 for (ChildNodeEntry child : children) {
                     String converted = convert(child.getName());
-                    if (value.compareTo(converted) < 0
-                        || (lpr.firstIncluding && value.equals(converted))) {
+                    if (predicate.apply(converted)) {
                         // here we are let's start counting
                         v = new CountingNodeVisitor(max);
                         v.visit(content.getChildNode(child.getName()));
@@ -403,18 +470,41 @@ public class OrderedContentMirrorStoreSt
                 v.depthTotal = depthTotal;
                 v.count = (int) Math.min(count, Integer.MAX_VALUE);
                 count = v.getEstimatedCount();
-            } else if (lpr.last != null && !lpr.last.equals(lpr.first)
-                       && OrderDirection.DESC.equals(direction)) {
-                // > & >= in ascending index
+            } else if (lpr.last != null && !lpr.last.equals(lpr.first)) {
+                // < & <= 
+                value = lpr.last.getValue(Type.STRING);
+                final String vv = value;
+                final boolean include = lpr.lastIncluding;
+                final OrderDirection dd = direction;
+                
                 Iterable<? extends ChildNodeEntry> children = 
getChildNodeEntries(content);
+                Predicate<String> predicate = new Predicate<String>() {
+                    private String v = vv;
+                    private boolean i = include;
+                    private OrderDirection d = dd;
+                    
+                    @Override
+                    public boolean apply(String input) {
+                        boolean b;
+                        
+                        if (d.equals(OrderDirection.ASC)) {
+                            b = v.compareTo(input) < 0;
+                        } else {
+                            b = v.compareTo(input) > 0;
+                        }
+                        
+                        b = b || (i && v.equals(input));
+                        
+                        return b;
+                    }
+                };
+                
                 CountingNodeVisitor v;
-                value = lpr.last.getValue(Type.STRING);
                 int depthTotal = 0;
                 // seeking the right starting point
                 for (ChildNodeEntry child : children) {
                     String converted = convert(child.getName());
-                    if (value.compareTo(converted) > 0
-                        || (lpr.lastIncluding && value.equals(converted))) {
+                    if (predicate.apply(converted)) {
                         // here we are let's start counting
                         v = new CountingNodeVisitor(max);
                         v.visit(content.getChildNode(child.getName()));
@@ -435,7 +525,7 @@ public class OrderedContentMirrorStoreSt
         }
         return count;
     }
-    
+        
     /**
      * wrap an {@code Iterable<ChildNodeEntry>} in something that can be 
understood by the Query
      * Engine
@@ -707,17 +797,20 @@ public class OrderedContentMirrorStoreSt
     private static class BetweenIterable extends SeekedIterable {
         private String lastKey;
         private boolean lastInclude;
+        private OrderDirection direction;
         
-        public BetweenIterable(NodeState index, ChildNodeEntry first, String 
lastKey,
-                               boolean lastInclude) {
+        public BetweenIterable(final NodeState index, final ChildNodeEntry 
first,
+                               final String lastKey, final boolean lastInclude,
+                               final OrderDirection direction) {
             super(index, first);
             this.lastKey = lastKey;
             this.lastInclude = lastInclude;
+            this.direction = direction;
         }
 
         @Override
         public Iterator<ChildNodeEntry> iterator() {
-            return new BetweenIterator(index, start, first, lastKey, 
lastInclude);
+            return new BetweenIterator(index, start, first, lastKey, 
lastInclude, direction);
         }
     }
 
@@ -725,9 +818,8 @@ public class OrderedContentMirrorStoreSt
      * iterator for iterating in the cases of BETWEEN queries.
      */
     private static class BetweenIterator extends SeekedIterator {
-        private String lastKey;
-        private boolean lastInclude;
-
+        private Predicate<String> condition;
+        
         /**
          * @param index the current index content {@code :index}
          * @param start the {@code :start} node
@@ -735,11 +827,22 @@ public class OrderedContentMirrorStoreSt
          * @param lastKey the last key to be returned
          * @param lastInclude whether including the last key or not. 
          */
-        public BetweenIterator(NodeState index, NodeState start, 
ChildNodeEntry first,
-                               String lastKey, boolean lastInclude) {
+        public BetweenIterator(final NodeState index, final NodeState start,
+                               final ChildNodeEntry first, final String 
lastKey,
+                               final boolean lastInclude, final OrderDirection 
direction) {
             super(index, start, first);
-            this.lastInclude = lastInclude;
-            this.lastKey = lastKey;
+            this.condition = new Predicate<String>() {
+                private String v = lastKey;
+                private boolean i = lastInclude;
+                private OrderDirection d = direction;
+                
+                @Override
+                public boolean apply(String input) {
+                    return d.equals(OrderDirection.ASC) 
+                        ? v.compareTo(input) > 0 || (i && v.equals(input))
+                        : v.compareTo(input) < 0 || (i && v.equals(input));
+                }
+            };
         }
 
         @Override
@@ -749,10 +852,9 @@ public class OrderedContentMirrorStoreSt
 
             if (name != null && next) {
                 name = convert(name);
-                next = next && (lastKey.compareTo(name) > 0 || (lastInclude && 
lastKey
-                    .equals(name)));
+                next = next && condition.apply(name);
             }
             return next;
         }
     }
-}
\ No newline at end of file
+}

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java?rev=1595856&r1=1595855&r2=1595856&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java
 Mon May 19 12:03:29 2014
@@ -23,6 +23,7 @@ import static org.apache.jackrabbit.JcrC
 
 import java.text.ParseException;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -40,6 +41,8 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
@@ -47,6 +50,9 @@ import com.google.common.collect.Lists;
 
 
 public class OrderedPropertyIndexDescendingQueryTest extends 
BasicOrderedPropertyIndexQueryTest {
+    private static final Logger LOG = LoggerFactory
+        .getLogger(OrderedPropertyIndexDescendingQueryTest.class);
+    
     @Override
     protected void createTestIndexNode() throws Exception {
         Tree index = root.getTree("/");
@@ -150,19 +156,27 @@ public class OrderedPropertyIndexDescend
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
         Calendar start = midnightFirstJan2013();
-        addChildNodes(
+        List<ValuePathTuple> nodes = addChildNodes(
             generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
         root.commit();
 
         Calendar searchForCalendar = (Calendar) start.clone();
         searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
         String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+        
+        // re-sorting descending for matching the actual index direction
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.GreaterThanPredicate(searchFor)).iterator();
+
         Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
             PropertyValues.newDate(searchFor));
         Iterator<? extends ResultRow> results = executeQuery(
             String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, 
filter).getRows()
             .iterator();
-        assertFalse("We should not return any results as of the cost", 
results.hasNext());
+
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("no more results expected", results.hasNext());
 
         setTravesalEnabled(true);
     }
@@ -186,19 +200,27 @@ public class OrderedPropertyIndexDescend
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
         Calendar start = midnightFirstJan2013();
-        addChildNodes(
+        List<ValuePathTuple> nodes = addChildNodes(
             generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
         root.commit();
 
         Calendar searchForCalendar = (Calendar) start.clone();
         searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
         String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+        
+        // re-sorting descending for matching the actual index direction
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.GreaterThanPredicate(searchFor, 
true)).iterator();
+
         Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
             PropertyValues.newDate(searchFor));
         Iterator<? extends ResultRow> results = executeQuery(
             String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, 
filter).getRows()
             .iterator();
-        assertFalse("We should not return any results as of the cost", 
results.hasNext());
+
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("no more results expected", results.hasNext());
 
         setTravesalEnabled(true);
     }
@@ -306,18 +328,226 @@ public class OrderedPropertyIndexDescend
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
         Calendar start = midnightFirstJan2013();
-        addChildNodes(generateOrderedDates(NUMBER_OF_NODES, direction, start), 
test, direction,
-            Type.DATE);
+        List<ValuePathTuple> nodes = addChildNodes(
+            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
         root.commit();
 
         Calendar searchForCalendar = (Calendar) start.clone();
         searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
         String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+        
+        // re-sorting descending for matching the actual index direction
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.GreaterThanPredicate(searchFor, 
true)).iterator();
+
         Iterator<? extends ResultRow> results = 
executeQuery(String.format(query, searchFor), SQL2,
             null).getRows().iterator();
-        assertFalse("the index should not be used in this case", 
results.hasNext());
+
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("no more results expecrted", results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+    
+    @Test
+    public void queryBetweenNoIncludes() throws Exception {
+        setTravesalEnabled(false);
+
+        final OrderDirection direction = OrderDirection.ASC;
+        final String query = "SELECT * FROM [nt:base] WHERE " + 
ORDERED_PROPERTY + "> $start AND "
+                             + ORDERED_PROPERTY + " < $end";
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initialising the data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        Calendar start = midnightFirstJan2013();
+
+        List<ValuePathTuple> nodes = addChildNodes(
+            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
+        root.commit();
+
+        Calendar searchForCalendarStart = (Calendar) start.clone();
+        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
+        String searchForStart = 
ISO_8601_2000.format(searchForCalendarStart.getTime());
+
+        Calendar endCalendar = Calendar.getInstance();
+        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 
1).getValue()));
+        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
+        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+
+        Map<String, PropertyValue> filter = ImmutableMap.of("start",
+            PropertyValues.newDate(searchForStart), "end", 
PropertyValues.newDate(searchForEnd));
+        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, 
filter).getRows()
+            .iterator();
+
+        // re-sorting according to the actual index
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
false, false))
+            .iterator();
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("--- added nodes");
+            for (ValuePathTuple n : nodes) {
+                LOG.debug("{}", n);
+            }
+            LOG.debug("--- expected list");
+            while (filtered.hasNext()) {
+                LOG.debug("{}", filtered.next());
+            }
+            filtered = Iterables.filter(nodes,
+                new ValuePathTuple.BetweenPredicate(searchForStart, 
searchForEnd, false, false))
+                .iterator();
+        }
+        
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throuhg all the results", 
results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+    
+    @Test
+    public void queryBetweenIncludeBoth() throws Exception {
+        setTravesalEnabled(false);
+
+        final OrderDirection direction = OrderDirection.ASC;
+        final String query = "SELECT * FROM [nt:base] WHERE " + 
ORDERED_PROPERTY + ">= $start AND "
+                             + ORDERED_PROPERTY + " <= $end";
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initialising the data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        Calendar start = midnightFirstJan2013();
+
+        List<ValuePathTuple> nodes = addChildNodes(
+            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
+        root.commit();
+        
+        Calendar searchForCalendarStart = (Calendar) start.clone();
+        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
+        String searchForStart = 
ISO_8601_2000.format(searchForCalendarStart.getTime());
+
+        Calendar endCalendar = Calendar.getInstance();
+        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 
1).getValue()));
+        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
+        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+
+        Map<String, PropertyValue> filter = ImmutableMap.of("start",
+            PropertyValues.newDate(searchForStart), "end", 
PropertyValues.newDate(searchForEnd));
+        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, 
filter).getRows()
+            .iterator();
+
+        // re-sorting according to the actual index
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
true, true))
+            .iterator();
+        
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throuhg all the results", 
results.hasNext());
 
         setTravesalEnabled(true);
 
     }
+
+    @Test
+    public void queryBetweenIncludeHigher() throws Exception {
+        setTravesalEnabled(false);
+
+        final OrderDirection direction = OrderDirection.ASC;
+        final String query = "SELECT * FROM [nt:base] WHERE " + 
ORDERED_PROPERTY + "> $start AND "
+                             + ORDERED_PROPERTY + " <= $end";
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initialising the data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        Calendar start = midnightFirstJan2013();
+
+        List<ValuePathTuple> nodes = addChildNodes(
+            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
+        root.commit();
+        
+        Calendar searchForCalendarStart = (Calendar) start.clone();
+        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
+        String searchForStart = 
ISO_8601_2000.format(searchForCalendarStart.getTime());
+
+        Calendar endCalendar = Calendar.getInstance();
+        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 
1).getValue()));
+        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
+        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+
+        Map<String, PropertyValue> filter = ImmutableMap.of("start",
+            PropertyValues.newDate(searchForStart), "end", 
PropertyValues.newDate(searchForEnd));
+        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, 
filter).getRows()
+            .iterator();
+
+        // re-sorting according to the actual index
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
false, true))
+            .iterator();
+        
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throuhg all the results", 
results.hasNext());
+
+        setTravesalEnabled(true);
+
+    }
+    
+    @Test
+    public void queryBetweenIncludeLower() throws Exception {
+        setTravesalEnabled(false);
+
+        final OrderDirection direction = OrderDirection.ASC;
+        final String query = "SELECT * FROM [nt:base] WHERE " + 
ORDERED_PROPERTY + ">= $start AND "
+                             + ORDERED_PROPERTY + " < $end";
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initialising the data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        Calendar start = midnightFirstJan2013();
+
+        List<ValuePathTuple> nodes = addChildNodes(
+            generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
+        root.commit();
+
+        Calendar searchForCalendarStart = (Calendar) start.clone();
+        searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
+        String searchForStart = 
ISO_8601_2000.format(searchForCalendarStart.getTime());
+
+        Calendar endCalendar = Calendar.getInstance();
+        endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 
1).getValue()));
+        endCalendar.add(Calendar.HOUR_OF_DAY, -36);
+        String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+
+        Map<String, PropertyValue> filter = ImmutableMap.of("start",
+            PropertyValues.newDate(searchForStart), "end", 
PropertyValues.newDate(searchForEnd));
+        Iterator<? extends ResultRow> results = executeQuery(query, SQL2, 
filter).getRows()
+            .iterator();
+
+        // re-sorting according to the actual index
+        Collections.sort(nodes, Collections.reverseOrder());
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
true, false))
+            .iterator();
+
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throuhg all the results", 
results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java?rev=1595856&r1=1595855&r2=1595856&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java
 Mon May 19 12:03:29 2014
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertNot
 
 import java.text.ParseException;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -64,8 +65,12 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class OrderedPropertyIndexQueryTest extends 
BasicOrderedPropertyIndexQueryTest {
+    private static final Logger LOG = 
LoggerFactory.getLogger(OrderedPropertyIndexQueryTest.class);
+    
     private static final EditorHook HOOK = new EditorHook(new 
IndexUpdateProvider(
         new OrderedPropertyIndexEditorProvider()));
 
@@ -242,19 +247,36 @@ public class OrderedPropertyIndexQueryTe
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
         Calendar start = midnightFirstJan2013();
-        addChildNodes(
+        List<ValuePathTuple> nodes = addChildNodes(
                 generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
         root.commit();
 
         Calendar searchForCalendar = (Calendar) start.clone();
         searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
         String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+
+        // re-sorting ascending as the index is ASC and the results will be 
returned as ASC
+        Collections.sort(nodes);
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.LessThanPredicate(searchFor, false)).iterator();
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("-- Expected results:");
+            while (filtered.hasNext()) {
+                LOG.debug("{}", filtered.next());
+            }
+            // re-initialising the filtered for the test
+            filtered = Iterables.filter(nodes,
+                new ValuePathTuple.LessThanPredicate(searchFor, 
false)).iterator();
+        }
+
         Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
                 PropertyValues.newDate(searchFor));
         Iterator<? extends ResultRow> results = executeQuery(
             String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, 
filter).getRows()
             .iterator();
-        assertFalse("We should have no results as of the cost and index 
direction", results.hasNext());
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throught all the results", 
results.hasNext());
 
         setTravesalEnabled(true);
     }
@@ -281,19 +303,27 @@ public class OrderedPropertyIndexQueryTe
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
         Calendar start = midnightFirstJan2013();
-        addChildNodes(
+        List<ValuePathTuple> nodes = addChildNodes(
             generateOrderedDates(NUMBER_OF_NODES, direction, start), test, 
direction, Type.DATE);
         root.commit();
 
         Calendar searchForCalendar = (Calendar) start.clone();
         searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
         String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+        
+        // re-sorting ascending as the index is ASC and the results will be 
returned as ASC
+        Collections.sort(nodes);
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.LessThanPredicate(searchFor, true)).iterator();
+        
         Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
             PropertyValues.newDate(searchFor));
         Iterator<? extends ResultRow> results = executeQuery(
             String.format(query, ORDERED_PROPERTY, ORDERED_PROPERTY), SQL2, 
filter).getRows()
             .iterator();
-        assertFalse("We should have no results as of the cost and index 
direction", results.hasNext());
+        
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throught all the results", 
results.hasNext());
 
         setTravesalEnabled(true);
     }
@@ -768,11 +798,6 @@ public class OrderedPropertyIndexQueryTe
         List<ValuePathTuple> nodes = addChildNodes(
             generateOrderedDates(10, direction, start), test, direction, 
Type.DATE);
         root.commit();
-
-        for (ValuePathTuple n : nodes) {
-            n.toString();
-            // System.out.println("+++" + n);
-        }
         
         Calendar searchForCalendarStart = (Calendar) start.clone();
         searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
@@ -792,9 +817,6 @@ public class OrderedPropertyIndexQueryTe
             new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
false, true))
             .iterator();
 
-        while (filtered.hasNext()) {
-            System.out.println("---" + filtered.next());
-        }
         filtered = Iterables.filter(nodes,
             new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
false, true))
             .iterator();
@@ -825,11 +847,6 @@ public class OrderedPropertyIndexQueryTe
         List<ValuePathTuple> nodes = addChildNodes(
             generateOrderedDates(10, direction, start), test, direction, 
Type.DATE);
         root.commit();
-
-        for (ValuePathTuple n : nodes) {
-            n.toString();
-            // System.out.println("+++" + n);
-        }
         
         Calendar searchForCalendarStart = (Calendar) start.clone();
         searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
@@ -849,9 +866,6 @@ public class OrderedPropertyIndexQueryTe
             new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
false, true))
             .iterator();
 
-        while (filtered.hasNext()) {
-            System.out.println("---" + filtered.next());
-        }
         filtered = Iterables.filter(nodes,
             new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, 
true, true))
             .iterator();
@@ -862,4 +876,4 @@ public class OrderedPropertyIndexQueryTe
         setTravesalEnabled(true);
 
     }
-}
\ No newline at end of file
+}

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java?rev=1595856&r1=1595855&r2=1595856&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java
 Mon May 19 12:03:29 2014
@@ -1331,7 +1331,7 @@ public class OrderedContentMirrorStorage
         // don't care about the actual results as long as we have something. 
We're reusing existing
         // code
         assertTrue(store.count(ascendingMeta, pr, maxNodeCount) > 0);
-        assertEquals(0, descendingStore.count(descendingMeta, pr, 
maxNodeCount));
+        assertTrue(descendingStore.count(ascendingMeta, pr, maxNodeCount) > 0);
 
         // '>='
         pr = new Filter.PropertyRestriction();
@@ -1342,7 +1342,7 @@ public class OrderedContentMirrorStorage
         // don't care about the actual results as long as we have something. 
We're reusing existing
         // code
         assertTrue(store.count(ascendingMeta, pr, maxNodeCount) > 0);
-        assertEquals(0, descendingStore.count(descendingMeta, pr, 
maxNodeCount));
+        assertTrue(descendingStore.count(ascendingMeta, pr, maxNodeCount) > 0);
 
         // '<'
         pr = new Filter.PropertyRestriction();
@@ -1353,7 +1353,7 @@ public class OrderedContentMirrorStorage
         // don't care about the actual results as long as we have something. 
We're reusing existing
         // code
         assertTrue(descendingStore.count(descendingMeta, pr, maxNodeCount) > 
0);
-        assertEquals(0, store.count(ascendingMeta, pr, maxNodeCount));
+        assertTrue(store.count(ascendingMeta, pr, maxNodeCount) > 0);
 
         // when no conditions has been asked but just an ORDER BY
         pr = null;


Reply via email to