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=1578779&r1=1578778&r2=1578779&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
 Tue Mar 18 08:25:57 2014
@@ -19,52 +19,53 @@ package org.apache.jackrabbit.oak.plugin
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
 import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+import static 
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
+import static org.junit.Assert.assertNotNull;
 
 import java.text.ParseException;
+import java.util.Calendar;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
 import javax.jcr.RepositoryException;
 
+import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.api.ResultRow;
 import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
 import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
 import 
org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex.OrderDirection;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.query.ast.Operator;
+import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.Ignore;
 import org.junit.Test;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 
 public class OrderedPropertyIndexQueryTest extends 
BasicOrderedPropertyIndexQueryTest {
-    /**
-     * testing for asserting the right comparison behaviour of the custom class
-     */
-    @Test
-    public void valuePathTupleComparison() {
-        try {
-            new ValuePathTuple("value", "path").compareTo(null);
-            fail("It should have raised a NPE");
-        } catch (NullPointerException e) {
-            // so far so good
-        }
-        assertEquals(0, (new ValuePathTuple("value", "path")).compareTo(new 
ValuePathTuple("value", "path")));
-        assertEquals(-1, (new ValuePathTuple("value", "path")).compareTo(new 
ValuePathTuple("value1", "path")));
-        assertEquals(-1, (new ValuePathTuple("value1", "path")).compareTo(new 
ValuePathTuple("value1", "path1")));
-        assertEquals(1, (new ValuePathTuple("value1", "path")).compareTo(new 
ValuePathTuple("value", "path")));
-        assertEquals(1, (new ValuePathTuple("value1", "path1")).compareTo(new 
ValuePathTuple("value1", "path")));
-
-        assertEquals(-1,
-            (new ValuePathTuple("value000", "/test/n1")).compareTo(new 
ValuePathTuple("value001", "/test/n0")));
-        assertEquals(1,
-            (new ValuePathTuple("value001", "/test/n0")).compareTo(new 
ValuePathTuple("value000", "/test/n1")));
-    }
+    private static final EditorHook HOOK = new EditorHook(new 
IndexUpdateProvider(
+        new OrderedPropertyIndexEditorProvider()));
 
     @Override
     protected void createTestIndexNode() throws Exception {
@@ -90,7 +91,8 @@ public class OrderedPropertyIndexQueryTe
 
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
-        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test, OrderDirection.ASC);
+        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
+            OrderDirection.ASC, Type.STRING);
         root.commit();
 
         // querying
@@ -117,21 +119,441 @@ public class OrderedPropertyIndexQueryTe
 
         Tree rTree = root.getTree("/");
         Tree test = rTree.addChild("test");
-        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test, OrderDirection.ASC);
+        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
+            OrderDirection.ASC, Type.STRING);
         root.commit();
 
         // getting the middle of the random list of nodes.
-        ValuePathTuple searchfor = nodes.get(NUMBER_OF_NODES / 2); 
-        Map<String, PropertyValue> filter = ImmutableMap
-            .of(ORDERED_PROPERTY, 
PropertyValues.newString(searchfor.getValue()));
+        ValuePathTuple searchfor = nodes.get(NUMBER_OF_NODES / 2);
+        
+        Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
+            PropertyValues.newString(searchfor.getValue()));
         String query = "SELECT * FROM [%s] WHERE %s=$%s";
         Iterator<? extends ResultRow> results = executeQuery(
-            String.format(query, NT_UNSTRUCTURED, ORDERED_PROPERTY, 
ORDERED_PROPERTY), SQL2, filter).getRows()
-            .iterator();
+            String.format(query, NT_UNSTRUCTURED, ORDERED_PROPERTY, 
ORDERED_PROPERTY), SQL2, filter)
+            .getRows().iterator();
         assertTrue("one element is expected", results.hasNext());
         assertEquals("wrong path returned", searchfor.getPath(), 
results.next().getPath());
         assertFalse("there should be not any more items", results.hasNext());
 
         setTravesalEnabled(true);
     }
