This is an automated email from the ASF dual-hosted git repository. thomasm pushed a commit to branch OAK-10527 in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit 8551bae413d52f4f8373e2ee0dc803e91b6030d4 Author: Thomas Mueller <[email protected]> AuthorDate: Fri Nov 3 09:31:50 2023 +0100 OAK-10527 Improve readability of the explain query output --- .../oak/plugins/index/nodetype/NodeTypeIndex.java | 5 +- .../plugins/index/property/PropertyIndexPlan.java | 22 +- .../plugins/index/reference/ReferenceIndex.java | 17 +- .../jackrabbit/oak/query/QueryEngineImpl.java | 5 +- .../jackrabbit/oak/query/QueryFormatter.java | 103 +++++++++ .../org/apache/jackrabbit/oak/query/QueryImpl.java | 4 - .../jackrabbit/oak/query/ast/SelectorImpl.java | 9 +- .../oak/query/index/TraversingIndex.java | 25 +- .../index/nodetype/NodeTypeIndexQueryTest.java | 15 +- .../index/property/MultiPropertyOrTest.java | 15 +- .../index/property/OptionIndexTagTests.java | 8 +- .../index/property/PropertyIndexDisabledTest.java | 12 +- .../org/apache/jackrabbit/oak/query/sql2_index.txt | 253 ++++++++++++++------- .../CompositeNodeStoreLuceneIndexTest.java | 20 +- .../oak/composite/CompositeNodeStoreQueryTest.java | 10 +- .../oak/jcr/query/QueryFormatterTest.java | 77 +++++++ .../index/lucene/LuceneIndexAugmentTest.java | 12 +- .../index/lucene/LuceneIndexQueryCommonTest.java | 3 +- .../lucene/LucenePropertyIndexCommonTest.java | 4 +- .../index/lucene/LucenePropertyIndexTest.java | 117 +++++----- .../dynamicBoost/LuceneDynamicBoostTest.java | 5 +- .../property/SynchronousPropertyIndexTest.java | 4 +- .../index/elastic/ElasticDynamicBoostTest.java | 5 +- .../index/elastic/ElasticIndexQueryCommonTest.java | 16 +- .../index/elastic/ElasticPropertyIndexTest.java | 2 +- .../index/search/spi/query/FulltextIndex.java | 32 ++- .../search/spi/query/FulltextIndexPlanner.java | 2 +- .../oak/plugins/index/DynamicBoostCommonTest.java | 17 +- .../oak/plugins/index/FunctionIndexCommonTest.java | 42 ++-- .../oak/plugins/index/IndexQueryCommonTest.java | 4 +- .../oak/plugins/index/OrderByCommonTest.java | 24 +- .../oak/plugins/index/PropertyIndexCommonTest.java | 16 +- 32 files changed, 599 insertions(+), 306 deletions(-) diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java index 672158d620..0f50c74ff6 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java @@ -102,7 +102,10 @@ class NodeTypeIndex implements QueryIndex, JcrConstants { @Override public String getPlan(Filter filter, NodeState root) { - return "nodeType " + filter.toString(); + return "nodeType\n" + + " path: " + filter.getPath() + "\n" + + " primaryTypes: " + filter.getPrimaryTypes().toString() + "\n" + + " mixinTypes: " + filter.getMixinTypes().toString() + "\n"; } @Override diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java index 0c7e9d7cf7..22408fb72e 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java @@ -32,6 +32,7 @@ import org.apache.jackrabbit.oak.plugins.index.IndexConstants; import org.apache.jackrabbit.oak.plugins.index.IndexUtils; import org.apache.jackrabbit.oak.plugins.index.cursor.Cursors; import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy; +import org.apache.jackrabbit.oak.query.SQL2Parser; import org.apache.jackrabbit.oak.spi.filter.PathFilter; import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider; import org.apache.jackrabbit.oak.spi.mount.Mounts; @@ -238,27 +239,30 @@ public class PropertyIndexPlan { @Override public String toString() { - StringBuilder buffer = new StringBuilder("property "); - buffer.append(name); + StringBuilder buffer = new StringBuilder(); + buffer.append("property ").append(name).append("\n"); + buffer.append(" indexDefinition: /"); + buffer.append(IndexConstants.INDEX_DEFINITIONS_NAME); + buffer.append("/").append(name).append("\n"); + buffer.append(" estimatedCost: ").append(cost).append("\n"); + buffer.append(" values: "); if (values == null) { - buffer.append(" IS NOT NULL"); + buffer.append("all values in the index (warning: may be slow)"); } else if (values.isEmpty()) { - buffer.append(" NOT APPLICABLE"); + buffer.append("not applicable"); } else if (values.size() == 1) { - buffer.append(" = "); - buffer.append(values.iterator().next()); + buffer.append(SQL2Parser.escapeStringLiteral(values.iterator().next())); } else { - buffer.append(" IN ("); boolean comma = false; for (String value : values) { if (comma) { buffer.append(", "); } - buffer.append(value); + buffer.append(SQL2Parser.escapeStringLiteral(value)); comma = true; } - buffer.append(")"); } + buffer.append("\n"); return buffer.toString(); } diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java index 639e94aa80..438ede13c0 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java @@ -36,6 +36,7 @@ import java.util.Set; import org.apache.jackrabbit.oak.plugins.index.property.Multiplexers; import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy; +import org.apache.jackrabbit.oak.query.SQL2Parser; import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider; import org.apache.jackrabbit.oak.spi.mount.Mounts; import org.apache.jackrabbit.oak.spi.query.Cursor; @@ -163,23 +164,25 @@ class ReferenceIndex implements QueryIndex { @Override public String getPlan(Filter filter, NodeState root) { - StringBuilder buff = new StringBuilder("reference"); + StringBuilder buff = new StringBuilder(); + buff.append("reference\n"); for (PropertyRestriction pr : filter.getPropertyRestrictions()) { if (pr.propertyType == REFERENCE) { - buff.append(" PROPERTY(["); + buff.append(" on: property(["); buff.append(pr.propertyName); buff.append("], 'Reference') = "); - buff.append(pr.first.getValue(STRING)); - return buff.toString(); + buff.append(SQL2Parser.escapeStringLiteral(pr.first.getValue(STRING))); + break; } if (pr.propertyType == WEAKREFERENCE) { - buff.append(" PROPERTY(["); + buff.append(" on: property(["); buff.append(pr.propertyName); buff.append("], 'WeakReference') = "); - buff.append(pr.first.getValue(STRING)); - return buff.toString(); + buff.append(SQL2Parser.escapeStringLiteral(pr.first.getValue(STRING))); + break; } } + buff.append("\n"); return buff.toString(); } diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java index 576cbab2f4..37a122e17a 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java @@ -151,7 +151,10 @@ public abstract class QueryEngineImpl implements QueryEngine { if (isInternal) { LOG.trace("Parsing {} statement: {}", language, statement); } else { - LOG.debug("Parsing {} statement: {}", language, statement); + if (LOG.isDebugEnabled()) { + String formattedStatement = QueryFormatter.format(statement, language); + LOG.debug("Parsing {} statement: {}", language, formattedStatement); + } } QueryEngineSettings settings = context.getSettings(); if (statement.length() > (settings.getQueryLengthErrorLimit())){ diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryFormatter.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryFormatter.java new file mode 100644 index 0000000000..3a2cd811b8 --- /dev/null +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryFormatter.java @@ -0,0 +1,103 @@ +/* + * 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.query; + +import java.util.Locale; + +/** + * Formatter for JCR queries in order to make them easier to read. Formatting is + * done on a best-effort basis. + * + * Warning: formatting is also done within e.g. string literals. So there is no + * guarantee that the formatted query is semantically equal to the original one! + */ +public class QueryFormatter { + + /** + * Detect whether the query is an XPath query. + * + * @param query the query + * @param language the language, if known, or null + * @return true if xpath + */ + public static boolean isXPath(String query, String language) { + if (language != null) { + return "xpath".equals(language); + } + query = query.trim().toLowerCase(Locale.ENGLISH); + // explain queries + if (query.startsWith("explain")) { + query = query.substring("explain".length()).trim(); + if (query.startsWith("measure")) { + query = query.substring("explain".length()).trim(); + } + } + // union queries + while (query.startsWith("(")) { + query = query.substring("(".length()).trim(); + } + if (query.startsWith("select")) { + return false; + } + return true; + } + + /** + * Format the query into a more human-readable way, by adding newlines. + * Warning: newlines are also added inside e.g. string literals. + * + * @param query the query (may not be null) + * @param language the query language, or null if unknown + * @return the formatted query + */ + public static String format(String query, String language) { + boolean xpath = isXPath(query, language); + if (xpath) { + return formatXPath(query); + } else { + return formatSQL(query); + } + } + + private static String formatXPath(String query) { + query = query.replaceAll("\\[", "\\[\n "); + for (String term : new String[] { + "and ", "or ", "order by ", "option\\(" + }) { + // xpath is case sensitive + query = query.replaceAll(" (" + term + ")", "\n $1"); + } + // remove duplicate newlines + query = query.replaceAll("\n+", "\n"); + return query; + } + + private static String formatSQL(String query) { + for (String term : new String[] { + "union ", "from ", "where ", "and ", "or ", "order by ", "option\\(" + }) { + // SQL is case insensitive, so we use (?i) + query = query.replaceAll("(?i) (" + term + ")", "\n $1"); + } + // remove duplicate newlines + query = query.replaceAll("\n+", "\n"); + return query; + } + +} diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java index eee7a71dfa..028c0dceab 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java @@ -1154,10 +1154,6 @@ public class QueryImpl implements Query { almostBestPlan = p; } } - - if (indexPlan != null && indexPlan.getPlanName() != null) { - indexName += "[" + indexPlan.getPlanName() + "]"; - } } else { cost = index.getCost(filter, rootState); } diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java index 2e57f144b5..e097611bd9 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java @@ -25,7 +25,6 @@ import static org.apache.jackrabbit.JcrConstants.NT_BASE; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -427,10 +426,14 @@ public class SelectorImpl extends SourceImpl { buff.append(index.getPlan(createFilter(true), rootState)); } } else { - buff.append("no-index"); + buff.append("no-index\n"); } if (!selectorConstraints.isEmpty()) { - buff.append(" where ").append(new AndImpl(selectorConstraints).toString()); + // we could add the selector constraints here, + // but it turns out this distracts more than it helps - + // however for the JSON representation it would be useful, + // that's why I think it makes sense to keep the commented code for now + // buff.append(" selectorCondition: ").append(new AndImpl(selectorConstraints).toString()).append("\n"); } buff.append(" */"); return buff.toString(); diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java index b61ace1eb1..3f6a1e473f 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java @@ -158,7 +158,30 @@ public class TraversingIndex implements QueryIndex { @Override public String getPlan(Filter filter, NodeState rootState) { - return "traverse \"" + filter.getPathPlan() + '"'; + StringBuilder buff = new StringBuilder(); + buff.append("traverse\n"); + PathRestriction restriction = filter.getPathRestriction(); + String path = filter.getPath(); + switch (restriction) { + case EXACT: + buff.append(" oneNode: ").append(path); + break; + case PARENT: + buff.append(" parent: ").append(path); + break; + case NO_RESTRICTION: + buff.append(" allNodes (warning: slow)"); + break; + case ALL_CHILDREN: + buff.append(" allDescendents: ").append(path); + break; + case DIRECT_CHILDREN: + buff.append(" onlyDirectChildren: ").append(path); + break; + } + buff.append("\n").append(" estimatedEntries: ").append(getCost(filter, rootState)); + buff.append("\n"); + return buff.toString(); } @Override diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexQueryTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexQueryTest.java index e44f123419..b641d3bb32 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexQueryTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexQueryTest.java @@ -120,9 +120,8 @@ public class NodeTypeIndexQueryTest extends AbstractQueryTest { Query.JCR_SQL2, false); assertEquals(1, plan.size()); assertTrue(plan.get(0).contains("no-index")); - assertEquals("[nt:unstructured] as [nt:unstructured] /* no-index\n" + - " where (isdescendantnode([nt:unstructured], [/test]))\n" + - " and (contains([nt:unstructured].[foo], 'bar')) */", + assertEquals("[nt:unstructured] as [nt:unstructured] /* no-index\n" + + " */", plan.get(0)); plan = executeQuery( @@ -132,9 +131,8 @@ public class NodeTypeIndexQueryTest extends AbstractQueryTest { Query.JCR_SQL2, false); assertEquals(1, plan.size()); assertTrue(plan.get(0).contains("no-index")); - assertEquals("[nt:unstructured] as [nt:unstructured] /* no-index\n" + - " where (isdescendantnode([nt:unstructured], [/test]))\n" + - " and (not contains([nt:unstructured].[foo], 'bar')) */", + assertEquals("[nt:unstructured] as [nt:unstructured] /* no-index\n" + + " */", plan.get(0)); plan = executeQuery( @@ -144,9 +142,8 @@ public class NodeTypeIndexQueryTest extends AbstractQueryTest { Query.JCR_SQL2, false); assertEquals(1, plan.size()); assertTrue(plan.get(0).contains("no-index")); - assertEquals("[nt:unstructured] as [nt:unstructured] /* no-index\n" + - " where (isdescendantnode([nt:unstructured], [/test]))\n" + - " and (contains([nt:unstructured].[foo], 'bar')) */", + assertEquals("[nt:unstructured] as [nt:unstructured] /* no-index\n" + + " */", plan.get(0)); setTraversalEnabled(true); diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiPropertyOrTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiPropertyOrTest.java index 0b3f12e0a0..65a9b13d85 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiPropertyOrTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiPropertyOrTest.java @@ -85,22 +85,22 @@ public class MultiPropertyOrTest extends AbstractQueryTest { Query.JCR_SQL2); assertEquals(1, lines.size()); // make sure it used the property index - assertTrue(lines.get(0).contains("property xyz IS NOT NULL")); + assertTrue(lines.toString(), lines.get(0).contains("all values in the index")); lines = executeQuery( "explain select [jcr:path] from [nt:base] where [x] = 'foo' OR [y] = 'foo'", Query.JCR_SQL2); assertEquals(1, lines.size()); // make sure it used the property index - assertTrue(lines.get(0).contains("property xyz = foo")); + assertTrue(lines.toString(), lines.get(0).contains("values: 'foo'")); lines = executeQuery( "explain select [jcr:path] from [nt:base] where [x] = 'foo' OR [y] = 'bar'", Query.JCR_SQL2); assertEquals(1, lines.size()); // make sure it used the property index - assertTrue(lines.get(0), lines.get(0).contains("property xyz = foo")); - assertTrue(lines.get(0), lines.get(0).contains("property xyz = bar")); + assertTrue(lines.get(0), lines.get(0).contains("values: 'foo'")); + assertTrue(lines.get(0), lines.get(0).contains("values: 'bar'")); assertQuery( "select [jcr:path] from [nt:base] where [x] = 'foo' OR [y] = 'foo'", @@ -121,22 +121,17 @@ public class MultiPropertyOrTest extends AbstractQueryTest { root.commit(); List<Integer> nodes = Lists.newArrayList(); - Random r = new Random(); - int seed = -2; + Random r = new Random(1); for (int i = 0; i < 1000; i++) { Tree a = test.addChild("a" + i); a.setProperty("x", "fooa"); - seed += 2; int num = r.nextInt(100); a.setProperty("z", num); nodes.add(num); } - - seed = -1; for (int i = 0; i < 1000; i++) { Tree a = test.addChild("b" + i); a.setProperty("y", "foob"); - seed += 2; int num = 100 + r.nextInt(100); a.setProperty("z", num); nodes.add(num); diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OptionIndexTagTests.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OptionIndexTagTests.java index f4d3abc528..40606e3481 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OptionIndexTagTests.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OptionIndexTagTests.java @@ -73,14 +73,14 @@ public class OptionIndexTagTests extends AbstractQueryTest { statement = "explain select * from [mix:versionable] where [jcr:uuid] = 1 option(index tag y, index name nodetype)"; result = executeQuery(statement, Query.JCR_SQL2, false, false).toString(); - assertTrue(result, result.indexOf("/* nodeType ") >= 0); + assertTrue(result, result.indexOf("/* nodeType") >= 0); statement = "explain select * from [mix:versionable] where [jcr:uuid] = 1 option(index name nodetype)"; result = executeQuery(statement, Query.JCR_SQL2, false, false).toString(); - assertTrue(result, result.indexOf("/* nodeType ") >= 0); + assertTrue(result, result.indexOf("/* nodeType") >= 0); statement = "explain select * from [mix:versionable] where [jcr:uuid] = 1 option(index tag y)"; result = executeQuery(statement, Query.JCR_SQL2, false, false).toString(); - assertTrue(result, result.indexOf("/* traverse ") >= 0); + assertTrue(result, result.indexOf("/* traverse") >= 0); } @Test @@ -95,7 +95,7 @@ public class OptionIndexTagTests extends AbstractQueryTest { assertTrue(result, result.indexOf("/* property uuid") >= 0); statement = "explain select * from [mix:versionable] where [jcr:uuid] = 1 option(index name nodetype)"; result = executeQuery(statement, Query.JCR_SQL2, false, false).toString(); - assertTrue(result, result.indexOf("/* nodeType ") >= 0); + assertTrue(result, result.indexOf("/* nodeType") >= 0); } @Test diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDisabledTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDisabledTest.java index 3bd7044ca7..f754ff34e6 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDisabledTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDisabledTest.java @@ -77,7 +77,11 @@ public class PropertyIndexDisabledTest { f.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("x10")); PropertyIndex propertyIndex = new PropertyIndex(Mounts.defaultMountInfoProvider()); assertTrue(propertyIndex.getCost(f, root) != Double.POSITIVE_INFINITY); - assertEquals("property foo = x10", propertyIndex.getPlan(f, root)); + assertEquals("property foo\n" + + " indexDefinition: /oak:index/foo\n" + + " estimatedCost: 7.0\n" + + " values: 'x10'\n" + + "", propertyIndex.getPlan(f, root)); // now test with a node that doesn't exist index = rootBuilder.child(INDEX_DEFINITIONS_NAME).child("foo"); @@ -95,7 +99,11 @@ public class PropertyIndexDisabledTest { // need to create a new one - otherwise the cached plan is used propertyIndex = new PropertyIndex(Mounts.defaultMountInfoProvider()); assertTrue(propertyIndex.getCost(f, root) != Double.POSITIVE_INFINITY); - assertEquals("property foo = x10", propertyIndex.getPlan(f, root)); + assertEquals("property foo\n" + + " indexDefinition: /oak:index/foo\n" + + " estimatedCost: 7.0\n" + + " values: 'x10'\n" + + "", propertyIndex.getPlan(f, root)); // test with a property that does not exist index = rootBuilder.child(INDEX_DEFINITIONS_NAME).child("foo"); diff --git a/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt b/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt index 980f86655e..1cb403b7a6 100644 --- a/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt +++ b/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt @@ -25,38 +25,56 @@ # * use ascii characters only explain select [jcr:path], [jcr:score], * from [nt:base] as a where lower([test]) <> 'lower' -[nt:base] as [a] /* traverse "*" - where lower([a].[test]) <> 'lower' */ +[nt:base] as [a] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ explain select * from [nt:base] where [jcr:uuid] <> '1' -[nt:base] as [nt:base] /* property uuid IS NOT NULL - where [nt:base].[jcr:uuid] <> '1' */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ explain select * from [nt:base] as a left outer join [nt:base] as b on a.x=b.y where a.y is null and b.z = 1 -[nt:base] as [a] /* traverse "*" - where [a].[y] is null */ left outer join [nt:base] as [b] /* traverse "*" - where [b].[z] = 1 */ +[nt:base] as [a] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ left outer join [nt:base] as [b] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on [a].[x] = [b].[y] explain select * from [nt:base] as a right outer join [nt:base] as b on a.x=b.y where a.y is null and b.z = 1 -[nt:base] as [b] /* traverse "*" - where [b].[z] = 1 */ left outer join [nt:base] as [a] /* traverse "*" */ +[nt:base] as [b] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ left outer join [nt:base] as [a] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on [a].[x] = [b].[y] explain select * from [nt:base] where (p=1 or p=2) and (p=3 or p=4) -[nt:base] as [nt:base] /* traverse "*" - where ([nt:base].[p] in(1, 2)) - and ([nt:base].[p] in(3, 4)) */ +[nt:base] as [nt:base] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ explain select * from [nt:base] where [jcr:uuid] like '%' -[nt:base] as [nt:base] /* property uuid IS NOT NULL - where [nt:base].[jcr:uuid] like '%' */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ explain select e.[jcr:path] from [nt:base] as a @@ -70,20 +88,30 @@ explain select e.[jcr:path] and name(c) = 'd' and name(d) = 'e' and (e.[jcr:uuid] = '1' or e.[jcr:uuid] = '2' or e.[jcr:uuid] = '3' or e.[jcr:uuid] = '4') -[nt:base] as [e] /* property uuid IN (1, 2, 3, 4) - where [e].[jcr:uuid] in('1', '2', '3', '4') */ - inner join [nt:base] as [d] /* traverse "* && //parent/of/join" - where name([d]) = 'e' */ +[nt:base] as [e] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 6.0 + values: '1', '2', '3', '4' + */ + inner join [nt:base] as [d] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on ischildnode([e], [d]) - inner join [nt:base] as [c] /* traverse "* && //parent/of/join" - where name([c]) = 'd' */ + inner join [nt:base] as [c] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on ischildnode([d], [c]) - inner join [nt:base] as [b] /* traverse "* && //parent/of/join" - where name([b]) = 'c' */ + inner join [nt:base] as [b] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on ischildnode([c], [b]) - inner join [nt:base] as [a] /* traverse "//* && //parent/of/join" - where (name([a]) = 'a') - and (isdescendantnode([a], [/])) */ + inner join [nt:base] as [a] /* traverse + allDescendents: / + estimatedEntries: 1.0E8 + */ on ischildnode([b], [a]) explain select e.[jcr:path] @@ -98,55 +126,78 @@ explain select e.[jcr:path] and name(c) = 'd' and name(d) = 'e' and (e.[jcr:uuid] = '1' or e.[jcr:uuid] = '2' or e.[jcr:uuid] = '3' or e.[jcr:uuid] = '4') -[nt:base] as [e] /* property uuid IN (1, 2, 3, 4) - where [e].[jcr:uuid] in('1', '2', '3', '4') */ - inner join [nt:base] as [d] /* traverse "* && //parent/of/join" - where name([d]) = 'e' */ +[nt:base] as [e] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 6.0 + values: '1', '2', '3', '4' + */ + inner join [nt:base] as [d] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on ischildnode([e], [d]) - inner join [nt:base] as [c] /* traverse "* && //parent/of/join" - where name([c]) = 'd' */ + inner join [nt:base] as [c] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on ischildnode([d], [c]) - inner join [nt:base] as [b] /* traverse "* && //parent/of/join" - where name([b]) = 'c' */ + inner join [nt:base] as [b] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on ischildnode([c], [b]) - inner join [nt:base] as [a] /* traverse "//* && //parent/of/join" - where (name([a]) = 'a') - and (isdescendantnode([a], [/])) */ + inner join [nt:base] as [a] /* traverse + allDescendents: / + estimatedEntries: 1.0E8 + */ on ischildnode([b], [a]) explain select excerpt(.) from [nt:resource] where contains(*, 'jackrabbit') -[nt:resource] as [nt:resource] /* traverse "*" - where contains([nt:resource].[*], 'jackrabbit') */ +[nt:resource] as [nt:resource] /* traverse + allNodes (warning: slow) + estimatedEntries: Infinity + */ explain select excerpt(.) from [nt:resource] where contains(*, 'jackrabbit') or contains(*, 'jackrabbit') -[nt:resource] as [nt:resource] /* traverse "*" - where contains([nt:resource].[*], 'jackrabbit') */ +[nt:resource] as [nt:resource] /* traverse + allNodes (warning: slow) + estimatedEntries: Infinity + */ explain select excerpt(.) from [nt:resource] where (contains(*, 'jackrabbit') or contains(*, 'jackrabbit')) and x = '1' -[nt:resource] as [nt:resource] /* traverse "*" - where (contains([nt:resource].[*], 'jackrabbit')) - and ([nt:resource].[x] = '1') */ +[nt:resource] as [nt:resource] /* traverse + allNodes (warning: slow) + estimatedEntries: Infinity + */ explain select * from [nt:base] where [jcr:uuid]=1 or [b]=2 -[nt:base] as [nt:base] /* traverse "*" - where ([nt:base].[jcr:uuid] = 1) or ([nt:base].[b] = 2) */ +[nt:base] as [nt:base] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ explain select b.[jcr:uuid] from [nt:base] as a inner join [nt:base] as b on isdescendantnode(b, a) where (a.[jcr:uuid] = '1' or a.[jcr:uuid] = '2') -[nt:base] as [a] /* property uuid IN (1, 2) - where [a].[jcr:uuid] in('1', '2') */ - inner join [nt:base] as [b] /* traverse "* && //path/from/join//*" */ +[nt:base] as [a] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '1', '2' + */ + inner join [nt:base] as [b] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on isdescendantnode([b], [a]) explain select b.[jcr:uuid] @@ -154,60 +205,88 @@ explain select b.[jcr:uuid] inner join [nt:base] as b on isdescendantnode(b, a) where (a.[jcr:uuid] = '1' or a.[jcr:uuid] = '2') and b.[jcr:uuid] is not null -[nt:base] as [a] /* property uuid IN (1, 2) - where [a].[jcr:uuid] in('1', '2') */ - inner join [nt:base] as [b] /* property uuid IS NOT NULL - where [b].[jcr:uuid] is not null */ +[nt:base] as [a] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '1', '2' + */ + inner join [nt:base] as [b] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ on isdescendantnode([b], [a]) explain select * from [nt:base] where length([jcr:uuid])=1 or upper([jcr:uuid])='1' or lower([jcr:uuid])='3' -[nt:base] as [nt:base] /* property uuid IS NOT NULL - where ([nt:base].[jcr:uuid] is not null) - and ((length([nt:base].[jcr:uuid]) = 1) or (upper([nt:base].[jcr:uuid]) = '1') or (lower([nt:base].[jcr:uuid]) = '3')) */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ explain select * from [nt:base] where [jcr:uuid] = '1' or ([jcr:uuid] = '2' and [b] = '3') -[nt:base] as [nt:base] /* property uuid IN (1, 2) - where ([nt:base].[jcr:uuid] is not null) - and ([nt:base].[jcr:uuid] in('1', '2')) */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '1', '2' + */ explain select * from [nt:base] where [jcr:uuid] in('1', '2') -[nt:base] as [nt:base] /* property uuid IN (1, 2) - where [nt:base].[jcr:uuid] in('1', '2') */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '1', '2' + */ explain select * from [nt:base] where [jcr:uuid] = '1' or [jcr:uuid] = '2' -[nt:base] as [nt:base] /* property uuid IN (1, 2) - where [nt:base].[jcr:uuid] in('1', '2') */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '1', '2' + */ explain select * from [nt:base] where [jcr:uuid] = '123' -[nt:base] as [nt:base] /* property uuid = 123 - where [nt:base].[jcr:uuid] = '123' */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 2.0 + values: '123' + */ explain select * from [nt:base] where [jcr:uuid] is not null -[nt:base] as [nt:base] /* property uuid IS NOT NULL - where [nt:base].[jcr:uuid] is not null */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ explain select * from [nt:base] as a inner join [nt:base] as b on isdescendantnode(b, a) where a.[jcr:uuid] is not null and b.[jcr:uuid] is not null -[nt:base] as [a] /* property uuid IS NOT NULL - where [a].[jcr:uuid] is not null */ - inner join [nt:base] as [b] /* property uuid IS NOT NULL - where [b].[jcr:uuid] is not null */ +[nt:base] as [a] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ + inner join [nt:base] as [b] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ on isdescendantnode([b], [a]) explain select * @@ -215,10 +294,16 @@ explain select * inner join [nt:base] as b on isdescendantnode(b, a) where (a.[jcr:uuid]=1 or a.[jcr:uuid]=2) and (b.[jcr:uuid]=3 or b.[jcr:uuid]=4) -[nt:base] as [a] /* property uuid IN (1, 2) - where [a].[jcr:uuid] in(1, 2) */ - inner join [nt:base] as [b] /* property uuid IN (3, 4) - where [b].[jcr:uuid] in(3, 4) */ +[nt:base] as [a] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '1', '2' + */ + inner join [nt:base] as [b] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 4.0 + values: '3', '4' + */ on isdescendantnode([b], [a]) explain select * @@ -226,17 +311,25 @@ explain select * inner join [nt:base] as b on isdescendantnode(b, a) where a.[jcr:uuid] is not null and b.[x] is not null -[nt:base] as [a] /* property uuid IS NOT NULL - where [a].[jcr:uuid] is not null */ - inner join [nt:base] as [b] /* traverse "* && //path/from/join//*" - where [b].[x] is not null */ +[nt:base] as [a] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ + inner join [nt:base] as [b] /* traverse + allNodes (warning: slow) + estimatedEntries: 1.0E8 + */ on isdescendantnode([b], [a]) explain select [rep:excerpt] from [nt:base] where [jcr:uuid] is not null -[nt:base] as [nt:base] /* property uuid IS NOT NULL - where [nt:base].[jcr:uuid] is not null */ +[nt:base] as [nt:base] /* property uuid + indexDefinition: /oak:index/uuid + estimatedCost: 12.0 + values: all values in the index (warning: may be slow) + */ commit / + "test": { "jcr:uuid": "xyz", "a": { "jcr:uuid": "123" } } diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreLuceneIndexTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreLuceneIndexTest.java index 5ad27c76c8..5e1a3c0eab 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreLuceneIndexTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreLuceneIndexTest.java @@ -158,7 +158,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // since it is now disabled as path corresponding to useIfExists property is not present in new read only lib QueryResult result = repoV2.executeQuery("explain /jcr:root//*[@foo = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* traverse \"//*\" where ([a].[foo] = 'bar'")); + containsString("allDescendents: /")); // Check that proper nodes are returned by the query // even after traversal from both readonly version 2 and global read write parts @@ -169,7 +169,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // Now just for sake of completeness - check that the index is still used if we use V1 of composite app. result = repoV1.executeQuery("explain /jcr:root//*[@foo = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* lucene:luceneTest(/oak:index/luceneTest) foo:bar")); + containsString("/oak:index/luceneTest")); result = repoV1.executeQuery("/jcr:root//*[@foo = 'bar'] order by @jcr:path", "xpath"); assertEquals("/content-foo/node-0, " + @@ -188,7 +188,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe result = repoV2.executeQuery("explain /jcr:root//*[@foo = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* traverse \"//*\" where ([a].[foo] = 'bar'")); + containsString("allDescendents: /")); // Check that proper nodes are returned by the query // even after traversal from both readonly version 2 and global read write parts @@ -232,7 +232,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // Check V2 now uses luceneTest2_V2 for foo2 and no index for foo i.e traversal QueryResult result = repoV2.executeQuery("explain /jcr:root//*[@foo = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* traverse \"//*\" where ([a].[foo] = 'bar'")); + containsString("allDescendents: /")); // Check that proper nodes are returned by the query // even after traversal from both readonly version 2 and global read write parts @@ -242,7 +242,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // Checking for prop foo2 now result = repoV2.executeQuery("explain /jcr:root//*[@foo2 = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* lucene:luceneTest2_V2(/oak:index/luceneTest2_V2) foo2:bar")); + containsString("/oak:index/luceneTest2_V2")); result = repoV2.executeQuery("/jcr:root//*[@foo2 = 'bar'] order by @jcr:path", "xpath"); assertEquals("/content-foo2/node-0, /content-foo2/node-1, " + @@ -253,7 +253,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // Checking for foo3 now - new index on V2 result = repoV2.executeQuery("explain /jcr:root//*[@foo3 = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* lucene:luceneTest3(/oak:index/luceneTest3) foo3:bar")); + containsString("/oak:index/luceneTest3")); // Check that proper nodes are returned by the query // even after traversal from both readonly version 2 and global read write parts @@ -267,7 +267,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // Now check that the V1 instance still uses B for foo2 , A for foo and traverses for foo3 result = repoV1.executeQuery("explain /jcr:root//*[@foo = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* lucene:luceneTest(/oak:index/luceneTest) foo:bar")); + containsString("/oak:index/luceneTest")); result = repoV1.executeQuery("/jcr:root//*[@foo = 'bar'] order by @jcr:path", "xpath"); assertEquals("/content-foo/node-0, " + @@ -279,7 +279,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe // foo 2 check result = repoV1.executeQuery("explain /jcr:root//*[@foo2 = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* lucene:luceneTest2(/oak:index/luceneTest2) foo2:bar")); + containsString("/oak:index/luceneTest2")); result = repoV1.executeQuery("/jcr:root//*[@foo2 = 'bar'] order by @jcr:path", "xpath"); assertEquals("/content-foo2/node-0, " + @@ -292,7 +292,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe repoV1.login(); result = repoV1.executeQuery("explain /jcr:root//*[@foo3 = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* traverse \"//*\" where ([a].[foo3] = 'bar'")); + containsString("allDescendents: /")); result = repoV1.executeQuery("/jcr:root//*[@foo3 = 'bar'] order by @jcr:path", "xpath"); assertEquals("/content-foo3/node-0, " + @@ -429,7 +429,7 @@ public class CompositeNodeStoreLuceneIndexTest extends CompositeNodeStoreQueryTe QueryResult result = executeQuery("explain /jcr:root//*[@" + indexedProperty + " = 'bar']", "xpath"); assertThat(result.getRows().next().toString(), - containsString("/* lucene:" + indexName + "(/oak:index/" + indexName + ") " + indexedProperty + ":bar")); + containsString("/oak:index/" + indexName)); result = executeQuery("/jcr:root//*[@" + indexedProperty + " = 'bar'] order by @jcr:path", "xpath"); assertEquals("/content-" + indexedProperty + "/node-0, " + diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java index 2f97919743..4f65eab8d9 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java @@ -99,7 +99,7 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase qe = root.getQueryEngine(); assertThat( executeQuery("explain /jcr:root//*[@foo = 'bar']", "xpath", false).toString(), - containsString("/* property foo = bar")); + containsString("/oak:index/foo")); assertEquals("[/readOnly/node-0, /readOnly/node-1, /readOnly/node-2]", executeQuery("/jcr:root//*[@foo = 'bar']", "xpath").toString()); @@ -116,7 +116,7 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase "/readOnly/node-0, /readOnly/node-1, /readOnly/node-2]", executeQuery("/jcr:root//*[@foo = 'bar']", "xpath").toString()); assertThat(executeQuery("explain /jcr:root/content//*[@foo = 'bar']", "xpath", false).toString(), - containsString("/* property foo = bar")); + containsString("/oak:index/foo")); // remove all data builder = store.getRoot().builder(); @@ -170,7 +170,7 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase qe = root.getQueryEngine(); assertThat(executeQuery("explain select * from [nt:base] " + "where property([*], 'Reference') = cast('u1' as reference)", Query.JCR_SQL2, false).toString(), - containsString("/* reference ")); + containsString("/* reference")); // expected: also /readOnly/node-0 .. 2 assertEquals("[/a/x, /readOnly/node-0, /readOnly/node-1, /readOnly/node-2]", executeQuery("select [jcr:path] from [nt:base] " + @@ -268,7 +268,7 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase assertThat( executeQuery("explain /jcr:root//*[@asyncFoo = 'bar']", "xpath", false).toString(), - containsString("/* lucene:lucene(/oak:index/lucene) asyncFoo:bar")); + containsString("/oak:index/lucene")); assertEquals("[/readOnly/node-0, /readOnly/node-1, /readOnly/node-2]", executeQuery("/jcr:root//*[@asyncFoo = 'bar']", "xpath").toString()); @@ -283,7 +283,7 @@ public class CompositeNodeStoreQueryTest extends CompositeNodeStoreQueryTestBase // run a query assertThat( executeQuery("explain /jcr:root//*[@asyncFoo = 'bar']", "xpath", false).toString(), - containsString("/* lucene:lucene(/oak:index/lucene) asyncFoo:bar")); + containsString("/oak:index/lucene")); assertEquals("[/content/node-0, /content/node-1, /content/node-2, " + "/readOnly/node-0, /readOnly/node-1, /readOnly/node-2]", executeQuery("/jcr:root//*[@asyncFoo = 'bar']", "xpath").toString()); diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFormatterTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFormatterTest.java new file mode 100644 index 0000000000..bf9fba4dce --- /dev/null +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFormatterTest.java @@ -0,0 +1,77 @@ +/* + * 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.jcr.query; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.apache.jackrabbit.oak.query.QueryFormatter; +import org.junit.Test; + +public class QueryFormatterTest { + + @Test + public void detectLanguage() { + assertFalse(QueryFormatter.isXPath("SELECT * FROM [rep:Authorizable]", null)); + assertFalse(QueryFormatter.isXPath(" select * from [nt:base]", null)); + assertFalse(QueryFormatter.isXPath("EXPLAIN SELECT ...", null)); + assertFalse(QueryFormatter.isXPath("explain measure SELECT ...", null)); + + // common xpath + assertTrue(QueryFormatter.isXPath("/jcr:root//*", null)); + assertTrue(QueryFormatter.isXPath(" /jcr:root//*", null)); + assertTrue(QueryFormatter.isXPath("\nexplain /jcr:root//element(*,rep:ACE)", null)); + + // xpath union + assertTrue(QueryFormatter.isXPath("( ( /jcr:root//a | /jcr:root//b ) )", null)); + + // language is set explicitly + assertTrue(QueryFormatter.isXPath("select", "xpath")); + } + + @Test + public void format() { + assertEquals("/jcr:root//*[\n" + + " @a=1\n" + + " and @b=2]\n" + + " order by @c\n" + + " option(traversal ok)", + QueryFormatter.format( + "/jcr:root//*[@a=1 and @b=2] order by @c option(traversal ok)", null)); + assertEquals( + "sElEct *\n" + + " FROM nt:base\n" + + " WHERE x=1\n" + + " and y=2", + QueryFormatter.format( + "sElEct * FROM nt:base WHERE x=1 and y=2", + null)); + assertEquals( + "select ...\n" + + " union select ...", + QueryFormatter.format( + "select ... union select ...", + null)); + // formatting is also done inside string literals + assertEquals( + "/jcr:root//*[\n" + + " @x='\n" + + " and ']", + QueryFormatter.format("/jcr:root//*[@x=' and ']", null)); + } +} diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexAugmentTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexAugmentTest.java index 3beb7db00e..6a58164304 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexAugmentTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexAugmentTest.java @@ -397,12 +397,12 @@ public class LuceneIndexAugmentTest extends AbstractQueryTest { String query = "EXPLAIN SELECT [jcr:path] from [" + TestUtil.NT_TEST + "] WHERE [foo1]='bar1'"; List<String> paths = executeQuery(query, SQL2); assertTrue("indexed prop name shouldn't decide query plan (" + paths.get(0) + ")", - paths.get(0).contains("/* no-index ")); + paths.get(0).contains("/* no-index")); query = "EXPLAIN SELECT [jcr:path] from [" + TestUtil.NT_TEST + "] WHERE [subChild/foo2]='bar2'"; paths = executeQuery(query, SQL2); assertTrue("indexed prop name shouldn't decide query plan (" + paths.get(0) + ")", - paths.get(0).contains("/* no-index ")); + paths.get(0).contains("/* no-index")); } //OAK-3576 @@ -461,7 +461,7 @@ public class LuceneIndexAugmentTest extends AbstractQueryTest { query = "EXPLAIN " + query; List<String> paths = executeQuery(query, SQL2, false); assertTrue("property index should have made the index selected (" + paths.get(0) + ")", - paths.get(0).contains("/* lucene:test-index(")); + paths.get(0).contains("/oak:index/test-index")); query = "SELECT [jcr:path] from [" + TestUtil.NT_TEST + "] WHERE [subChild/foo2]='bar2'"; executeQuery(query, SQL2); @@ -469,7 +469,7 @@ public class LuceneIndexAugmentTest extends AbstractQueryTest { query = "EXPLAIN " + query; paths = executeQuery(query, SQL2); assertTrue("property index should have made the index selected (" + paths.get(0) + ")", - paths.get(0).contains("/* lucene:test-index(")); + paths.get(0).contains("/oak:index/test-index")); } //OAK-3576 @@ -530,7 +530,7 @@ public class LuceneIndexAugmentTest extends AbstractQueryTest { List<String> paths = executeQuery(query, SQL2, false); assertEquals("Query augmentor should get called for full text constraints", 1, queryingCounter.get()); assertTrue("property index should have made the index selected (" + paths.get(0) + ")", - paths.get(0).contains("/* lucene:test-index(")); + paths.get(0).contains("/oak:index/test-index")); queryingCounter.set(0); query = "SELECT [jcr:path] from [" + TestUtil.NT_TEST + "] WHERE CONTAINS(*, 'bar2')"; @@ -541,7 +541,7 @@ public class LuceneIndexAugmentTest extends AbstractQueryTest { paths = executeQuery(query, SQL2, false); assertEquals("Query augmentor should get called for full text constraints", 1, queryingCounter.get()); assertTrue("property index should have made the index selected (" + paths.get(0) + ")", - paths.get(0).contains("/* lucene:test-index(")); + paths.get(0).contains("/oak:index/test-index")); } @Test diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryCommonTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryCommonTest.java index 84d9419162..273deb0db2 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryCommonTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryCommonTest.java @@ -79,7 +79,6 @@ public class LuceneIndexQueryCommonTest extends IndexQueryCommonTest { @Override public String getExplainValueForDescendantTestWithIndexTagExplain() { - return "[nt:base] as [nt:base] /* lucene:test-index(/oak:index/test-index) :ancestors:/test" + - " where isdescendantnode([nt:base], [/test]) */"; + return ":ancestors:/test"; } } diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexCommonTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexCommonTest.java index af1064b898..d458987f8c 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexCommonTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexCommonTest.java @@ -52,11 +52,11 @@ public class LucenePropertyIndexCommonTest extends PropertyIndexCommonTest { @Override protected String propertyExistenceQueryWithNullCheckExpectedExplain() { - return "lucene:test1(/oak:index/test1) :notNullProps:propa"; + return "/oak:index/test1"; } @Override protected String propertyNonExistenceQueryExpectedExplain() { - return "lucene:test1(/oak:index/test1) :nullProps:propa"; + return "/oak:index/test1"; } } diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java index d6ac51ec77..a45fb2b210 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java @@ -469,7 +469,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String propabQuery = "select [jcr:path] from [nt:base] where LOCALNAME() = 'foo'"; - assertThat(explain(propabQuery), containsString("lucene:test1(/oak:index/test1) :nodeName:foo")); + assertThat(explain(propabQuery), containsString(":nodeName:foo")); assertQuery(propabQuery, asList("/foo")); assertQuery("select [jcr:path] from [nt:base] where LOCALNAME() = 'bar'", asList("/test/bar")); assertQuery("select [jcr:path] from [nt:base] where LOCALNAME() LIKE 'foo'", asList("/foo")); @@ -503,7 +503,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { //test String propabQuery = "select [jcr:path] from [nt:base] where LOCALNAME() = 'foo'"; - assertThat(explain(propabQuery), containsString("lucene:test1(/oak:index/test1) :nodeName:foo")); + assertThat(explain(propabQuery), containsString(":nodeName:foo")); assertQuery(propabQuery, asList("/foo")); assertQuery("select [jcr:path] from [nt:base] where LOCALNAME() = 'bar'", asList("/test/bar")); assertQuery("select [jcr:path] from [nt:base] where LOCALNAME() LIKE 'foo'", asList("/foo")); @@ -573,12 +573,8 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { " or content.[hasRendition] = 'false'\n" + ")"; String explain = explain(q); - System.out.println(explain); - String luceneQuery = explain.substring(0, explain.indexOf('\n')); - assertEquals("[nt:unstructured] as [content] /* lucene:test1(/oak:index/test1) " + - "+(tags:Products:A tags:Products:A/B) " + - "+(tags:DocTypes:A tags:DocTypes:B tags:DocTypes:C tags:ProblemType:A)", - luceneQuery); + assertThat(explain, containsString("+(tags:Products:A tags:Products:A/B) " + + "+(tags:DocTypes:A tags:DocTypes:B tags:DocTypes:C tags:ProblemType:A)")); } @Test @@ -593,10 +589,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { String q = "SELECT * FROM [nt:unstructured] as content WHERE references LIKE '/some/content/efjoiefjowfgj/%'"; String explain = explain(q); - String luceneQuery = explain.substring(0, explain.indexOf('\n')); - assertEquals("[nt:unstructured] as [content] /* lucene:test1(/oak:index/test1) " + - "references:/some/content/efjoiefjowfgj/*", - luceneQuery); + assertThat(explain, containsString("references:/some/content/efjoiefjowfgj/*")); } @Test @@ -1946,7 +1939,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String propabQuery = "select [jcr:path] from [mix:title] where [jcr:title] = 'a'"; - assertThat(explain(propabQuery), containsString("lucene:test1(/oak:index/test1)")); + assertThat(explain(propabQuery), containsString("/oak:index/test1")); assertQuery(propabQuery, asList("/test/a")); } @@ -1966,7 +1959,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String propabQuery = "select [jcr:path] from [mix:mimeType] where [jcr:mimeType] = 'a'"; - assertThat(explain(propabQuery), containsString("lucene:test1(/oak:index/test1)")); + assertThat(explain(propabQuery), containsString("/oak:index/test1")); assertQuery(propabQuery, asList("/test/a")); } @@ -1997,14 +1990,14 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { String query; query = "/jcr:root/test//*[jcr:contains(@jcr:mimeType, '1234')]"; - assertThat(explainXpath(query), containsString("lucene:test2(/oak:index/test2)")); + assertThat(explainXpath(query), containsString("/oak:index/test2")); assertQuery(query, "xpath", asList("/test/a")); query = "/jcr:root/test//*[jcr:contains(., '1234')]"; assertThat(explainXpath(query), containsString("no-index")); query = "/jcr:root/test//*[@jcr:mimeType = '1234']"; - assertThat(explainXpath(query), containsString("lucene:test2(/oak:index/test2)")); + assertThat(explainXpath(query), containsString("/oak:index/test2")); assertQuery(query, "xpath", asList("/test/a")); } @@ -2068,7 +2061,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String propabQuery = "select [jcr:path] from [mix:title] where [jcr:content/type] = 'foo-a'"; - assertThat(explain(propabQuery), containsString("lucene:test1(/oak:index/test1)")); + assertThat(explain(propabQuery), containsString("/oak:index/test1")); assertQuery(propabQuery, asList("/test/a")); } @@ -2150,16 +2143,16 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { String propabQuery = "select * from [nt:base] where CONTAINS(tag, " + "'stockphotography:business/business_abstract')"; - assertPlanAndQuery(propabQuery, "lucene:test1(/oak:index/test1)", asList("/test")); + assertPlanAndQuery(propabQuery, "/oak:index/test1", asList("/test")); String query2 = "select * from [nt:base] where CONTAINS(tag, 'foo!')"; - assertPlanAndQuery(query2, "lucene:test1(/oak:index/test1)", asList("/test2")); + assertPlanAndQuery(query2, "/oak:index/test1", asList("/test2")); String query3 = "select * from [nt:base] where CONTAINS(tag, 'a=b')"; - assertPlanAndQuery(query3, "lucene:test1(/oak:index/test1)", asList("/test3")); + assertPlanAndQuery(query3, "/oak:index/test1", asList("/test3")); String query4 = "select * from [nt:base] where CONTAINS(tag, 'c=d=e')"; - assertPlanAndQuery(query4, "lucene:test1(/oak:index/test1)", asList("/test4")); + assertPlanAndQuery(query4, "/oak:index/test1", asList("/test4")); } @@ -2177,7 +2170,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String propabQuery = "select * from [nt:base] where CONTAINS([jcr:content/metadata/comment], 'december')"; - assertPlanAndQuery(propabQuery, "lucene:test1(/oak:index/test1)", asList("/test")); + assertPlanAndQuery(propabQuery, "/oak:index/test1", asList("/test")); } @Test @@ -2256,7 +2249,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String query = "select * from [nt:base] where [tag] = 'foo'"; - assertPlanAndQuery(query, "lucene:test1(/oak:index/test1)", Collections.<String>emptyList()); + assertPlanAndQuery(query, "/oak:index/test1", Collections.<String>emptyList()); } @Test @@ -2325,8 +2318,8 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); - assertPlanAndQuery("select * from [oak:TestSuperType]", "lucene:test1(/oak:index/test1)", asList("/a", "/b")); - assertPlanAndQuery("select * from [oak:TestMixA]", "lucene:test1(/oak:index/test1)", asList("/b", "/c")); + assertPlanAndQuery("select * from [oak:TestSuperType]", "/oak:index/test1", asList("/a", "/b")); + assertPlanAndQuery("select * from [oak:TestMixA]", "/oak:index/test1", asList("/b", "/c")); } @Test @@ -2369,8 +2362,8 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); - assertPlanAndQuery("select * from [oak:TestSuperType]", "lucene:test1(/oak:index/test1)", asList("/a", "/b")); - assertPlanAndQuery("select * from [oak:TestMixA]", "lucene:test1(/oak:index/test1)", asList("/b", "/c")); + assertPlanAndQuery("select * from [oak:TestSuperType]", "/oak:index/test1", asList("/a", "/b")); + assertPlanAndQuery("select * from [oak:TestMixA]", "/oak:index/test1", asList("/b", "/c")); } @@ -2387,7 +2380,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String query = "select * from [nt:base] where [foo] = 'bar'"; - assertPlanAndQuery(query, "lucene:test1(/oak:index/test1)", asList("/a")); + assertPlanAndQuery(query, "/oak:index/test1", asList("/a")); Tree barProp = root.getTree("/oak:index/test1/indexRules/nt:base/properties").addChild("bar"); barProp.setProperty("name", "bar"); @@ -2395,12 +2388,12 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); query = "select * from [nt:base] where [bar] = 'bar'"; - assertThat(explain(query), not(containsString("lucene:test1(/oak:index/test1)"))); + assertThat(explain(query), not(containsString("/oak:index/test1"))); root.getTree("/oak:index/test1").setProperty(REINDEX_PROPERTY_NAME, true); root.commit(); - assertPlanAndQuery(query, "lucene:test1(/oak:index/test1)", asList("/b")); + assertPlanAndQuery(query, "/oak:index/test1", asList("/b")); } @Test @@ -2416,7 +2409,7 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); String query = "select * from [nt:base] where [foo] = 'bar'"; - assertPlanAndQuery(query, "lucene:test1(/oak:index/test1)", asList("/a")); + assertPlanAndQuery(query, "/oak:index/test1", asList("/a")); Tree barProp = root.getTree("/oak:index/test1/indexRules/nt:base/properties").addChild("bar"); barProp.setProperty("name", "bar"); @@ -2424,18 +2417,18 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); query = "select * from [nt:base] where [bar] = 'bar'"; - assertThat(explain(query), not(containsString("lucene:test1(/oak:index/test1)"))); + assertThat(explain(query), not(containsString("/oak:index/test1"))); //Instead of reindex just refresh the index definition so that new index definition gets picked up root.getTree("/oak:index/test1").setProperty(FulltextIndexConstants.PROP_REFRESH_DEFN, true); root.commit(); //Plan would reflect new defintion - assertThat(explain(query), containsString("lucene:test1(/oak:index/test1)")); + assertThat(explain(query), containsString("/oak:index/test1")); assertFalse(root.getTree("/oak:index/test1").hasProperty(FulltextIndexConstants.PROP_REFRESH_DEFN)); //However as reindex was not done query would result in empty set - assertPlanAndQuery(query, "lucene:test1(/oak:index/test1)", Collections.<String>emptyList()); + assertPlanAndQuery(query, "/oak:index/test1", Collections.<String>emptyList()); } @Test @@ -2530,10 +2523,10 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { root.commit(); assertPlanAndQuery("select * from [nt:base] where [jcr:content/foo] = 'bar'", - "lucene:test1(/oak:index/test1)", asList("/a", "/b")); + "/oak:index/test1", asList("/a", "/b")); assertPlanAndQuery("select * from [nt:base] where [jcr:content/metadata/sub/foo] = 'bar'", - "lucene:test1(/oak:index/test1)", asList("/d")); + "/oak:index/test1", asList("/d")); } @Test @@ -3082,49 +3075,49 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { // XPaths assertPlanAndQueryXPath("//*[j:c/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a", "/b", "/d/e", "/")); + "/oak:index/fooIndex", asList("/a", "/b", "/d/e", "/")); assertPlanAndQueryXPath("//*[e/j:c/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/d")); + "/oak:index/fooIndex", asList("/d")); assertPlanAndQueryXPath("//*[*/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a", "/b", "/d/e", "/")); + "/oak:index/fooIndex", asList("/a", "/b", "/d/e", "/")); assertPlanAndQueryXPath("//*[*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", + "/oak:index/fooIndex", asList("/a/j:c", "/b/j:c", "/c", "/d/e/j:c", "/j:c", "/")); assertPlanAndQueryXPath("//*[j:c/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a", "/b", "/d/e", "/")); + "/oak:index/fooIndex", asList("/a", "/b", "/d/e", "/")); assertPlanAndQueryXPath("//*[*/foo1/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a")); + "/oak:index/fooIndex", asList("/a")); assertPlanAndQueryXPath("//*[*/*/foo3/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/d")); + "/oak:index/fooIndex", asList("/d")); // SQL2s assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [j:c/*/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a", "/b", "/d/e", "/")); + "/oak:index/fooIndex", asList("/a", "/b", "/d/e", "/")); assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [e/j:c/*/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/d")); + "/oak:index/fooIndex", asList("/d")); assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [*/*/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a", "/b", "/d/e", "/")); + "/oak:index/fooIndex", asList("/a", "/b", "/d/e", "/")); assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [*/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", + "/oak:index/fooIndex", asList("/a/j:c", "/b/j:c", "/c", "/d/e/j:c", "/j:c", "/")); assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [j:c/*/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a", "/b", "/d/e", "/")); + "/oak:index/fooIndex", asList("/a", "/b", "/d/e", "/")); assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [*/foo1/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/a")); + "/oak:index/fooIndex", asList("/a")); assertPlanAndQuery("SELECT * FROM [nt:base] WHERE [*/*/foo3/foo] = 'bar'", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/d")); + "/oak:index/fooIndex", asList("/d")); } @Test @@ -3149,35 +3142,35 @@ public class LucenePropertyIndexTest extends AbstractQueryTest { // no path restriction assertPlanAndQueryXPath("//*[j:c/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a", "/test/c/d")); + "/oak:index/fooIndex", asList("/test/a", "/test/c/d")); assertPlanAndQueryXPath("//*[*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a", "/test", "/test/c/d")); + "/oak:index/fooIndex", asList("/test/a", "/test", "/test/c/d")); assertPlanAndQueryXPath("//*[d/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/c")); + "/oak:index/fooIndex", asList("/test/c")); // any descendant assertPlanAndQueryXPath("/jcr:root/test//*[j:c/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a", "/test/c/d")); + "/oak:index/fooIndex", asList("/test/a", "/test/c/d")); assertPlanAndQueryXPath("/jcr:root/test//*[*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a", "/test/c/d")); + "/oak:index/fooIndex", asList("/test/a", "/test/c/d")); assertPlanAndQueryXPath("/jcr:root/test//*[d/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/c")); + "/oak:index/fooIndex", asList("/test/c")); // direct children assertPlanAndQueryXPath("/jcr:root/test/*[j:c/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a")); + "/oak:index/fooIndex", asList("/test/a")); assertPlanAndQueryXPath("/jcr:root/test/*[*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a")); + "/oak:index/fooIndex", asList("/test/a")); assertPlanAndQueryXPath("/jcr:root/test/*[d/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/c")); + "/oak:index/fooIndex", asList("/test/c")); // exact path assertPlanAndQueryXPath("/jcr:root/test/a[j:c/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a")); + "/oak:index/fooIndex", asList("/test/a")); assertPlanAndQueryXPath("/jcr:root/test/a[*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/a")); + "/oak:index/fooIndex", asList("/test/a")); assertPlanAndQueryXPath("/jcr:root/test/c[d/*/@foo = 'bar']", - "lucene:fooIndex(/oak:index/fooIndex)", asList("/test/c")); + "/oak:index/fooIndex", asList("/test/c")); } private void assertPlanAndQueryXPath(String query, String planExpectation, List<String> paths) throws ParseException { diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/LuceneDynamicBoostTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/LuceneDynamicBoostTest.java index c81bfedeac..1a745bced6 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/LuceneDynamicBoostTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/LuceneDynamicBoostTest.java @@ -88,9 +88,8 @@ public class LuceneDynamicBoostTest extends DynamicBoostCommonTest { @Override protected String getTestQueryDynamicBoostBasicExplained() { - return "[dam:Asset] as [a] /* lucene:test-index(/oak:index/test-index) (full:title:plant :fulltext:plant) " + - "((jcr:content/metadata/predictedTags/plant:1 jcr:content/metadata/predictedTags/plant:1)^1.0E-4) ft:(\"plant\")\n" + - " where contains([a].[*], 'plant') */"; + return "(full:title:plant :fulltext:plant) " + + "((jcr:content/metadata/predictedTags/plant:1 jcr:content/metadata/predictedTags/plant:1)^1.0E-4)"; } @Override diff --git a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/property/SynchronousPropertyIndexTest.java b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/property/SynchronousPropertyIndexTest.java index e1d418686d..9694d43925 100644 --- a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/property/SynchronousPropertyIndexTest.java +++ b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/property/SynchronousPropertyIndexTest.java @@ -331,9 +331,9 @@ public class SynchronousPropertyIndexTest extends AbstractQueryTest { runAsyncIndex(); assertThat(explain("select * from [nt:base] where [jcr:content/foo] = 'bar'"), - containsString("sync:(foo[jcr:content/foo] bar)")); + containsString("synchronousPropertyCondition: foo[jcr:content/foo] bar")); assertThat(explain("select * from [nt:base] where [foo] = 'bar'"), - containsString("sync:(foo bar)")); + containsString("synchronousPropertyCondition: foo bar")); } @Test diff --git a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostTest.java b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostTest.java index d780ab9df9..9fb2172c96 100644 --- a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostTest.java +++ b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostTest.java @@ -48,14 +48,13 @@ public class ElasticDynamicBoostTest extends DynamicBoostCommonTest { @Override protected String getTestQueryDynamicBoostBasicExplained() { - return "[dam:Asset] as [a] /* elasticsearch:test-index(/oak:index/test-index) {\"_source\":{\"includes\":[\":path\"]}," + + return "{\"_source\":{\"includes\":[\":path\"]}," + "\"query\":{\"bool\":{\"must\":[{\"bool\":{\"must\":[{\"query_string\":{\"default_operator\":\"and\"," + "\"fields\":[\"title^1.0\",\":dynamic-boost-ft^1.0E-4\",\":fulltext\"],\"query\":\"plant\",\"tie_breaker\":0.5,\"type\":\"cross_fields\"}}]," + "\"should\":[{\"nested\":{\"path\":\"predictedTagsDynamicBoost\",\"query\":{\"function_score\":{\"boost\":9.999999747378752E-5," + "\"functions\":[{\"field_value_factor\":{\"field\":\"predictedTagsDynamicBoost.boost\"}}]," + "\"query\":{\"match\":{\"predictedTagsDynamicBoost.value\":{\"query\":\"plant\"}}}}},\"score_mode\":\"avg\"}}]}}]}}," + - "\"size\":10,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\":path\":{\"order\":\"asc\"}}],\"track_total_hits\":10000} ft:(\"plant\")\n" + - " where contains([a].[*], 'plant') */"; + "\"size\":10,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\":path\":{\"order\":\"asc\"}}],\"track_total_hits\":10000}"; } /** diff --git a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexQueryCommonTest.java b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexQueryCommonTest.java index f8530356f1..c787d1e9eb 100644 --- a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexQueryCommonTest.java +++ b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexQueryCommonTest.java @@ -52,8 +52,7 @@ public class ElasticIndexQueryCommonTest extends IndexQueryCommonTest { String query = "explain select [jcr:path] from [nt:base] where " + "native('lucene', 'mlt?stream.body=/test/a&mlt.fl=:path&mlt.mindf=0&mlt.mintf=0')"; - String explainWithoutSimilarityTags = "[nt:base] as [nt:base] /* elasticsearch:test-index(/oak:index/test-index) {\"_source\":{\"includes\":[\":path\"]},\"query\":{\"bool\":{\"must\":[{\"more_like_this\":{\"fields\":[\":dynamic-boost-ft\",\"*\"],\"include\":true,\"like\":[{\"_id\":\"/test/a\",\"per_field_analyzer\":{\"_ignored\":\"keyword\"}}],\"min_doc_freq\":0,\"min_term_freq\":0}}]}},\"size\":10,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\":path\":{\"order\":\"asc\"}}],\"tra [...] - " where native([nt:base], [lucene], 'mlt?stream.body=/test/a&mlt.fl=:path&mlt.mindf=0&mlt.mintf=0') */"; + String explainWithoutSimilarityTags = "{\"_source\":{\"includes\":[\":path\"]},\"query\":{\"bool\":{\"must\":[{\"more_like_this\":{\"fields\":[\":dynamic-boost-ft\",\"*\"],\"include\":true,\"like\":[{\"_id\":\"/test/a\",\"per_field_analyzer\":{\"_ignored\":\"keyword\"}}],\"min_doc_freq\":0,\"min_term_freq\":0}}]}},\"size\":10,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\":path\":{\"order\":\"asc\"}}],\"track_total_hits\":10000}"; Tree test = root.getTree("/").addChild("test"); test.addChild("a").setProperty("text", "Hello World"); @@ -64,22 +63,21 @@ public class ElasticIndexQueryCommonTest extends IndexQueryCommonTest { root.commit(); // similarity tags disabled, should not be present in the explain output - assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, explainWithoutSimilarityTags, true)); + assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, explainWithoutSimilarityTags, false)); indexDefn.setProperty("similarityTagsEnabled", true); root.commit(); // similarity tags enabled, but no similarity tags properties configured, should not be present in the explain output - assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, explainWithoutSimilarityTags, true)); + assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, explainWithoutSimilarityTags, false)); - String explainWithSimilarityTags = "[nt:base] as [nt:base] /* elasticsearch:test-index(/oak:index/test-index) {\"_source\":{\"includes\":[\":path\"]},\"query\":{\"bool\":{\"must\":[{\"more_like_this\":{\"fields\":[\":dynamic-boost-ft\",\"*\"],\"include\":true,\"like\":[{\"_id\":\"/test/a\",\"per_field_analyzer\":{\"_ignored\":\"keyword\"}}],\"min_doc_freq\":0,\"min_term_freq\":0}}],\"should\":[{\"more_like_this\":{\"boost\":0.5,\"fields\":[\":simTags\"],\"like\":[{\"_id\":\"/test [...] - " where native([nt:base], [lucene], 'mlt?stream.body=/test/a&mlt.fl=:path&mlt.mindf=0&mlt.mintf=0') */"; + String explainWithSimilarityTags = "{\"_source\":{\"includes\":[\":path\"]},\"query\":{\"bool\":{\"must\":[{\"more_like_this\":{\"fields\":[\":dynamic-boost-ft\",\"*\"],\"include\":true,\"like\":[{\"_id\":\"/test/a\",\"per_field_analyzer\":{\"_ignored\":\"keyword\"}}],\"min_doc_freq\":0,\"min_term_freq\":0}}],\"should\":[{\"more_like_this\":{\"boost\":0.5,\"fields\":[\":simTags\"],\"like\":[{\"_id\":\"/test/a\"}],\"min_doc_freq\":1,\"min_term_freq\":1}}]}},\"size\":10,\"sort\":[{ [...] Tree properties = indexDefn.getChild(FulltextIndexConstants.INDEX_RULES).getChild("nt:base").getChild("properties"); Tree simProp = TestUtil.enableForFullText(properties, "simProp", false); simProp.setProperty(FulltextIndexConstants.PROP_SIMILARITY_TAGS, true); root.commit(); - assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, explainWithSimilarityTags, true)); + assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, explainWithSimilarityTags, false)); } @Override @@ -112,9 +110,7 @@ public class ElasticIndexQueryCommonTest extends IndexQueryCommonTest { @Override public String getExplainValueForDescendantTestWithIndexTagExplain() { - return "[nt:base] as [nt:base] /* elasticsearch:test-index(/oak:index/test-index) " - + "{\"_source\":{\"includes\":[\":path\"]},\"query\":{\"bool\":{\"filter\":[{\"term\":{\":ancestors\":{\"value\":\"/test\"}}}]}},\"size\":10,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\":path\":{\"order\":\"asc\"}}],\"track_total_hits\":10000}" - + " where isdescendantnode([nt:base], [/test]) */"; + return "{\"_source\":{\"includes\":[\":path\"]},\"query\":{\"bool\":{\"filter\":[{\"term\":{\":ancestors\":{\"value\":\"/test\"}}}]}},\"size\":10,\"sort\":[{\"_score\":{\"order\":\"desc\"}},{\":path\":{\"order\":\"asc\"}}],\"track_total_hits\":10000}"; } } diff --git a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticPropertyIndexTest.java b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticPropertyIndexTest.java index afa4dafd9f..cef7ae6c43 100644 --- a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticPropertyIndexTest.java +++ b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticPropertyIndexTest.java @@ -161,7 +161,7 @@ public class ElasticPropertyIndexTest extends ElasticAbstractQueryTest { assertEventually(() -> { String explanation = explain(propabQuery); - assertThat(explanation, containsString("elasticsearch:test1(/oak:index/test1) ")); + assertThat(explanation, containsString("/oak:index/test1")); assertThat(explanation, containsString("{\"term\":{\":nodeName\":{\"value\":\"foo\"")); assertQuery(propabQuery, List.of("/test/foo")); diff --git a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java index fe7d3f9727..38dd82d953 100644 --- a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java +++ b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java @@ -161,18 +161,18 @@ public abstract class FulltextIndex implements AdvancedQueryIndex, QueryIndex, N checkState(index != null, "The fulltext index of type " + getType() + " index is not available"); try { FullTextExpression ft = filter.getFullTextConstraint(); - StringBuilder sb = new StringBuilder(getType()).append(":"); + StringBuilder sb = new StringBuilder(); + sb.append(getType()).append(":").append(getIndexName(plan)).append("\n"); String path = getPlanResult(plan).indexPath; - sb.append(getIndexName(plan)) - .append("(") - .append(path) - .append(") "); - sb.append(getFulltextRequestString(plan, index, root)); + sb.append(" indexDefinition: ").append(path).append("\n"); + sb.append(" estimatedEntries: ").append(plan.getEstimatedEntryCount()).append("\n"); + // luceneQuery / elasticQuery + sb.append(" ").append(getType()).append("Query: ").append(getFulltextRequestString(plan, index, root)).append("\n"); if (plan.getSortOrder() != null && !plan.getSortOrder().isEmpty()) { - sb.append(" ordering:").append(plan.getSortOrder()); + sb.append(" sortOrder: ").append(plan.getSortOrder()).append("\n"); } if (ft != null) { - sb.append(" ft:(").append(ft).append(")"); + sb.append(" fulltextCondition: ").append(ft).append("\n"); } addSyncIndexPlan(plan, sb); return sb.toString(); @@ -185,22 +185,18 @@ public abstract class FulltextIndex implements AdvancedQueryIndex, QueryIndex, N PlanResult pr = getPlanResult(plan); if (pr.hasPropertyIndexResult()) { FulltextIndexPlanner.PropertyIndexResult pres = pr.getPropertyIndexResult(); - sb.append(" sync:(") - .append(pres.propertyName); - + sb.append(" synchronousPropertyCondition: ").append(pres.propertyName); if (!pres.propertyName.equals(pres.pr.propertyName)) { sb.append("[").append(pres.pr.propertyName).append("]"); } - sb.append(" ").append(pres.pr); - sb.append(")"); + sb.append("\n"); } - if (pr.evaluateSyncNodeTypeRestriction()) { - sb.append(" sync:(nodeType"); - sb.append(" primaryTypes : ").append(plan.getFilter().getPrimaryTypes()); - sb.append(" mixinTypes : ").append(plan.getFilter().getMixinTypes()); - sb.append(")"); + sb.append(" synchronousNodeType: "); + sb.append("primaryTypes=").append(plan.getFilter().getPrimaryTypes()); + sb.append(" mixinTypes=").append(plan.getFilter().getMixinTypes()); + sb.append("\n"); } } diff --git a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexPlanner.java b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexPlanner.java index 66d4130c5f..855d87c668 100644 --- a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexPlanner.java +++ b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexPlanner.java @@ -973,7 +973,7 @@ public class FulltextIndexPlanner { matchingRule = rule; } if (matchingRule != null){ - log.debug("Applicable IndexingRule found {}", matchingRule); + log.trace("Applicable IndexingRule found {}", matchingRule); return rule; } } diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/DynamicBoostCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/DynamicBoostCommonTest.java index be3cfac7f9..75dcbee99d 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/DynamicBoostCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/DynamicBoostCommonTest.java @@ -16,6 +16,14 @@ */ package org.apache.jackrabbit.oak.plugins.index; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.util.List; +import java.util.UUID; + import org.apache.commons.lang3.StringUtils; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.api.CommitFailedException; @@ -28,12 +36,6 @@ import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry; import org.apache.jackrabbit.oak.query.AbstractQueryTest; import org.junit.Test; -import java.io.ByteArrayInputStream; -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.assertEquals; - public abstract class DynamicBoostCommonTest extends AbstractQueryTest { protected static final String ASSET_NODE_TYPE = "[dam:Asset]\n" + " - * (UNDEFINED) multiple\n" + " - * (UNDEFINED)\n" + " + * (nt:base) = oak:TestNode VERSION"; @@ -46,7 +48,8 @@ public abstract class DynamicBoostCommonTest extends AbstractQueryTest { createAssetsIndexAndProperties(false, false); prepareTestAssets(); - assertEquals(getTestQueryDynamicBoostBasicExplained(), explain("//element(*, dam:Asset)[jcr:contains(., 'plant')]", XPATH)); + assertThat(explain("//element(*, dam:Asset)[jcr:contains(., 'plant')]", XPATH), + containsString(getTestQueryDynamicBoostBasicExplained())); assertEventually(() -> { assertQuery("//element(*, dam:Asset)[jcr:contains(., 'plant')]", XPATH, diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java index b3d4e281e4..883ef4bdf5 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java @@ -241,15 +241,15 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { postCommitHook(); String query = "select [jcr:path] from [nt:base] where path() = '/test/world'"; - assertThat(explain(query), containsString(getIndexProvider() + "pathIndex(/oak:index/pathIndex)")); + assertThat(explain(query), containsString("/oak:index/pathIndex")); assertQuery(query, asList("/test/world")); query = "select [jcr:path] from [nt:base] where path() like '%hell%'"; - assertThat(explain(query), containsString(getIndexProvider() + "pathIndex(/oak:index/pathIndex)")); + assertThat(explain(query), containsString("/oak:index/pathIndex")); assertQuery(query, asList("/test/hello", "/test/hello world")); query = "select [jcr:path] from [nt:base] where path() like '%ll_'"; - assertThat(explain(query), containsString(getIndexProvider() + "pathIndex(/oak:index/pathIndex)")); + assertThat(explain(query), containsString("/oak:index/pathIndex")); assertQuery(query, asList("/test/hello")); } @@ -300,7 +300,7 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { root.commit(); postCommitHook(); - assertThat(explain(query), containsString(getIndexProvider() + "test-index(/oak:index/test-index)")); + assertThat(explain(query), containsString("/oak:index/test-index")); List<String> result = executeQuery(query, SQL2); assertEquals("Ordering doesn't match", asList("10 percent", "10%", "Hallo", "hello", "World!"), result); @@ -931,11 +931,11 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { assertOrderedPlanAndQuery( "select * from [nt:base] order by coalesce([jcr:content/foo2], [jcr:content/foo])", - getIndexProvider() + "test1(/oak:index/test1)", asList("/a", "/c", "/b")); + "/oak:index/test1", asList("/a", "/c", "/b")); assertOrderedPlanAndQuery( "select * from [nt:base] order by coalesce([jcr:content/foo2], [jcr:content/foo]) DESC", - getIndexProvider() + "test1(/oak:index/test1)", asList("/b", "/c", "/a")); + "/oak:index/test1", asList("/b", "/c", "/a")); } @Test @@ -961,7 +961,7 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { assertPlanAndQuery( "select * from [nt:base] where lower(coalesce([jcr:content/foo2], coalesce([jcr:content/foo], localname()))) = 'bar'", - getIndexProvider() + "test1(/oak:index/test1)", asList("/a", "/b", "/bar")); + "/oak:index/test1", asList("/a", "/b", "/bar")); } /* @@ -1018,19 +1018,19 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { // Check ordering works for func and non func properties assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([jcr:content/n/foo])", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a", "/c", "/b", "/e", "/d")); + "/oak:index/upper", asList("/a", "/c", "/b", "/e", "/d")); assertOrderedPlanAndQuery( "select * from [nt:base] order by [jcr:content/n/foo]", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a", "/c", "/b", "/e", "/d")); + "/oak:index/upper", asList("/a", "/c", "/b", "/e", "/d")); assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([jcr:content/n/foo]) DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d", "/e", "/b", "/c", "/a")); + "/oak:index/upper", asList("/d", "/e", "/b", "/c", "/a")); assertOrderedPlanAndQuery( "select * from [nt:base] order by [jcr:content/n/foo] DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d", "/e", "/b", "/c", "/a")); + "/oak:index/upper", asList("/d", "/e", "/b", "/c", "/a")); // Now we change the value of foo on already indexed nodes and see if changes // get indexed properly. @@ -1052,19 +1052,19 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([jcr:content/n/foo])", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d", "/e", "/b", "/c", "/a")); + "/oak:index/upper", asList("/d", "/e", "/b", "/c", "/a")); assertOrderedPlanAndQuery( "select * from [nt:base] order by [jcr:content/n/foo]", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d", "/e", "/b", "/c", "/a")); + "/oak:index/upper", asList("/d", "/e", "/b", "/c", "/a")); assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([jcr:content/n/foo]) DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a", "/c", "/b", "/e", "/d")); + "/oak:index/upper", asList("/a", "/c", "/b", "/e", "/d")); assertOrderedPlanAndQuery( "select * from [nt:base] order by [jcr:content/n/foo] DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a", "/c", "/b", "/e", "/d")); + "/oak:index/upper", asList("/a", "/c", "/b", "/e", "/d")); } @@ -1127,19 +1127,19 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([foo])", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d", "/e", "/b", "/c", "/a")); + "/oak:index/upper", asList("/d", "/e", "/b", "/c", "/a")); assertOrderedPlanAndQuery( "select * from [nt:base] order by [foo]", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d", "/e", "/b", "/c", "/a")); + "/oak:index/upper", asList("/d", "/e", "/b", "/c", "/a")); assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([foo]) DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a", "/c", "/b", "/e", "/d")); + "/oak:index/upper", asList("/a", "/c", "/b", "/e", "/d")); assertOrderedPlanAndQuery( "select * from [nt:base] order by [foo] DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a", "/c", "/b", "/e", "/d")); + "/oak:index/upper", asList("/a", "/c", "/b", "/e", "/d")); } finally { customLogs.finished(); @@ -1244,11 +1244,11 @@ public abstract class FunctionIndexCommonTest extends AbstractQueryTest { // Check ordering works for func and non func properties assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([jcr:content/n/foo])", - getIndexProvider() + "upper(/oak:index/upper)", asList("/a","/c","/b","/e","/d")); + "/oak:index/upper", asList("/a","/c","/b","/e","/d")); assertOrderedPlanAndQuery( "select * from [nt:base] order by upper([jcr:content/n/foo]) DESC", - getIndexProvider() + "upper(/oak:index/upper)", asList("/d","/e","/b","/c","/a")); + "/oak:index/upper", asList("/d","/e","/b","/c","/a")); } diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java index 21a29a4def..22a05eca4f 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexQueryCommonTest.java @@ -207,7 +207,7 @@ public abstract class IndexQueryCommonTest extends AbstractQueryTest { root.commit(); String query = "explain select [jcr:path] from [nt:base] where isdescendantnode('/test') option (index tag x)"; - assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, getExplainValueForDescendantTestWithIndexTagExplain(), true)); + assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, getExplainValueForDescendantTestWithIndexTagExplain(), false)); } // Check if this is a valid behaviour or not ? @@ -216,7 +216,7 @@ public abstract class IndexQueryCommonTest extends AbstractQueryTest { @Test public void descendantTestWithIndexTagExplainWithNoData() { String query = "explain select [jcr:path] from [nt:base] where isdescendantnode('/test') option (index tag x)"; - assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, getExplainValueForDescendantTestWithIndexTagExplain(), true)); + assertEventually(getAssertionForExplain(query, Query.JCR_SQL2, getExplainValueForDescendantTestWithIndexTagExplain(), false)); } @Test diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/OrderByCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/OrderByCommonTest.java index 6eeb672333..7d600d6afe 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/OrderByCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/OrderByCommonTest.java @@ -320,28 +320,28 @@ public abstract class OrderByCommonTest extends AbstractQueryTest { root.commit(); String query = "/jcr:root/test/* order by fn:name() option(index tag fnName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":fnName(/oak:index/fnName)"); + assertXpathPlan(query, "/oak:index/fnName"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:name() ascending option(index tag fnName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":fnName(/oak:index/fnName)"); + assertXpathPlan(query, "/oak:index/fnName"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:name() descending option(index tag fnName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":fnName(/oak:index/fnName)"); + assertXpathPlan(query, "/oak:index/fnName"); assertEquals(Lists.reverse(expected), executeQuery(query, XPATH)); // order by fn:name() although function index is on "name()" query = "/jcr:root/test/* order by fn:name() option(index tag name)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":name(/oak:index/name)"); + assertXpathPlan(query, "/oak:index/name"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:name() ascending option(index tag name)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":name(/oak:index/name)"); + assertXpathPlan(query, "/oak:index/name"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:name() descending option(index tag name)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":name(/oak:index/name)"); + assertXpathPlan(query, "/oak:index/name"); assertEquals(Lists.reverse(expected), executeQuery(query, XPATH)); } @@ -392,28 +392,28 @@ public abstract class OrderByCommonTest extends AbstractQueryTest { root.commit(); String query = "/jcr:root/test/* order by fn:local-name() option(index tag fnLocalName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":fnLocalName(/oak:index/fnLocalName)"); + assertXpathPlan(query, "/oak:index/fnLocalName"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:local-name() ascending option(index tag fnLocalName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":fnLocalName(/oak:index/fnLocalName)"); + assertXpathPlan(query, "/oak:index/fnLocalName"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:local-name() descending option(index tag fnLocalName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":fnLocalName(/oak:index/fnLocalName)"); + assertXpathPlan(query, "/oak:index/fnLocalName"); assertEquals(Lists.reverse(expected), executeQuery(query, XPATH)); // order by fn:name() although function index is on "name()" query = "/jcr:root/test/* order by fn:local-name() option(index tag localName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":localName(/oak:index/localName)"); + assertXpathPlan(query, "/oak:index/localName"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:local-name() ascending option(index tag localName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":localName(/oak:index/localName)"); + assertXpathPlan(query, "/oak:index/localName"); assertEquals(expected, executeQuery(query, XPATH)); query = "/jcr:root/test/* order by fn:local-name() descending option(index tag localName)"; - assertXpathPlan(query, indexOptions.getIndexType() + ":localName(/oak:index/localName)"); + assertXpathPlan(query, "/oak:index/localName"); assertEquals(Lists.reverse(expected), executeQuery(query, XPATH)); } diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexCommonTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexCommonTest.java index 08d54fde72..ca7493fe4e 100644 --- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexCommonTest.java +++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexCommonTest.java @@ -72,7 +72,7 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { // Make sure that the last entry is indexed correctly. String propaQuery = "select [jcr:path] from [nt:base] where [propa] = 'foo248'"; assertEventually(() -> { - assertThat(explain(propaQuery), containsString(indexOptions.getIndexType() + ":test1")); + assertThat(explain(propaQuery), containsString("/oak:index/test1")); assertQuery(propaQuery, singletonList("/test/a248")); }); @@ -85,7 +85,7 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { root.commit(); String propaQuery2 = "select [jcr:path] from [nt:base] where [propa] = 'foo299'"; assertEventually(() -> { - assertThat(explain(propaQuery2), containsString(indexOptions.getIndexType() + ":test1")); + assertThat(explain(propaQuery2), containsString("/oak:index/test1")); assertQuery(propaQuery2, singletonList("/test/a299")); }); @@ -112,9 +112,9 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { .indexRule("nt:base") .property("nodeName", PROPDEF_PROP_NODE_NAME); indexOptions.setIndex(root, "test1", builder); - assertThat(explain(propaQuery), containsString(indexOptions.getIndexType() + ":test1")); + assertThat(explain(propaQuery), containsString("/oak:index/test1")); assertThat(explain("select [jcr:path] from [nt:base] where [propc] = 'foo'"), - containsString(indexOptions.getIndexType() + ":test2")); + containsString("/oak:index/test2")); assertQuery(propaQuery, Arrays.asList("/test/a", "/test/b")); assertQuery("select [jcr:path] from [nt:base] where [propa] = 'foo2'", singletonList("/test/c")); @@ -146,7 +146,7 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { assertEventually(() -> { String explanation = explain(propabQuery); - assertThat(explanation, containsString(indexOptions.getIndexType() + ":test1(/oak:index/test1) ")); + assertThat(explanation, containsString("/oak:index/test1")); //assertThat(explanation, containsString("{\"term\":{\":nodeName\":{\"value\":\"foo\",")); assertQuery(propabQuery, singletonList("/test/foo")); @@ -170,7 +170,7 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { test.addChild("b"); root.commit(); assertEventually(() -> assertThat(explain("select [jcr:path] from [nt:base] where [propa] = 'foo'"), - containsString(indexOptions.getIndexType() + ":test1"))); + containsString("/oak:index/test1"))); } @Test @@ -214,7 +214,7 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { } protected String propertyExistenceQueryWithNullCheckExpectedExplain() { - return indexOptions.getIndexType() + ":test1(/oak:index/test1) "; + return "/oak:index/test1"; } @Test @@ -243,7 +243,7 @@ public abstract class PropertyIndexCommonTest extends AbstractQueryTest { } protected String propertyNonExistenceQueryExpectedExplain() { - return indexOptions.getIndexType() + ":test1(/oak:index/test1) "; + return "/oak:index/test1"; } @Test
