You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2016/10/19 12:20:57 UTC
svn commit: r1765583 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-cor...
Author: thomasm
Date: Wed Oct 19 12:20:56 2016
New Revision: 1765583
URL: http://svn.apache.org/viewvc?rev=1765583&view=rev
Log:
OAK-4888 Warn or fail queries above a configurable cost value
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java Wed Oct 19 12:20:56 2016
@@ -51,4 +51,19 @@ public interface QueryEngineSettingsMBea
*/
void setLimitReads(long limitReads);
+ /**
+ * Whether queries that don't use an index will fail (throw an exception).
+ * The default is false.
+ *
+ * @return true if they fail
+ */
+ boolean getFailTraversal();
+
+ /**
+ * Set whether queries that don't use an index will fail (throw an exception).
+ *
+ * @param failTraversal the new value for this setting
+ */
+ void setFailTraversal(boolean failTraversal);
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java Wed Oct 19 12:20:56 2016
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-@Version("4.0.0")
+@Version("5.0.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.api.jmx;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java Wed Oct 19 12:20:56 2016
@@ -434,7 +434,7 @@ public class ContentMirrorStoreStrategy
readCount++;
if (readCount % TRAVERSING_WARN == 0) {
FilterIterators.checkReadLimit(readCount, settings);
- LOG.warn("Traversed {} nodes ({} index entries) using index {} with filter {}", readCount, intermediateNodeReadCount, indexName, filter);
+ LOG.warn("Index-Traversed {} nodes ({} index entries) using index {} with filter {}", readCount, intermediateNodeReadCount, indexName, filter);
}
return;
} else {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Wed Oct 19 12:20:56 2016
@@ -183,4 +183,11 @@ public interface Query {
*/
boolean containsUnfilteredFullTextCondition();
+ /**
+ * Set the query option to be used for this query.
+ *
+ * @param options the options
+ */
+ void setQueryOptions(QueryOptions options);
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java Wed Oct 19 12:20:56 2016
@@ -35,7 +35,10 @@ public class QueryEngineSettings impleme
Integer.getInteger("oak.queryLimitInMemory", Integer.MAX_VALUE);
private static final int DEFAULT_QUERY_LIMIT_READS =
- Integer.getInteger("oak.queryLimitReads", Integer.MAX_VALUE);
+ Integer.getInteger("oak.queryLimitReads", Integer.MAX_VALUE);
+
+ private static final boolean DEFAULT_FAIL_TRAVERSAL =
+ Boolean.getBoolean("oak.queryFailTraversal");
private static final boolean DEFAULT_FULL_TEXT_COMPARISON_WITHOUT_INDEX =
Boolean.getBoolean("oak.queryFullTextComparisonWithoutIndex");
@@ -44,6 +47,8 @@ public class QueryEngineSettings impleme
private long limitReads = DEFAULT_QUERY_LIMIT_READS;
+ private boolean failTraversal = DEFAULT_FAIL_TRAVERSAL;
+
private boolean fullTextComparisonWithoutIndex =
DEFAULT_FULL_TEXT_COMPARISON_WITHOUT_INDEX;
@@ -72,6 +77,16 @@ public class QueryEngineSettings impleme
this.limitReads = limitReads;
}
+ @Override
+ public boolean getFailTraversal() {
+ return failTraversal;
+ }
+
+ @Override
+ public void setFailTraversal(boolean failTraversal) {
+ this.failTraversal = failTraversal;
+ }
+
public void setFullTextComparisonWithoutIndex(boolean fullTextComparisonWithoutIndex) {
this.fullTextComparisonWithoutIndex = fullTextComparisonWithoutIndex;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java Wed Oct 19 12:20:56 2016
@@ -70,6 +70,16 @@ public class QueryEngineSettingsMBeanImp
settings.setLimitReads(limitReads);
}
+ @Override
+ public boolean getFailTraversal() {
+ return settings.getFailTraversal();
+ }
+
+ @Override
+ public void setFailTraversal(boolean failQueriesWithoutIndex) {
+ settings.setFailTraversal(failQueriesWithoutIndex);
+ }
+
public void setFullTextComparisonWithoutIndex(boolean fullTextComparisonWithoutIndex) {
settings.setFullTextComparisonWithoutIndex(fullTextComparisonWithoutIndex);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Wed Oct 19 12:20:56 2016
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.oak.api.Res
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.namepath.JcrPathParser;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
import org.apache.jackrabbit.oak.query.ast.AndImpl;
import org.apache.jackrabbit.oak.query.ast.AstVisitorBase;
import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
@@ -160,6 +161,11 @@ public class QueryImpl implements Query
* purposes.
*/
private boolean traversalEnabled = true;
+
+ /**
+ * The query option to be used for this query.
+ */
+ private QueryOptions queryOptions = new QueryOptions();
private OrderingImpl[] orderings;
private ColumnImpl[] columns;
@@ -948,6 +954,11 @@ public class QueryImpl implements Query
this.traversalEnabled = traversalEnabled;
}
+ @Override
+ public void setQueryOptions(QueryOptions options) {
+ this.queryOptions = options;
+ }
+
public SelectorExecutionPlan getBestSelectorExecutionPlan(FilterImpl filter) {
return getBestSelectorExecutionPlan(context.getBaseState(), filter,
context.getIndexProvider(), traversalEnabled);
@@ -1036,7 +1047,27 @@ public class QueryImpl implements Query
bestPlan = indexPlan;
}
}
-
+ if (bestIndex == null) {
+ QueryOptions.Traversal traversal = queryOptions.traversal;
+ if (traversal == Traversal.DEFAULT) {
+ // use the (configured) default
+ traversal = settings.getFailTraversal() ? Traversal.FAIL : Traversal.WARN;
+ } else {
+ // explicitly set in the query
+ traversal = queryOptions.traversal;
+ }
+ String message = "Traversal query (query without index): " + statement + "; consider creating an index";
+ switch (traversal) {
+ case OK:
+ break;
+ case WARN:
+ LOG.warn(message);
+ break;
+ case FAIL:
+ LOG.warn(message);
+ throw new IllegalArgumentException(message);
+ }
+ }
if (traversalEnabled) {
QueryIndex traversal = new TraversingIndex();
double cost = traversal.getCost(filter, rootState);
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java?rev=1765583&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java Wed Oct 19 12:20:56 2016
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * A query options (or "hints") that are used to customize the way the query is processed.
+ */
+public class QueryOptions {
+
+ public Traversal traversal = Traversal.DEFAULT;
+
+ public enum Traversal {
+ // traversing without index is OK for this query, and does not fail or log a warning
+ OK,
+ // traversing is OK, but logs a warning
+ WARN,
+ // traversing will fail the query
+ FAIL,
+ // the default setting
+ DEFAULT
+ };
+
+}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Wed Oct 19 12:20:56 2016
@@ -24,6 +24,7 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import javax.jcr.PropertyType;
@@ -34,6 +35,7 @@ import org.apache.jackrabbit.oak.api.Que
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
import org.apache.jackrabbit.oak.query.ast.AstElementFactory;
import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
import org.apache.jackrabbit.oak.query.ast.ColumnImpl;
@@ -161,6 +163,15 @@ public class SQL2Parser {
read("BY");
orderings = parseOrder();
}
+ QueryOptions options = new QueryOptions();
+ if (readIf("OPTION")) {
+ read("(");
+ if (readIf("TRAVERSAL")) {
+ String n = readName().toUpperCase(Locale.ENGLISH);
+ options.traversal = Traversal.valueOf(n);
+ }
+ read(")");
+ }
if (!currentToken.isEmpty()) {
throw getSyntaxError("<end>");
}
@@ -168,6 +179,7 @@ public class SQL2Parser {
q.setExplain(explain);
q.setMeasure(measure);
q.setInternal(isInternal(query));
+ q.setQueryOptions(options);
if (initialise) {
try {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java Wed Oct 19 12:20:56 2016
@@ -118,6 +118,12 @@ public class UnionQueryImpl implements Q
left.setTraversalEnabled(traversal);
right.setTraversalEnabled(traversal);
}
+
+ @Override
+ public void setQueryOptions(QueryOptions options) {
+ left.setQueryOptions(options);
+ right.setQueryOptions(options);
+ }
@Override
public void prepare() {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java Wed Oct 19 12:20:56 2016
@@ -19,6 +19,8 @@ package org.apache.jackrabbit.oak.query.
import java.util.ArrayList;
import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.query.QueryOptions;
+import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
import org.apache.jackrabbit.oak.query.xpath.Expression.AndCondition;
import org.apache.jackrabbit.oak.query.xpath.Expression.OrCondition;
import org.apache.jackrabbit.oak.query.xpath.Expression.Property;
@@ -50,6 +52,8 @@ public class Statement {
String xpathQuery;
+ QueryOptions queryOptions = new QueryOptions();
+
public Statement optimize() {
ignoreOrderByScoreDesc();
if (where == null) {
@@ -80,6 +84,7 @@ public class Statement {
union.xpathQuery = xpathQuery;
union.measure = measure;
union.explain = explain;
+ union.queryOptions = queryOptions;
return union;
}
@@ -209,6 +214,9 @@ public class Statement {
buff.append(orderList.get(i));
}
}
+ if (queryOptions.traversal != Traversal.DEFAULT) {
+ buff.append(" option(traversal " + queryOptions.traversal +")");
+ }
// leave original xpath string as a comment
appendXPathAsComment(buff, xpathQuery);
return buff.toString();
@@ -296,6 +304,9 @@ public class Statement {
buff.append(orderList.get(i));
}
}
+ if (queryOptions.traversal != Traversal.DEFAULT) {
+ buff.append(" option(traversal " + queryOptions.traversal +")");
+ }
// leave original xpath string as a comment
appendXPathAsComment(buff, xpathQuery);
return buff.toString();
@@ -314,4 +325,8 @@ public class Statement {
buff.append(" */");
}
+ public void setQueryOptions(QueryOptions options) {
+ this.queryOptions = options;
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java Wed Oct 19 12:20:56 2016
@@ -17,6 +17,8 @@
package org.apache.jackrabbit.oak.query.xpath;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.query.QueryOptions;
+import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
import org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement;
import org.apache.jackrabbit.util.ISO9075;
import org.slf4j.Logger;
@@ -25,6 +27,7 @@ import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
+import java.util.Locale;
/**
* This class can can convert a XPATH query to a SQL2 query.
@@ -324,11 +327,21 @@ public class XPathToSQL2Converter {
statement.addOrderBy(order);
} while (readIf(","));
}
+ QueryOptions options = new QueryOptions();
+ if (readIf("option")) {
+ read("(");
+ if (readIf("traversal")) {
+ String type = readIdentifier().toUpperCase(Locale.ENGLISH);
+ options.traversal = Traversal.valueOf(type);
+ }
+ read(")");
+ }
if (!currentToken.isEmpty()) {
throw getSyntaxError("<end>");
}
statement.setColumnSelector(currentSelector);
statement.setSelectors(selectors);
+ statement.setQueryOptions(options);
Expression where = null;
for (Selector s : selectors) {
@@ -1105,10 +1118,14 @@ public class XPathToSQL2Converter {
} else {
UnionStatement union = new UnionStatement(result, stat);
union.orderList = stat.orderList;
+ union.queryOptions = stat.queryOptions;
result = union;
}
- // can not use clear, because it is shared
+ // reset fields that are used in the union,
+ // but no longer in the individual statements
+ // (can not use clear, because it is shared)
stat.orderList = new ArrayList<Order>();
+ stat.queryOptions = new QueryOptions();
}
return result;
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java Wed Oct 19 12:20:56 2016
@@ -54,7 +54,6 @@ public class SQL2ParserTest {
.convert("/jcr:root/test/*/nt:resource[@jcr:encoding]"));
p.parse(new XPathToSQL2Converter()
.convert("/jcr:root/test/*/*/nt:resource[@jcr:encoding]"));
-
String xpath = "/jcr:root/etc/commerce/products//*[@cq:commerceType = 'product' " +
"and ((@size = 'M' or */@size= 'M' or */*/@size = 'M' " +
"or */*/*/@size = 'M' or */*/*/*/@size = 'M' or */*/*/*/*/@size = 'M'))]";
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java Wed Oct 19 12:20:56 2016
@@ -34,6 +34,45 @@ public class XPathTest {
new NodeStateNodeTypeInfoProvider(INITIAL_CONTENT);
@Test
+ public void queryOptions() throws ParseException {
+ verify("/jcr:root/content//*[@a] order by @c option(traversal fail)",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and isdescendantnode(a, '/content') " +
+ "order by [c] option(traversal FAIL) " +
+ "/* xpath: /jcr:root/content//*[@a] " +
+ "order by @c " +
+ "option(traversal fail) */");
+ verify("//*[@a or @b] order by @c option(traversal warn)",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [b] is not null " +
+ "order by [c] option(traversal WARN) " +
+ "/* xpath: //*[@a or @b] " +
+ "order by @c " +
+ "option(traversal warn) */");
+ verify("/jcr:root/(content|libs)//*[@a] order by @c option(traversal ok)",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and isdescendantnode(a, '/content') " +
+ "/* xpath: /jcr:root/content//*[@a] " +
+ "order by @c option(traversal ok) */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and isdescendantnode(a, '/libs') " +
+ "/* xpath: /jcr:root/libs//*[@a] " +
+ "order by @c option(traversal ok) */ " +
+ "order by [c] " +
+ "option(traversal OK)");
+ }
+
+ @Test
public void test() throws ParseException {
verify("(/jcr:root/content//*[@a] | /jcr:root/lib//*[@b]) order by @c",
"select [jcr:path], [jcr:score], * " +
@@ -121,6 +160,7 @@ public class XPathTest {
sql = sql.replaceAll(" and ", "\nand ");
sql = sql.replaceAll(" union ", "\nunion ");
sql = sql.replaceAll(" order by ", "\norder by ");
+ sql = sql.replaceAll(" option\\(", "\noption\\(");
sql = sql.replaceAll(" \\/\\* ", "\n/* ");
return sql;
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1765583&r1=1765582&r2=1765583&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java Wed Oct 19 12:20:56 2016
@@ -69,6 +69,34 @@ public class QueryTest extends AbstractR
}
@Test
+ public void traversalOption() throws Exception {
+ Session session = getAdminSession();
+ QueryManager qm = session.getWorkspace().getQueryManager();
+ try {
+ qm.createQuery("//*[@test] option(traversal fail)",
+ "xpath").execute();
+ fail();
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ try {
+ qm.createQuery("select * from [nt:base] option(traversal fail)",
+ Query.JCR_SQL2).execute();
+ fail();
+ } catch (InvalidQueryException e) {
+ // expected
+ }
+ qm.createQuery("//*[@test] option(traversal ok)",
+ "xpath").execute();
+ qm.createQuery("//*[@test] option(traversal warn)",
+ "xpath").execute();
+ qm.createQuery("select * from [nt:base] option(traversal ok)",
+ Query.JCR_SQL2).execute();
+ qm.createQuery("select * from [nt:base] option(traversal warn)",
+ Query.JCR_SQL2).execute();
+ }
+
+ @Test
public void firstSelector() throws Exception {
Session session = getAdminSession();
Node root = session.getRootNode();
Re: svn commit: r1765583 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-cor...
Posted by Julian Sedding <js...@gmail.com>.
Thanks Chetan!
On Fri, Oct 21, 2016 at 2:59 PM, Chetan Mehrotra
<ch...@gmail.com> wrote:
> On Thu, Oct 20, 2016 at 6:08 PM, Julian Sedding <js...@gmail.com> wrote:
>> I think we could get away with increasing this to 4.1.0 if we can
>> annotate QueryEngineSettingsMBean with @ProviderType.
>
> Makes sense. Opened OAK-4977 for that
>
> Chetan Mehrotra
Re: svn commit: r1765583 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-cor...
Posted by Chetan Mehrotra <ch...@gmail.com>.
On Thu, Oct 20, 2016 at 6:08 PM, Julian Sedding <js...@gmail.com> wrote:
> I think we could get away with increasing this to 4.1.0 if we can
> annotate QueryEngineSettingsMBean with @ProviderType.
Makes sense. Opened OAK-4977 for that
Chetan Mehrotra
Re: svn commit: r1765583 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-cor...
Posted by Julian Sedding <js...@gmail.com>.
> -@Version("4.0.0")
> +@Version("5.0.0")
> @Export(optional = "provide:=true")
> package org.apache.jackrabbit.oak.api.jmx;
I think we could get away with increasing this to 4.1.0 if we can
annotate QueryEngineSettingsMBean with @ProviderType. I.e. we don't
expect API consumers to implement QueryEngineSettingsMBean and
therefore the API change is irrelevant for them.
WDYT?
Regards
Julian
On Wed, Oct 19, 2016 at 2:20 PM, <th...@apache.org> wrote:
> Author: thomasm
> Date: Wed Oct 19 12:20:56 2016
> New Revision: 1765583
>
> URL: http://svn.apache.org/viewvc?rev=1765583&view=rev
> Log:
> OAK-4888 Warn or fail queries above a configurable cost value
>
> Added:
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java
> Modified:
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
> jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
> jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
> jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
> jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/QueryEngineSettingsMBean.java Wed Oct 19 12:20:56 2016
> @@ -51,4 +51,19 @@ public interface QueryEngineSettingsMBea
> */
> void setLimitReads(long limitReads);
>
> + /**
> + * Whether queries that don't use an index will fail (throw an exception).
> + * The default is false.
> + *
> + * @return true if they fail
> + */
> + boolean getFailTraversal();
> +
> + /**
> + * Set whether queries that don't use an index will fail (throw an exception).
> + *
> + * @param failTraversal the new value for this setting
> + */
> + void setFailTraversal(boolean failTraversal);
> +
> }
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/jmx/package-info.java Wed Oct 19 12:20:56 2016
> @@ -15,7 +15,7 @@
> * limitations under the License.
> */
>
> -@Version("4.0.0")
> +@Version("5.0.0")
> @Export(optional = "provide:=true")
> package org.apache.jackrabbit.oak.api.jmx;
>
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java Wed Oct 19 12:20:56 2016
> @@ -434,7 +434,7 @@ public class ContentMirrorStoreStrategy
> readCount++;
> if (readCount % TRAVERSING_WARN == 0) {
> FilterIterators.checkReadLimit(readCount, settings);
> - LOG.warn("Traversed {} nodes ({} index entries) using index {} with filter {}", readCount, intermediateNodeReadCount, indexName, filter);
> + LOG.warn("Index-Traversed {} nodes ({} index entries) using index {} with filter {}", readCount, intermediateNodeReadCount, indexName, filter);
> }
> return;
> } else {
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Wed Oct 19 12:20:56 2016
> @@ -183,4 +183,11 @@ public interface Query {
> */
> boolean containsUnfilteredFullTextCondition();
>
> + /**
> + * Set the query option to be used for this query.
> + *
> + * @param options the options
> + */
> + void setQueryOptions(QueryOptions options);
> +
> }
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettings.java Wed Oct 19 12:20:56 2016
> @@ -35,7 +35,10 @@ public class QueryEngineSettings impleme
> Integer.getInteger("oak.queryLimitInMemory", Integer.MAX_VALUE);
>
> private static final int DEFAULT_QUERY_LIMIT_READS =
> - Integer.getInteger("oak.queryLimitReads", Integer.MAX_VALUE);
> + Integer.getInteger("oak.queryLimitReads", Integer.MAX_VALUE);
> +
> + private static final boolean DEFAULT_FAIL_TRAVERSAL =
> + Boolean.getBoolean("oak.queryFailTraversal");
>
> private static final boolean DEFAULT_FULL_TEXT_COMPARISON_WITHOUT_INDEX =
> Boolean.getBoolean("oak.queryFullTextComparisonWithoutIndex");
> @@ -44,6 +47,8 @@ public class QueryEngineSettings impleme
>
> private long limitReads = DEFAULT_QUERY_LIMIT_READS;
>
> + private boolean failTraversal = DEFAULT_FAIL_TRAVERSAL;
> +
> private boolean fullTextComparisonWithoutIndex =
> DEFAULT_FULL_TEXT_COMPARISON_WITHOUT_INDEX;
>
> @@ -72,6 +77,16 @@ public class QueryEngineSettings impleme
> this.limitReads = limitReads;
> }
>
> + @Override
> + public boolean getFailTraversal() {
> + return failTraversal;
> + }
> +
> + @Override
> + public void setFailTraversal(boolean failTraversal) {
> + this.failTraversal = failTraversal;
> + }
> +
> public void setFullTextComparisonWithoutIndex(boolean fullTextComparisonWithoutIndex) {
> this.fullTextComparisonWithoutIndex = fullTextComparisonWithoutIndex;
> }
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineSettingsMBeanImpl.java Wed Oct 19 12:20:56 2016
> @@ -70,6 +70,16 @@ public class QueryEngineSettingsMBeanImp
> settings.setLimitReads(limitReads);
> }
>
> + @Override
> + public boolean getFailTraversal() {
> + return settings.getFailTraversal();
> + }
> +
> + @Override
> + public void setFailTraversal(boolean failQueriesWithoutIndex) {
> + settings.setFailTraversal(failQueriesWithoutIndex);
> + }
> +
> public void setFullTextComparisonWithoutIndex(boolean fullTextComparisonWithoutIndex) {
> settings.setFullTextComparisonWithoutIndex(fullTextComparisonWithoutIndex);
> }
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Wed Oct 19 12:20:56 2016
> @@ -36,6 +36,7 @@ import org.apache.jackrabbit.oak.api.Res
> import org.apache.jackrabbit.oak.api.Tree;
> import org.apache.jackrabbit.oak.namepath.JcrPathParser;
> import org.apache.jackrabbit.oak.namepath.NamePathMapper;
> +import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
> import org.apache.jackrabbit.oak.query.ast.AndImpl;
> import org.apache.jackrabbit.oak.query.ast.AstVisitorBase;
> import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
> @@ -160,6 +161,11 @@ public class QueryImpl implements Query
> * purposes.
> */
> private boolean traversalEnabled = true;
> +
> + /**
> + * The query option to be used for this query.
> + */
> + private QueryOptions queryOptions = new QueryOptions();
>
> private OrderingImpl[] orderings;
> private ColumnImpl[] columns;
> @@ -948,6 +954,11 @@ public class QueryImpl implements Query
> this.traversalEnabled = traversalEnabled;
> }
>
> + @Override
> + public void setQueryOptions(QueryOptions options) {
> + this.queryOptions = options;
> + }
> +
> public SelectorExecutionPlan getBestSelectorExecutionPlan(FilterImpl filter) {
> return getBestSelectorExecutionPlan(context.getBaseState(), filter,
> context.getIndexProvider(), traversalEnabled);
> @@ -1036,7 +1047,27 @@ public class QueryImpl implements Query
> bestPlan = indexPlan;
> }
> }
> -
> + if (bestIndex == null) {
> + QueryOptions.Traversal traversal = queryOptions.traversal;
> + if (traversal == Traversal.DEFAULT) {
> + // use the (configured) default
> + traversal = settings.getFailTraversal() ? Traversal.FAIL : Traversal.WARN;
> + } else {
> + // explicitly set in the query
> + traversal = queryOptions.traversal;
> + }
> + String message = "Traversal query (query without index): " + statement + "; consider creating an index";
> + switch (traversal) {
> + case OK:
> + break;
> + case WARN:
> + LOG.warn(message);
> + break;
> + case FAIL:
> + LOG.warn(message);
> + throw new IllegalArgumentException(message);
> + }
> + }
> if (traversalEnabled) {
> QueryIndex traversal = new TraversingIndex();
> double cost = traversal.getCost(filter, rootState);
>
> Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java?rev=1765583&view=auto
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java (added)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java Wed Oct 19 12:20:56 2016
> @@ -0,0 +1,34 @@
> +/*
> + * 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;
> +
> +/**
> + * A query options (or "hints") that are used to customize the way the query is processed.
> + */
> +public class QueryOptions {
> +
> + public Traversal traversal = Traversal.DEFAULT;
> +
> + public enum Traversal {
> + // traversing without index is OK for this query, and does not fail or log a warning
> + OK,
> + // traversing is OK, but logs a warning
> + WARN,
> + // traversing will fail the query
> + FAIL,
> + // the default setting
> + DEFAULT
> + };
> +
> +}
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Wed Oct 19 12:20:56 2016
> @@ -24,6 +24,7 @@ import java.text.ParseException;
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.HashMap;
> +import java.util.Locale;
> import java.util.Map;
>
> import javax.jcr.PropertyType;
> @@ -34,6 +35,7 @@ import org.apache.jackrabbit.oak.api.Que
> import org.apache.jackrabbit.oak.api.Type;
> import org.apache.jackrabbit.oak.commons.PathUtils;
> import org.apache.jackrabbit.oak.namepath.NamePathMapper;
> +import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
> import org.apache.jackrabbit.oak.query.ast.AstElementFactory;
> import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
> import org.apache.jackrabbit.oak.query.ast.ColumnImpl;
> @@ -161,6 +163,15 @@ public class SQL2Parser {
> read("BY");
> orderings = parseOrder();
> }
> + QueryOptions options = new QueryOptions();
> + if (readIf("OPTION")) {
> + read("(");
> + if (readIf("TRAVERSAL")) {
> + String n = readName().toUpperCase(Locale.ENGLISH);
> + options.traversal = Traversal.valueOf(n);
> + }
> + read(")");
> + }
> if (!currentToken.isEmpty()) {
> throw getSyntaxError("<end>");
> }
> @@ -168,6 +179,7 @@ public class SQL2Parser {
> q.setExplain(explain);
> q.setMeasure(measure);
> q.setInternal(isInternal(query));
> + q.setQueryOptions(options);
>
> if (initialise) {
> try {
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java Wed Oct 19 12:20:56 2016
> @@ -118,6 +118,12 @@ public class UnionQueryImpl implements Q
> left.setTraversalEnabled(traversal);
> right.setTraversalEnabled(traversal);
> }
> +
> + @Override
> + public void setQueryOptions(QueryOptions options) {
> + left.setQueryOptions(options);
> + right.setQueryOptions(options);
> + }
>
> @Override
> public void prepare() {
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java Wed Oct 19 12:20:56 2016
> @@ -19,6 +19,8 @@ package org.apache.jackrabbit.oak.query.
> import java.util.ArrayList;
>
> import org.apache.jackrabbit.oak.query.QueryImpl;
> +import org.apache.jackrabbit.oak.query.QueryOptions;
> +import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
> import org.apache.jackrabbit.oak.query.xpath.Expression.AndCondition;
> import org.apache.jackrabbit.oak.query.xpath.Expression.OrCondition;
> import org.apache.jackrabbit.oak.query.xpath.Expression.Property;
> @@ -50,6 +52,8 @@ public class Statement {
>
> String xpathQuery;
>
> + QueryOptions queryOptions = new QueryOptions();
> +
> public Statement optimize() {
> ignoreOrderByScoreDesc();
> if (where == null) {
> @@ -80,6 +84,7 @@ public class Statement {
> union.xpathQuery = xpathQuery;
> union.measure = measure;
> union.explain = explain;
> + union.queryOptions = queryOptions;
>
> return union;
> }
> @@ -209,6 +214,9 @@ public class Statement {
> buff.append(orderList.get(i));
> }
> }
> + if (queryOptions.traversal != Traversal.DEFAULT) {
> + buff.append(" option(traversal " + queryOptions.traversal +")");
> + }
> // leave original xpath string as a comment
> appendXPathAsComment(buff, xpathQuery);
> return buff.toString();
> @@ -296,6 +304,9 @@ public class Statement {
> buff.append(orderList.get(i));
> }
> }
> + if (queryOptions.traversal != Traversal.DEFAULT) {
> + buff.append(" option(traversal " + queryOptions.traversal +")");
> + }
> // leave original xpath string as a comment
> appendXPathAsComment(buff, xpathQuery);
> return buff.toString();
> @@ -314,4 +325,8 @@ public class Statement {
> buff.append(" */");
> }
>
> + public void setQueryOptions(QueryOptions options) {
> + this.queryOptions = options;
> + }
> +
> }
>
> Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java Wed Oct 19 12:20:56 2016
> @@ -17,6 +17,8 @@
> package org.apache.jackrabbit.oak.query.xpath;
>
> import org.apache.jackrabbit.oak.commons.PathUtils;
> +import org.apache.jackrabbit.oak.query.QueryOptions;
> +import org.apache.jackrabbit.oak.query.QueryOptions.Traversal;
> import org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement;
> import org.apache.jackrabbit.util.ISO9075;
> import org.slf4j.Logger;
> @@ -25,6 +27,7 @@ import org.slf4j.LoggerFactory;
> import java.math.BigDecimal;
> import java.text.ParseException;
> import java.util.ArrayList;
> +import java.util.Locale;
>
> /**
> * This class can can convert a XPATH query to a SQL2 query.
> @@ -324,11 +327,21 @@ public class XPathToSQL2Converter {
> statement.addOrderBy(order);
> } while (readIf(","));
> }
> + QueryOptions options = new QueryOptions();
> + if (readIf("option")) {
> + read("(");
> + if (readIf("traversal")) {
> + String type = readIdentifier().toUpperCase(Locale.ENGLISH);
> + options.traversal = Traversal.valueOf(type);
> + }
> + read(")");
> + }
> if (!currentToken.isEmpty()) {
> throw getSyntaxError("<end>");
> }
> statement.setColumnSelector(currentSelector);
> statement.setSelectors(selectors);
> + statement.setQueryOptions(options);
>
> Expression where = null;
> for (Selector s : selectors) {
> @@ -1105,10 +1118,14 @@ public class XPathToSQL2Converter {
> } else {
> UnionStatement union = new UnionStatement(result, stat);
> union.orderList = stat.orderList;
> + union.queryOptions = stat.queryOptions;
> result = union;
> }
> - // can not use clear, because it is shared
> + // reset fields that are used in the union,
> + // but no longer in the individual statements
> + // (can not use clear, because it is shared)
> stat.orderList = new ArrayList<Order>();
> + stat.queryOptions = new QueryOptions();
> }
> return result;
> }
>
> Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java Wed Oct 19 12:20:56 2016
> @@ -54,7 +54,6 @@ public class SQL2ParserTest {
> .convert("/jcr:root/test/*/nt:resource[@jcr:encoding]"));
> p.parse(new XPathToSQL2Converter()
> .convert("/jcr:root/test/*/*/nt:resource[@jcr:encoding]"));
> -
> String xpath = "/jcr:root/etc/commerce/products//*[@cq:commerceType = 'product' " +
> "and ((@size = 'M' or */@size= 'M' or */*/@size = 'M' " +
> "or */*/*/@size = 'M' or */*/*/*/@size = 'M' or */*/*/*/*/@size = 'M'))]";
>
> Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java (original)
> +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java Wed Oct 19 12:20:56 2016
> @@ -34,6 +34,45 @@ public class XPathTest {
> new NodeStateNodeTypeInfoProvider(INITIAL_CONTENT);
>
> @Test
> + public void queryOptions() throws ParseException {
> + verify("/jcr:root/content//*[@a] order by @c option(traversal fail)",
> + "select [jcr:path], [jcr:score], * " +
> + "from [nt:base] as a " +
> + "where [a] is not null " +
> + "and isdescendantnode(a, '/content') " +
> + "order by [c] option(traversal FAIL) " +
> + "/* xpath: /jcr:root/content//*[@a] " +
> + "order by @c " +
> + "option(traversal fail) */");
> + verify("//*[@a or @b] order by @c option(traversal warn)",
> + "select [jcr:path], [jcr:score], * " +
> + "from [nt:base] as a " +
> + "where [a] is not null " +
> + "union select [jcr:path], [jcr:score], * " +
> + "from [nt:base] as a " +
> + "where [b] is not null " +
> + "order by [c] option(traversal WARN) " +
> + "/* xpath: //*[@a or @b] " +
> + "order by @c " +
> + "option(traversal warn) */");
> + verify("/jcr:root/(content|libs)//*[@a] order by @c option(traversal ok)",
> + "select [jcr:path], [jcr:score], * " +
> + "from [nt:base] as a " +
> + "where [a] is not null " +
> + "and isdescendantnode(a, '/content') " +
> + "/* xpath: /jcr:root/content//*[@a] " +
> + "order by @c option(traversal ok) */ " +
> + "union select [jcr:path], [jcr:score], * " +
> + "from [nt:base] as a " +
> + "where [a] is not null " +
> + "and isdescendantnode(a, '/libs') " +
> + "/* xpath: /jcr:root/libs//*[@a] " +
> + "order by @c option(traversal ok) */ " +
> + "order by [c] " +
> + "option(traversal OK)");
> + }
> +
> + @Test
> public void test() throws ParseException {
> verify("(/jcr:root/content//*[@a] | /jcr:root/lib//*[@b]) order by @c",
> "select [jcr:path], [jcr:score], * " +
> @@ -121,6 +160,7 @@ public class XPathTest {
> sql = sql.replaceAll(" and ", "\nand ");
> sql = sql.replaceAll(" union ", "\nunion ");
> sql = sql.replaceAll(" order by ", "\norder by ");
> + sql = sql.replaceAll(" option\\(", "\noption\\(");
> sql = sql.replaceAll(" \\/\\* ", "\n/* ");
> return sql;
> }
>
> Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
> URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1765583&r1=1765582&r2=1765583&view=diff
> ==============================================================================
> --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java (original)
> +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java Wed Oct 19 12:20:56 2016
> @@ -69,6 +69,34 @@ public class QueryTest extends AbstractR
> }
>
> @Test
> + public void traversalOption() throws Exception {
> + Session session = getAdminSession();
> + QueryManager qm = session.getWorkspace().getQueryManager();
> + try {
> + qm.createQuery("//*[@test] option(traversal fail)",
> + "xpath").execute();
> + fail();
> + } catch (InvalidQueryException e) {
> + // expected
> + }
> + try {
> + qm.createQuery("select * from [nt:base] option(traversal fail)",
> + Query.JCR_SQL2).execute();
> + fail();
> + } catch (InvalidQueryException e) {
> + // expected
> + }
> + qm.createQuery("//*[@test] option(traversal ok)",
> + "xpath").execute();
> + qm.createQuery("//*[@test] option(traversal warn)",
> + "xpath").execute();
> + qm.createQuery("select * from [nt:base] option(traversal ok)",
> + Query.JCR_SQL2).execute();
> + qm.createQuery("select * from [nt:base] option(traversal warn)",
> + Query.JCR_SQL2).execute();
> + }
> +
> + @Test
> public void firstSelector() throws Exception {
> Session session = getAdminSession();
> Node root = session.getRootNode();
>
>