-}
+    
+    /**
+     * test the range query in case of '>' condition
+     * 
+     * @throws CommitFailedException
+     * @throws ParseException
+     */
+    @Test @Ignore("Disabling for now. Integration with OAK-622 and 
prioritising.")
+    public void queryGreaterThan() throws CommitFailedException, 
ParseException {
+        setTravesalEnabled(false);
+
+        final OrderDirection direction = OrderDirection.ASC;
+        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s > $%s";
+
+        // 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 searchForCalendar = (Calendar) start.clone();
+        searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
+        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+        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();
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+            new ValuePathTuple.GreaterThanPredicate(searchFor)).iterator();
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throuhg all the results", 
results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+    
+    /**
+     * test the range query in case of '>=' condition
+     * @throws CommitFailedException 
+     * @throws ParseException 
+     */
+    @Test @Ignore("Disabling for now. Integration with OAK-622 and 
prioritising.")
+    public void queryGreaterEqualThan() throws CommitFailedException, 
ParseException {
+        setTravesalEnabled(false);
+
+        final OrderDirection direction = OrderDirection.ASC;
+        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s >= $%s";
+
+        // 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 searchForCalendar = (Calendar) start.clone();
+        searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
+        String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+        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();
+        Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
+                new ValuePathTuple.GreaterThanPredicate(searchFor, true))
+                .iterator();
+        assertRightOrder(Lists.newArrayList(filtered), results);
+        assertFalse("We should have looped throuhg all the results", 
results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+
+    /**
+     * test the range query in case of '<' condition
+     * 
+     * in this case as we're ascending we're expecting an empty resultset with 
the proper
+     * provider. not the lowcost one.
+     * @throws Exception 
+     */
+    @Test @Ignore("Disabling for now. Integration with OAK-622 and 
prioritising.")
+    public void queryLessThan() throws Exception {
+        initWithProperProvider();
+        setTravesalEnabled(false);
+        final OrderDirection direction = OrderDirection.DESC;
+        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s < $%s";
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initialising the data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        Calendar start = midnightFirstJan2013();
+        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());
+        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());
+
+        setTravesalEnabled(true);
+    }
+
+    /**
+     * test the range query in case of '<=' condition
+     * 
+     * in this case as we're ascending we're expecting an empty resultset with 
the proper
+     * provider. not the lowcost one.
+     * @throws Exception 
+     */
+    @Test @Ignore("Disabling for now. Integration with OAK-622 and 
prioritising.")
+    public void queryLessEqualThan() throws Exception {
+        initWithProperProvider();
+        initWithProperProvider();
+        setTravesalEnabled(false);
+        final OrderDirection direction = OrderDirection.DESC;
+        final String query = "SELECT * FROM [nt:base] AS n WHERE n.%s <= $%s";
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initialising the data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        Calendar start = midnightFirstJan2013();
+        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());
+        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());
+
+        setTravesalEnabled(true);
+    }
+    
+    @Test
+    public void queryAllEntriesWithOrderBy() throws CommitFailedException, 
ParseException, RepositoryException {
+        setTravesalEnabled(false);
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
+            OrderDirection.ASC, Type.STRING);
+        root.commit();
+
+        // querying
+        Iterator<? extends ResultRow> results;
+        String query = String.format(
+            "SELECT * from [nt:base] WHERE %s IS NOT NULL ORDER BY %s",
+            ORDERED_PROPERTY,
+            ORDERED_PROPERTY);
+        results = executeQuery(query, SQL2, null)
+            .getRows().iterator();
+        assertRightOrder(nodes, results);
+
+        setTravesalEnabled(true);
+    }
+
+    @Test
+    public void orderByQueryNoWhere() throws CommitFailedException, 
ParseException {
+        setTravesalEnabled(false);
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
+            OrderDirection.ASC, Type.STRING);
+        root.commit();
+
+        // querying
+        Iterator<? extends ResultRow> results;
+        String query = String.format(
+            "SELECT * from [nt:base] ORDER BY %s",
+            ORDERED_PROPERTY);
+        results = executeQuery(query, SQL2, null)
+            .getRows().iterator();
+        assertRightOrder(nodes, results);
+
+        setTravesalEnabled(true);
+    }
+        
+    @Test
+    public void planOderByNoWhere() throws IllegalArgumentException, 
RepositoryException,
+                                   CommitFailedException {
+
+        NodeBuilder root = EmptyNodeState.EMPTY_NODE.builder();
+
+        
IndexUtils.createIndexDefinition(root.child(IndexConstants.INDEX_DEFINITIONS_NAME),
+            TEST_INDEX_NAME, false, ImmutableList.of(ORDERED_PROPERTY), null, 
OrderedIndex.TYPE,
+            ImmutableMap.<String, String> of());
+
+        NodeState before = root.getNodeState();
+        final OrderDirection direction = OrderDirection.ASC;
+        final QueryIndex.OrderEntry.Order order = 
OrderDirection.ASC.equals(direction) ? QueryIndex.OrderEntry.Order.ASCENDING
+                                                                               
       : QueryIndex.OrderEntry.Order.DESCENDING;
+
+        List<String> values = generateOrderedValues(NUMBER_OF_NODES, 
direction);
+        addChildNodes(values, root, Type.STRING);
+        NodeState after = root.getNodeState();
+
+        NodeState indexed = HOOK.processCommit(before, after, 
CommitInfo.EMPTY);
+
+        final OrderedPropertyIndex index = new OrderedPropertyIndex();
+        final String nodeTypeName = JcrConstants.NT_BASE;
+
+        Filter filter = createFilter(indexed, nodeTypeName);
+
+        List<QueryIndex.OrderEntry> sortOrder = 
ImmutableList.of(createOrderEntry(ORDERED_PROPERTY,
+            order));
+        List<IndexPlan> plans = index.getPlans(filter, sortOrder, indexed);
+
+        assertNotNull(plans);
+        assertEquals(1, plans.size());
+        IndexPlan p = plans.get(0);
+        assertTrue(p.getEstimatedEntryCount() > 0);
+        assertNotNull(p.getSortOrder());
+        assertEquals(1, p.getSortOrder().size());
+        QueryIndex.OrderEntry oe = p.getSortOrder().get(0);
+        assertNotNull(oe);
+        assertEquals(ORDERED_PROPERTY, oe.getPropertyName());
+        assertEquals(QueryIndex.OrderEntry.Order.ASCENDING, oe.getOrder());
+    }
+    
+    @Test
+    public void queryOrderByNonIndexedProperty() throws CommitFailedException, 
ParseException {
+        setTravesalEnabled(false);
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
+            OrderDirection.ASC, Type.STRING);
+        root.commit();
+
+        // querying
+        Iterator<? extends ResultRow> results;
+        String query = "SELECT * from [nt:base] ORDER BY somethingnotindexed";
+        results = executeQuery(query, SQL2, null)
+            .getRows().iterator();
+        assertFalse("An empty resultset is expected", results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+
+    private static FilterImpl createFilter(NodeState indexed, String 
nodeTypeName) {
+        NodeState system = indexed.getChildNode(JCR_SYSTEM);
+        NodeState types = system.getChildNode(JCR_NODE_TYPES);
+        NodeState type = types.getChildNode(nodeTypeName);
+        SelectorImpl selector = new SelectorImpl(type, nodeTypeName);
+        return new FilterImpl(selector, "SELECT * FROM [" + nodeTypeName + 
"]");
+    }
+
+    private static QueryIndex.OrderEntry createOrderEntry(String property,
+                                                          
QueryIndex.OrderEntry.Order order) {
+        return new QueryIndex.OrderEntry(property, Type.UNDEFINED, order);
+    }
+
+    @Test
+    public void planOrderByNonIndexedProperty() throws 
IllegalArgumentException,
+                                               RepositoryException, 
CommitFailedException {
+        NodeBuilder root = EmptyNodeState.EMPTY_NODE.builder();
+
+        
IndexUtils.createIndexDefinition(root.child(IndexConstants.INDEX_DEFINITIONS_NAME),
+            TEST_INDEX_NAME, false, ImmutableList.of(ORDERED_PROPERTY), null, 
OrderedIndex.TYPE,
+            ImmutableMap.<String, String> of());
+
+        NodeState before = root.getNodeState();
+        final OrderDirection direction = OrderDirection.ASC;
+        final QueryIndex.OrderEntry.Order order = 
OrderDirection.ASC.equals(direction) ? QueryIndex.OrderEntry.Order.ASCENDING
+                                                                               
       : QueryIndex.OrderEntry.Order.DESCENDING;
+        List<String> values = generateOrderedValues(NUMBER_OF_NODES, 
direction);
+        addChildNodes(values, root, Type.STRING);
+        NodeState after = root.getNodeState();
+
+        NodeState indexed = HOOK.processCommit(before, after, 
CommitInfo.EMPTY);
+
+        final OrderedPropertyIndex index = new OrderedPropertyIndex();
+        final String nodeTypeName = JcrConstants.NT_BASE;
+        Filter filter = createFilter(indexed, nodeTypeName);
+
+        List<QueryIndex.OrderEntry> sortOrder = 
ImmutableList.of(createOrderEntry(
+            "somethingnotindexed", order));
+
+        List<IndexPlan> plans = index.getPlans(filter, sortOrder, indexed);
+
+        assertNotNull(plans);
+        assertEquals(0, plans.size());
+    }
+    
+    /**
+     * tests the output of a plan where the query is asked with where 
conditions that are not indexed
+     * but the ORDER BY are on the indexed property
+     * 
+     * eg: SELECT * FROM [nt:base] WHERE pinned=1 ORDER BY lastModified
+     * 
+     * @throws RepositoryException 
+     * @throws IllegalArgumentException 
+     * @throws CommitFailedException 
+     */
+    @Test
+    public void planOrderAndWhereMixed() throws IllegalArgumentException, 
RepositoryException, CommitFailedException {
+        NodeBuilder root = EmptyNodeState.EMPTY_NODE.builder();
+
+        
IndexUtils.createIndexDefinition(root.child(IndexConstants.INDEX_DEFINITIONS_NAME),
+            TEST_INDEX_NAME, false, ImmutableList.of(ORDERED_PROPERTY), null, 
OrderedIndex.TYPE,
+            ImmutableMap.<String, String> of());
+
+        NodeState before = root.getNodeState();
+        final OrderDirection direction = OrderDirection.ASC;
+        final QueryIndex.OrderEntry.Order order = 
OrderDirection.ASC.equals(direction) ? QueryIndex.OrderEntry.Order.ASCENDING
+                                                                               
       : QueryIndex.OrderEntry.Order.DESCENDING;
+        List<String> values = generateOrderedValues(NUMBER_OF_NODES, 
direction);
+        addChildNodes(values, root, Type.STRING);
+        NodeState after = root.getNodeState();
+
+        NodeState indexed = HOOK.processCommit(before, after, 
CommitInfo.EMPTY);
+
+        final OrderedPropertyIndex index = new OrderedPropertyIndex();
+        final String nodeTypeName = JcrConstants.NT_BASE;
+        FilterImpl filter = createFilter(indexed, nodeTypeName);
+        filter.restrictProperty("somethingNotIndexed", Operator.EQUAL, 
PropertyValues.newLong(1L));
+        
+        List<QueryIndex.OrderEntry> sortOrder = 
ImmutableList.of(createOrderEntry(
+            ORDERED_PROPERTY, order));
+
+        List<IndexPlan> plans = index.getPlans(filter, sortOrder, indexed);
+        assertNotNull(plans);
+        assertEquals(1, plans.size());
+        IndexPlan p = plans.get(0);
+        assertTrue(p.getEstimatedEntryCount() > 0);
+        assertNotNull(p.getSortOrder());
+        assertEquals(1, p.getSortOrder().size());
+        assertEquals(QueryIndex.OrderEntry.Order.ASCENDING, p.getSortOrder()
+                .get(0).getOrder());
+    }
+    
+    /**
+     * query the index in case of mixed situation
+     * 
+     * eg: SELECT * FROM [nt:base] WHERE pinned=1 ORDER BY lastModified
+     * 
+     * @throws RepositoryException 
+     * @throws IllegalArgumentException 
+     * @throws CommitFailedException 
+     * @throws ParseException 
+     */
+    @Test
+    public void queryOrderAndWhereMixed() throws IllegalArgumentException, 
RepositoryException, CommitFailedException, ParseException {
+        setTravesalEnabled(false);
+
+        // index automatically created by the framework:
+        // {@code createTestIndexNode()}
+
+        // initiate the repo with some data
+        Tree rTree = root.getTree("/");
+        Tree test = rTree.addChild("test");
+        List<ValuePathTuple> nodes = 
addChildNodes(generateOrderedValues(NUMBER_OF_NODES), test,
+            OrderDirection.ASC, Type.STRING);
+        root.commit();
+
+        String where = "wholetthedogsout";
+        String value = "woof-woof-woof-woof";
+        
+        // let's set the property that will have to be queried only on 2 nodes
+        Tree t = root.getTree(nodes.get(0).getPath());
+        t.setProperty(where, value);
+        t = root.getTree(nodes.get(1).getPath());
+        t.setProperty(where, value);
+        root.commit();
+        
+        // querying
+        Iterator<? extends ResultRow> results;
+        String query = String.format(
+            "SELECT * from [nt:base] WHERE %s=$%s ORDER BY %s",
+            where,
+            where,
+            ORDERED_PROPERTY
+            );
+        Map<String, PropertyValue> filter = ImmutableMap.of(
+            where, PropertyValues.newString(value)
+            );
+        results = executeQuery(query, SQL2, filter)
+            .getRows().iterator();
+        assertTrue(results.hasNext());
+
+        setTravesalEnabled(true);
+    }
+
+}
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTuple.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTuple.java?rev=1578779&r1=1578778&r2=1578779&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTuple.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTuple.java
 Tue Mar 18 08:25:57 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.property;
 
