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();


Reply via email to