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; + } }