+import com.google.common.base.Predicate;
+
 
 /**
  * convenience orderable object that represents a tuple of values and paths
@@ -27,6 +29,64 @@ public class ValuePathTuple implements C
     private String value;
     private String path;
 
+    /**
+     * convenience Predicate for easing the testing
+     */
+    public static class GreaterThanPredicate implements 
Predicate<ValuePathTuple> {
+        /** 
+         * the value for comparison 
+         */
+        private String value;
+        
+        /**
+         * whether we should include the value in the result
+         */
+        private boolean include;
+        
+        public GreaterThanPredicate(String value) {
+            this.value = value;
+        }
+
+        public GreaterThanPredicate(String value, boolean include) {
+            this.value = value;
+            this.include = include;
+        }
+
+        @Override
+        public boolean apply(ValuePathTuple arg0) {
+            return (value.compareTo(arg0.getValue()) < 0)
+                   || (include && value.equals(arg0.getValue()));
+        }
+    };
+    
+    public static class LessThanPredicate implements Predicate<ValuePathTuple> 
{
+        /** 
+         * the value for comparison 
+         */
+        private String value;
+        
+        /**
+         * whether we should include the value in the result
+         */
+        private boolean include;
+
+        public LessThanPredicate(String value) {
+            this.value = value;
+        }
+
+        public LessThanPredicate(String value, boolean include) {
+            this.value = value;
+            this.include = include;
+        }
+
+        @Override
+        public boolean apply(ValuePathTuple arg0) {
+            return (value.compareTo(arg0.getValue()) > 0)
+                || (include && value.equals(arg0.getValue()));
+        }
+        
+    }
+    
     ValuePathTuple(String value, String path) {
         this.value = value;
         this.path = path;
@@ -98,4 +158,14 @@ public class ValuePathTuple implements C
     public String getPath() {
         return path;
     }
-}
\ No newline at end of file
+
+    @Override
+    public String toString() {
+        return String.format(
+            "value: %s - path: %s - hash: %s",
+            value,
+            path,
+            super.toString()
+        );
+    }
+}

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTupleTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTupleTest.java?rev=1578779&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTupleTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePathTupleTest.java
 Tue Mar 18 08:25:57 2014
