### Eclipse Workspace Patch 1.0 #P oak-core Index: src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java (revision 1604844) +++ src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java (working copy) @@ -39,6 +39,8 @@ String ENTRY_COUNT_PROPERTY_NAME = "entryCount"; + String KEY_COUNT_PROPERTY_NAME = "keyCount"; + /** * Marks a unique property index. */ Index: src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java (revision 1604849) +++ src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java (working copy) @@ -19,6 +19,7 @@ import static com.google.common.collect.Queues.newArrayDeque; import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME; import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.ENTRY_COUNT_PROPERTY_NAME; +import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.KEY_COUNT_PROPERTY_NAME; import java.util.Deque; import java.util.Iterator; @@ -177,6 +178,18 @@ if (size == 0) { return 0; } + PropertyState ec = indexMeta.getProperty(ENTRY_COUNT_PROPERTY_NAME); + if (ec != null) { + long entryCount = ec.getValue(Type.LONG); + long keyCount = 10000; + ec = indexMeta.getProperty(KEY_COUNT_PROPERTY_NAME); + if (ec != null) { + keyCount = ec.getValue(Type.LONG); + } + // cast to double to avoid overflow + // (entryCount could be Long.MAX_VALUE) + return (long) ((double) entryCount) * size/ keyCount; + } max = Math.max(10, max / size); int i = 0; for (String p : values) { Index: src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (revision 1604844) +++ src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (working copy) @@ -816,6 +816,7 @@ } else { cost = index.getCost(filter, rootState); } +;System.out.println("cost for " + index.getIndexName() + " is " + cost + " filter " + filter); if (LOG.isDebugEnabled()) { LOG.debug("cost for " + index.getIndexName() + " is " + cost); } #P oak-jcr Index: src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryPlanTest.java =================================================================== --- src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryPlanTest.java (revision 1604849) +++ src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryPlanTest.java (working copy) @@ -46,6 +46,54 @@ } @Test + // OAK-1902 + public void propertyIndexVersusNodeTypeIndex() throws Exception { + Session session = getAdminSession(); + Node nt = session.getRootNode().getNode("oak:index").getNode("nodetype"); + nt.setProperty("entryCount", Long.MAX_VALUE); + QueryManager qm = session.getWorkspace().getQueryManager(); + Node testRootNode = session.getRootNode().addNode("testroot"); + for (int i = 0; i < 100; i++) { + Node n = testRootNode.addNode("n" + i, "oak:Unstructured"); + n.addMixin("mix:referenceable"); + } + session.save(); + + Query q; + QueryResult result; + RowIterator it; + + String xpath = "/jcr:root//element(*, oak:Unstructured)"; + q = qm.createQuery("explain " + xpath, "xpath"); + result = q.execute(); + it = result.getRows(); + assertTrue(it.hasNext()); + String plan = it.nextRow().getValue("plan").getString(); + // System.out.println("plan: " + plan); + // should use the node type index + assertEquals("[oak:Unstructured] as [a] " + + "/* Filter(query=explain select [jcr:path], [jcr:score], * " + + "from [oak:Unstructured] as a where isdescendantnode(a, '/') " + + "/* xpath: /jcr:root//element(*, oak:Unstructured) */, " + + "path=//*) where isdescendantnode([a], [/]) */", + plan); + + String xpath2 = "/jcr:root//element(*, oak:Unstructured)[@jcr:uuid]"; + q = qm.createQuery("explain " + xpath2 + "", "xpath"); + result = q.execute(); + it = result.getRows(); + assertTrue(it.hasNext()); + plan = it.nextRow().getValue("plan").getString(); + // System.out.println("plan: " + plan); + // should use the index on "jcr:uuid" + assertEquals("[oak:Unstructured] as [a] " + + "/* property jcr:uuid where ([a].[jcr:uuid] is not null) " + + "and (isdescendantnode([a], [/])) */", + plan); + + } + + @Test // OAK-1903 public void propertyEqualsVersusPropertyNotNull() throws Exception { Session session = getAdminSession();