@@ -0,0 +1,152 @@
+/*
+ * 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.plugins.index.property;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+/**
+ * tests the utility class ValuePathTuple
+ */
+public class ValuePathTupleTest {
+    /**
+     * testing for asserting the right comparison behaviour of the custom class
+     */
+    @Test
+    public void valuePathTupleComparison() {
+        try {
+            new ValuePathTuple("value", "path").compareTo(null);
+            fail("It should have raised a NPE");
+        } catch (NullPointerException e) {
+            // so far so good
+        }
+        assertEquals(0,
+            (new ValuePathTuple("value", "path")).compareTo(new 
ValuePathTuple("value", "path")));
+        assertEquals(-1,
+            (new ValuePathTuple("value", "path")).compareTo(new 
ValuePathTuple("value1", "path")));
+        assertEquals(-1,
+            (new ValuePathTuple("value1", "path")).compareTo(new 
ValuePathTuple("value1", "path1")));
+        assertEquals(1,
+            (new ValuePathTuple("value1", "path")).compareTo(new 
ValuePathTuple("value", "path")));
+        assertEquals(1,
+            (new ValuePathTuple("value1", "path1")).compareTo(new 
ValuePathTuple("value1", "path")));
+
+        assertEquals(-1, (new ValuePathTuple("value000", 
"/test/n1")).compareTo(new ValuePathTuple(
+            "value001", "/test/n0")));
+        assertEquals(1, (new ValuePathTuple("value001", 
"/test/n0")).compareTo(new ValuePathTuple(
+            "value000", "/test/n1")));
+    }
+
+    @Test
+    public void greaterThanPredicate() {
+        List<ValuePathTuple> data = ImmutableList.of(new ValuePathTuple("a", 
"foobar"),
+            new ValuePathTuple("b", "foobar"), new ValuePathTuple("c", 
"foobar"),
+            new ValuePathTuple("d", "foobar"), new ValuePathTuple("e", 
"foobar"),
+            new ValuePathTuple("f", "foobar"));
+        Iterator<ValuePathTuple> filtered = Iterables.filter(data,
+            new ValuePathTuple.GreaterThanPredicate("b")).iterator();
+        assertTrue(filtered.hasNext());
+        assertEquals("c", filtered.next().getValue());
+        assertEquals("d", filtered.next().getValue());
+        assertEquals("e", filtered.next().getValue());
+        assertEquals("f", filtered.next().getValue());
+        assertFalse(filtered.hasNext());
+    }
+
+    @Test
+    public void greaterThanEqualaPredicate() {
+        List<ValuePathTuple> data = ImmutableList.of(new ValuePathTuple("a", 
"foobar"),
+            new ValuePathTuple("b", "foobar"), new ValuePathTuple("c", 
"foobar"),
+            new ValuePathTuple("d", "foobar"), new ValuePathTuple("e", 
"foobar"),
+            new ValuePathTuple("f", "foobar"));
+        Iterator<ValuePathTuple> filtered = Iterables.filter(data,
+            new ValuePathTuple.GreaterThanPredicate("b", true)).iterator();
+        assertTrue(filtered.hasNext());
+        assertEquals("b", filtered.next().getValue());
+        assertEquals("c", filtered.next().getValue());
+        assertEquals("d", filtered.next().getValue());
+        assertEquals("e", filtered.next().getValue());
+        assertEquals("f", filtered.next().getValue());
+        assertFalse(filtered.hasNext());
+    }
+    
+    @Test
+    public void lessThanPredicate() {
+        List<ValuePathTuple> data = ImmutableList.of(
+            new ValuePathTuple("a", "foobar"),
+            new ValuePathTuple("b", "foobar"), 
+            new ValuePathTuple("c", "foobar"),
+            new ValuePathTuple("d", "foobar"), 
+            new ValuePathTuple("e", "foobar"),
+            new ValuePathTuple("f", "foobar"));
+        Iterator<ValuePathTuple> filtered = Iterables.filter(data,
+            new ValuePathTuple.LessThanPredicate("e")).iterator();
+        assertTrue(filtered.hasNext());
+        assertEquals("a", filtered.next().getValue());
+        assertEquals("b", filtered.next().getValue());
+        assertEquals("c", filtered.next().getValue());
+        assertEquals("d", filtered.next().getValue());
+        assertFalse(filtered.hasNext());
+        
+        data = ImmutableList.of(
+            new ValuePathTuple("f", "foobar"),
+            new ValuePathTuple("e", "foobar"),
+            new ValuePathTuple("d", "foobar"), 
+            new ValuePathTuple("c", "foobar"),
+            new ValuePathTuple("b", "foobar"), 
+            new ValuePathTuple("a", "foobar")
+            );
+        filtered = Iterables.filter(data,
+            new ValuePathTuple.LessThanPredicate("e")).iterator();
+        assertTrue(filtered.hasNext());
+        assertEquals("d", filtered.next().getValue());
+        assertEquals("c", filtered.next().getValue());
+        assertEquals("b", filtered.next().getValue());
+        assertEquals("a", filtered.next().getValue());
+        assertFalse(filtered.hasNext());
+    }
+    
+    @Test
+    public void lessThanEqualPredicate() {
+        List<ValuePathTuple> data = ImmutableList.of(
+            new ValuePathTuple("a", "foobar"),
+            new ValuePathTuple("b", "foobar"), 
+            new ValuePathTuple("c", "foobar"),
+            new ValuePathTuple("d", "foobar"), 
+            new ValuePathTuple("e", "foobar"),
+            new ValuePathTuple("f", "foobar"));
+        Iterator<ValuePathTuple> filtered = Iterables.filter(data,
+            new ValuePathTuple.LessThanPredicate("e",true)).iterator();
+        assertTrue(filtered.hasNext());
+        assertEquals("a", filtered.next().getValue());
+        assertEquals("b", filtered.next().getValue());
+        assertEquals("c", filtered.next().getValue());
+        assertEquals("d", filtered.next().getValue());
+        assertEquals("e", filtered.next().getValue());
+        assertFalse(filtered.hasNext());
+    }
+}

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=1578779&r1=1578778&r2=1578779&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
 Tue Mar 18 08:25:57 2014
@@ -25,18 +25,29 @@ import static org.junit.Assert.assertFal
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.jcr.RepositoryException;
+
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
+import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex;
 import 
org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex.OrderDirection;
 import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.junit.Test;
 
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 
@@ -49,6 +60,7 @@ public class OrderedContentMirrorStorage
      */
     private static final String[] KEYS = new String[] { "donald", "goofy", 
"mickey", "minnie" };
     private static final Set<String> EMPTY_KEY_SET = newHashSet();
+    private static final NumberFormat NF = new DecimalFormat("00000");
 
     /**
      * checks that the fist item/key is inserted with an empty property 'next'
@@ -974,32 +986,6 @@ public class OrderedContentMirrorStorage
     }
     
     /**
-     * test the insert of 1 item in a descending order index. it should not 
really matter but just
-     * checking we don't break anything
-     * 
-     * expecting
-     * 
-     * <code>
-     *  :index : {
-     *      :start : { :next = n0 },
-     *      n0 : { :next = }
-     *  }
-     * </code>
-     */
-    @Test
-    public void descendingOrderInsert1item() {
-        IndexStoreStrategy store = new 
OrderedContentMirrorStoreStrategy(OrderDirection.DESC);
-        NodeBuilder index = EmptyNodeState.EMPTY_NODE.builder();
-        String n0 = KEYS[1];
-
-        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n0));
-        assertEquals(":start should point to the first node", n0, 
index.getChildNode(START)
-                                                                       
.getString(NEXT));
-        assertTrue("the first node should point nowhere",
-                   
Strings.isNullOrEmpty(index.getChildNode(n0).getString(NEXT)));
-    }
-    
-    /**
      * <p>test the insertion of 2 already ordered items</p>
      * 
      * <p>expected</p>
@@ -1029,42 +1015,6 @@ public class OrderedContentMirrorStorage
     }
     
     /**
-     * test the insert of 4 shuffled items in a descending ordered index
-     * 
-     * expected:
-     * 
-     * <code>
-     *      :index : {
-     *          :start : { :next= n1},
-     *          n0 : { :next= n3},  
-     *          n1 : { :next= n2},  
-     *          n2: { :next= n0},  
-     *          n3 : { :next= },  
-     *      }
-     * </code>
-     */
-    @Test
-    public void descendingOrderInsert4ShuffledItems() {
-        IndexStoreStrategy store = new 
OrderedContentMirrorStoreStrategy(OrderDirection.DESC);
-        NodeBuilder index = EmptyNodeState.EMPTY_NODE.builder();
-        String n0 = KEYS[1];
-        String n1 = KEYS[3];
-        String n2 = KEYS[2];
-        String n3 = KEYS[0];
-
-        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n0));
-        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n1));
-        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n2));
-        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n3));
-        assertEquals(":start should point to n1", n1, 
index.getChildNode(START).getString(NEXT));
-        assertEquals("n0 should point to n3", n3, 
index.getChildNode(n0).getString(NEXT));
-        assertEquals("n1 should point to n2", n2, 
index.getChildNode(n1).getString(NEXT));
-        assertEquals("n2 should point to n1", n0, 
index.getChildNode(n2).getString(NEXT));
-        assertTrue("n3 should point nowhere",
-                   
Strings.isNullOrEmpty(index.getChildNode(n3).getString(NEXT)));
-    }
-    
-    /**
      * Tests the insert of 4 items that will always have to be added at the 
beginning of the list.
      * Just to simulate the use-case of lastModified DESC.
      * 
@@ -1200,6 +1150,68 @@ public class OrderedContentMirrorStorage
     }
     
     /**
+     * test the insert of 1 item in a descending order index. it should not 
really matter but just
+     * checking we don't break anything
+     * 
+     * expecting
+     * 
+     * <code>
+     *  :index : {
+     *      :start : { :next = n0 },
+     *      n0 : { :next = }
+     *  }
+     * </code>
+     */
+    @Test
+    public void descendingOrderInsert1item() {
+        IndexStoreStrategy store = new 
OrderedContentMirrorStoreStrategy(OrderDirection.DESC);
+        NodeBuilder index = EmptyNodeState.EMPTY_NODE.builder();
+        String n0 = KEYS[1];
+
+        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n0));
+        assertEquals(":start should point to the first node", n0, 
index.getChildNode(START)
+                                                                       
.getString(NEXT));
+        assertTrue("the first node should point nowhere",
+                   
Strings.isNullOrEmpty(index.getChildNode(n0).getString(NEXT)));
+    }
+        
+    /**
+     * test the insert of 4 shuffled items in a descending ordered index
+     * 
+     * expected:
+     * 
+     * <code>
+     *      :index : {
+     *          :start : { :next= n1},
+     *          n0 : { :next= n3},  
+     *          n1 : { :next= n2},  
+     *          n2: { :next= n0},  
+     *          n3 : { :next= },  
+     *      }
+     * </code>
+     */
+    @Test
+    public void descendingOrderInsert4ShuffledItems() {
+        IndexStoreStrategy store = new 
OrderedContentMirrorStoreStrategy(OrderDirection.DESC);
+        NodeBuilder index = EmptyNodeState.EMPTY_NODE.builder();
+        String n0 = KEYS[1];
+        String n1 = KEYS[3];
+        String n2 = KEYS[2];
+        String n3 = KEYS[0];
+
+        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n0));
+        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n1));
+        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n2));
+        store.update(index, "/a/b", EMPTY_KEY_SET, newHashSet(n3));
+        assertEquals(":start should point to n1", n1, 
index.getChildNode(START).getString(NEXT));
+        assertEquals("n0 should point to n3", n3, 
index.getChildNode(n0).getString(NEXT));
+        assertEquals("n1 should point to n2", n2, 
index.getChildNode(n1).getString(NEXT));
+        assertEquals("n2 should point to n1", n0, 
index.getChildNode(n2).getString(NEXT));
+        assertTrue("n3 should point nowhere",
+                   
Strings.isNullOrEmpty(index.getChildNode(n3).getString(NEXT)));
+    }    
+        
+    /**
      * test the iteration of the descending index with 2 shuffled items
      * 
      * <code>
@@ -1244,4 +1256,108 @@ public class OrderedContentMirrorStorage
         assertEquals("Wrong entry returned", node0, entry.getNodeState());
         assertFalse("We should have be at the end of the list", it.hasNext());
     }
+
+    @Test
+    public void count() throws IllegalArgumentException, RepositoryException {
+        OrderedContentMirrorStoreStrategy store = new 
OrderedContentMirrorStoreStrategy();
+        OrderedContentMirrorStoreStrategy descendingStore = new 
OrderedContentMirrorStoreStrategy(OrderDirection.DESC);
+        final String orderedProperty = "fooprop";
+        final String testAscendingName = "testascending";
+        final String testDescendingName = "testdescending";
+        final int numberOfNodes = 1000;
+        final int maxNodeCount = 100;
+       
+        NodeBuilder builder = EmptyNodeState.EMPTY_NODE.builder();
+        
+        
IndexUtils.createIndexDefinition(builder.child(IndexConstants.INDEX_DEFINITIONS_NAME),
+            testAscendingName, false, ImmutableList.of(orderedProperty), null, 
OrderedIndex.TYPE,
+            ImmutableMap.<String, String> of());
+        
IndexUtils.createIndexDefinition(builder.child(IndexConstants.INDEX_DEFINITIONS_NAME),
+            testDescendingName, false, ImmutableList.of(orderedProperty), 
null, OrderedIndex.TYPE,
+            ImmutableMap.<String, String> of(OrderedIndex.DIRECTION, 
OrderDirection.DESC.getDirection()));
+
+        NodeBuilder ascendingContent = 
builder.getChildNode(IndexConstants.INDEX_DEFINITIONS_NAME)
+            
.getChildNode(testAscendingName).child(IndexConstants.INDEX_CONTENT_NODE_NAME);
+        NodeBuilder descendingContent = 
builder.getChildNode(IndexConstants.INDEX_DEFINITIONS_NAME)
+            
.getChildNode(testDescendingName).child(IndexConstants.INDEX_CONTENT_NODE_NAME);
+        
+        // adding some content under the index
+        for (int i = 0; i < numberOfNodes; i++) {
+            store.update(ascendingContent, "/foo/bar", EMPTY_KEY_SET, 
newHashSet("x" + NF.format(i)));
+            descendingStore.update(descendingContent, "/foo/bar", 
EMPTY_KEY_SET, newHashSet("x" + NF.format(i)));
+        }
+        
+        assertEquals("wrong number of nodes encountered", numberOfNodes,
+            
Iterables.size(store.getChildNodeEntries(ascendingContent.getNodeState())));
+        assertEquals("wrong number of nodes encountered", numberOfNodes,
+            
Iterables.size(descendingStore.getChildNodeEntries(descendingContent.getNodeState())));
+
+        NodeState ascendingMeta = 
builder.getChildNode(IndexConstants.INDEX_DEFINITIONS_NAME)
+            .getChildNode(testAscendingName).getNodeState(); 
+        NodeState descendingMeta = 
builder.getChildNode(IndexConstants.INDEX_DEFINITIONS_NAME)
+            .getChildNode(testDescendingName).getNodeState(); 
+
+        Filter.PropertyRestriction pr = null;
+        
+        // equality
+        String value = "x" + NF.format(11);
+        pr = new Filter.PropertyRestriction();
+        pr.first = PropertyValues.newString(value);
+        pr.last = PropertyValues.newString(value);
+        pr.firstIncluding = true;
+        pr.lastIncluding = true;
+        assertEquals(1, store.count(ascendingMeta, pr, maxNodeCount));
+        assertEquals(1, descendingStore.count(descendingMeta, pr, 
maxNodeCount));
+
+        // property not null
+        pr = new Filter.PropertyRestriction();
+        pr.first = null;
+        pr.last = null;
+        pr.firstIncluding = false;
+        pr.lastIncluding = false;
+        // 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(store.count(ascendingMeta, pr, maxNodeCount),
+            descendingStore.count(descendingMeta, pr, maxNodeCount));
+        
+        // '>'
+        pr = new Filter.PropertyRestriction();
+        pr.first = PropertyValues.newString(value);
+        pr.last = null;
+        pr.firstIncluding = false;
+        pr.lastIncluding = false;
+        // 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));
+
+        // '>='
+        pr = new Filter.PropertyRestriction();
+        pr.first = PropertyValues.newString(value);
+        pr.last = null;
+        pr.firstIncluding = true;
+        pr.lastIncluding = false;
+        // 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));
+
+        // '<'
+        pr = new Filter.PropertyRestriction();
+        pr.first = null;
+        pr.last = PropertyValues.newString(value);
+        pr.firstIncluding = false;
+        pr.lastIncluding = false;
+        // 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));
+        
+        // when no conditions has been asked but just an ORDER BY
+        pr = null;
+        assertTrue(store.count(ascendingMeta, pr, maxNodeCount) > 0);
+        assertEquals(store.count(ascendingMeta, pr, maxNodeCount),
+            descendingStore.count(descendingMeta, pr, maxNodeCount));
+    }
 }

Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1578779&r1=1578778&r2=1578779&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
 Tue Mar 18 08:25:57 2014
@@ -103,7 +103,6 @@ public class BenchmarkRunner {
             new OrderedIndexInsertOrderedPropertyTest(),
             new OrderedIndexInsertStandardPropertyTest(),
             new OrderedIndexInsertNoIndexTest(),
-            new OrderByQueryTest(),
             new LoginTest(),
             new LoginLogoutTest(),
             new NamespaceTest(),

Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexBaseTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexBaseTest.java?rev=1578779&r1=1578778&r2=1578779&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexBaseTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexBaseTest.java
 Tue Mar 18 08:25:57 2014
@@ -25,7 +25,7 @@ import javax.jcr.Session;
 
 import org.apache.jackrabbit.oak.benchmark.util.OakIndexUtils;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
-import 
org.apache.jackrabbit.oak.plugins.index.property.OrderedPropertyIndexEditorProvider;
+import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex;
 import 
org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
 
@@ -53,6 +53,11 @@ public abstract class OrderedIndexBaseTe
     */
    static final String INDEXED_PROPERTY = "indexedProperty";
    
+    /**
+     * size of the batch for saving
+     */
+    static final int BATCH_SAVING_SIZE = 1024;
+   
    /**
     * node name below which creating the test data
     */
@@ -68,22 +73,38 @@ public abstract class OrderedIndexBaseTe
     */
    Node dump;
       
-   void insertRandomNodes(int numberOfNodes){
-      try{
-         for(int i=0; i<numberOfNodes; i++){
-            String uuid = UUID.randomUUID().toString();
-            dump.addNode(uuid, NODE_TYPE).setProperty(INDEXED_PROPERTY, uuid);
-            session.save();            
-         }
-      } catch (RepositoryException e){
-         throw new RuntimeException(e);
-      }      
-   }
+
+    /**
+     * insert a {@code numberOfNode} random nodes in the repository
+     * 
+     * @param numberOfNodes
+     */
+    void insertRandomNodes(int numberOfNodes) {
+        try {
+            for (int i = 0; i < numberOfNodes; i++) {
+                String uuid = UUID.randomUUID().toString();
+                dump.addNode(uuid, NODE_TYPE).setProperty(INDEXED_PROPERTY, 
uuid);
+                if (isBatchSaving()) {
+                    if (i % BATCH_SAVING_SIZE == 0) {
+                        session.save();
+                    }
+                } else {
+                    session.save();
+                }
+            }
+            if (isBatchSaving()) {
+                // an extra save to catch any pending operations.
+                session.save();
+            }
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+    }
 
    /**
     * override when needed to define an index
     */
-   void defineIndex() throws Exception{
+   void defineIndex() throws Exception {
    }
    
    Node defineStandardPropertyIndex(Session session) throws Exception {
@@ -99,14 +120,27 @@ public abstract class OrderedIndexBaseTe
    }
    
    Node defineOrderedPropertyIndex(Session session) throws Exception {
-       Node index = new 
OakIndexUtils.PropertyIndex().property(INDEXED_PROPERTY).create(session,OrderedPropertyIndexEditorProvider.TYPE);
-       if(index == null) {
-           throw new RuntimeException("Error while creating the index 
definition. index node is null.");
-       }
-       
if(!OrderedPropertyIndexEditorProvider.TYPE.equals(index.getProperty(IndexConstants.TYPE_PROPERTY_NAME).getString()))
 {
-           throw new RuntimeException("The index type does not match the 
expected");
-       }
-       session.save();
-       return index;
+        Node index = new OakIndexUtils.PropertyIndex().property(
+                INDEXED_PROPERTY).create(session, OrderedIndex.TYPE);
+        if (index == null) {
+            throw new RuntimeException(
+                    "Error while creating the index definition. index node is 
null.");
+        }
+        if (!OrderedIndex.TYPE.equals(index.getProperty(
+                IndexConstants.TYPE_PROPERTY_NAME).getString())) {
+            throw new RuntimeException(
+                    "The index type does not match the expected");
+        }
+        session.save();
+        return index;
    }
-}
+   
+    /**
+     * 
+     * @return true if you want batch saving during {@code insertRandomNodes} 
by
+     *         {@code BATCH_SAVE_SIZE}
+     */
+    boolean isBatchSaving() {
+        return false;
+    }
+}
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexQueryBaseTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexQueryBaseTest.java?rev=1578779&r1=1578778&r2=1578779&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexQueryBaseTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/OrderedIndexQueryBaseTest.java
 Tue Mar 18 08:25:57 2014
@@ -77,4 +77,9 @@ public abstract class OrderedIndexQueryB
     }
     
     abstract String getQuery();
+
+    @Override
+    boolean isBatchSaving() {
+        return true;
+    }
 }


Reply via email to