Author: thomasm
Date: Fri Nov 20 13:04:18 2015
New Revision: 1715347

URL: http://svn.apache.org/viewvc?rev=1715347&view=rev
Log:
OAK-2539 SQL2 query not working with filter (s.[stringa] = 'a' OR 
CONTAINS(s.[stringb], 'b'))

Modified:
    
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/QueryEngineImpl.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/ast/AndImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotFullTextImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryCostOverheadTest.java

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=1715347&r1=1715346&r2=1715347&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
 Fri Nov 20 13:04:18 2015
@@ -180,18 +180,12 @@ public interface Query {
     boolean isInternal();
 
     /**
-     * <p>
-     * Some queries can bring with them a cost overhead that the query engine 
could consider when
-     * electing the best query between the original SQL2 and the possible 
available optimisations.
-     * </p>
-     * <p>
-     * For example for the case of <a 
href="https://issues.apache.org/jira/browse/OAK-2660"; /> if
-     * you have a case where {@code (a = 'v' OR CONTAINS(b, 'v1') OR 
CONTAINS(c, 'v2')) AND (...)}
-     * currently the query engine does not know how to leverage indexes and 
post conditions and the
-     * query is better suited with a UNION.
-     * </p>
+     * Whether the condition contains a fulltext condition that can not be 
+     * applied to the filter, for example because it is part of an "or" 
condition
+     * of the form "where a=1 or contains(., 'x')".
      * 
-     * @return a positive number or 0. <strong>Cannot be negative.</strong>
-     */
-    double getCostOverhead();
+     * @return true if yes
+     */    
+    boolean containsUnfilteredFullTextCondition();
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
 Fri Nov 20 13:04:18 2015
@@ -295,51 +295,41 @@ public abstract class QueryEngineImpl im
         
         
         if (checkNotNull(queries).size() == 1) {
-            // Optimisation. We only have the original query so we prepare and 
return it.
+            // we only have the original query so we prepare and return it.
             cheapest = queries.iterator().next();
             cheapest.prepare();
             LOG.debug("No optimisations found. Cheapest is the original query: 
{}", cheapest);
             map = new MdcAndPrepared(setupMDC(cheapest), cheapest);
         } else {
-            double bestCost = Double.MAX_VALUE;
-            double originalCost = Double.MAX_VALUE;
-            boolean firstLoop = true;
+            double bestCost = Double.POSITIVE_INFINITY;
+            double originalCost = Double.POSITIVE_INFINITY;
             Query original = null;
             
             // always prepare all of the queries and compute the cheapest as 
it's the default behaviour.
             // It should trigger more errors during unit and integration 
testing. Changing
             // `forceOptimised` flag should be in case used only during 
testing.
             for (Query q : checkNotNull(queries)) {
-                LOG.debug("Preparing: {}", q);
                 q.prepare();
-                
-                double actualCost = q.getEstimatedCost();
-                double costOverhead = q.getCostOverhead();
-                double overallCost = Math.min(actualCost + costOverhead, 
Double.MAX_VALUE);
-                
-                LOG.debug("actualCost: {} - costOverhead: {} - overallCost: 
{}", actualCost,
-                    costOverhead, overallCost);
-                
-                if (firstLoop) {
-                    // first time we're always the best cost. Avoiding 
situations where the original
-                    // query has an overall cost as Double.MAX_VALUE.
-                    bestCost = overallCost;
-                    cheapest = q;
-                    firstLoop = false;
-                } else if (overallCost < bestCost) {
-                    bestCost = overallCost;
+                double cost = q.getEstimatedCost();
+                LOG.debug("cost: {} for query {}", cost, q);
+                if (q.containsUnfilteredFullTextCondition()) {
+                    LOG.debug("contains an unfiltered fulltext condition");
+                    cost = Double.POSITIVE_INFINITY;
+                }
+                if (cheapest == null || cost < bestCost) {
                     cheapest = q;
+                    bestCost = cost;
                 }
                 if (!q.isOptimised()) {
                     original = q;
-                    originalCost = overallCost;
+                    originalCost = cost;
                 }
             }
             
             if (original != null && bestCost == originalCost && cheapest != 
original) {
                 // if the optimised cost is the same as the original SQL2 
query we prefer the original. As
                 // we deal with references the `cheapest!=original` should 
work.
-                LOG.trace("Same cost for original and optimised. Forcing 
original");
+                LOG.trace("Same cost for original and optimised. Using 
original");
                 cheapest = original;
             }
 

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=1715347&r1=1715346&r2=1715347&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
 Fri Nov 20 13:04:18 2015
@@ -86,7 +86,6 @@ import org.apache.jackrabbit.oak.query.p
 import org.apache.jackrabbit.oak.query.plan.SelectorExecutionPlan;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
-import org.apache.jackrabbit.oak.spi.query.QueryConstants;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex.AdvancedQueryIndex;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan;
@@ -1321,48 +1320,8 @@ public class QueryImpl implements Query
     }
 
     @Override
-    public double getCostOverhead() {
-        return oak2660CostOverhead(getConstraint());
+    public boolean containsUnfilteredFullTextCondition() {
+        return constraint.containsUnfilteredFullTextCondition();
     }
 
-    /**
-     * compute a cost overhead for the OAK-2660 use case. The query engine 
better perform/compute
-     * the use case `(a = 'v' OR CONTAINS(b, 'v1') OR CONTAINS(c, 'v2') AND 
(...)` as a UNION query
-     * to leverage different indexes. In this case we return an 'Infinity' 
overhead for make the
-     * query engine choose a union query instead.
-     * 
-     * @param constraint the constraint to analyse. Cannot be null.
-     * @return
-     */
-    private double oak2660CostOverhead(@Nonnull ConstraintImpl constraint) {
-        if (checkNotNull(constraint) instanceof OrImpl) {
-            boolean fulltext = false, plain = false;
-            for (ConstraintImpl c : constraint.getConstraints()) {
-                if (c instanceof FullTextSearchImpl) {
-                    fulltext = true;
-                } else {
-                    plain = true;
-                }
-                
-                if (fulltext && plain) {
-                    return Double.MAX_VALUE;
-                }
-            }
-        } else {
-            List<ConstraintImpl> cs = constraint.getConstraints();
-            if (cs == null) {
-                return 0;
-            } else {
-                double cost = 0;
-                for (ConstraintImpl c : cs) {
-                    cost += oak2660CostOverhead(c);
-                    if (cost == Double.MAX_VALUE) {
-                        return cost;
-                    }
-                }
-                return cost;
-            }
-        }
-        return 0;
-    }
 }

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=1715347&r1=1715346&r2=1715347&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
 Fri Nov 20 13:04:18 2015
@@ -184,7 +184,7 @@ public class SQL2Parser {
      * as {@link #parse(String, boolean)} by providing {@code true} to the 
initialisation flag.
      * 
      * @param query
-     * @return
+     * @return the parsed query
      * @throws ParseException
      */
     public Query parse(final String query) throws ParseException {

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=1715347&r1=1715346&r2=1715347&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
 Fri Nov 20 13:04:18 2015
@@ -137,7 +137,9 @@ public class UnionQueryImpl implements Q
     
     @Override
     public double getEstimatedCost() {
-        return left.getEstimatedCost() + right.getEstimatedCost();
+        // the cost is higher than the cost of both parts, so that
+        // non-union queries are preferred over union ones
+        return 10 + left.getEstimatedCost() + right.getEstimatedCost();
     }
 
     @Override
@@ -398,8 +400,9 @@ public class UnionQueryImpl implements Q
     }
 
     @Override
-    public double getCostOverhead() {
-        // for now we don't really have any case where a union query should 
suffer from overheads.
-        return 0;
+    public boolean containsUnfilteredFullTextCondition() {
+        return left.containsUnfilteredFullTextCondition() || 
+                right.containsUnfilteredFullTextCondition();
     }
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AndImpl.java
 Fri Nov 20 13:04:18 2015
@@ -43,7 +43,7 @@ public class AndImpl extends ConstraintI
 
     private final List<ConstraintImpl> constraints;
 
-    AndImpl(List<ConstraintImpl> constraints) {
+    public AndImpl(List<ConstraintImpl> constraints) {
         checkArgument(!constraints.isEmpty());
         this.constraints = constraints;
     }
@@ -52,7 +52,6 @@ public class AndImpl extends ConstraintI
         this(Arrays.asList(constraint1, constraint2));
     }
 
-    @Override
     public List<ConstraintImpl> getConstraints() {
         return constraints;
     }
@@ -225,7 +224,7 @@ public class AndImpl extends ConstraintI
         Set<ConstraintImpl> result = Sets.newHashSet();
         Set<ConstraintImpl> nonUnion = Sets.newHashSet();
         
-        for (ConstraintImpl c : getConstraints()) {
+        for (ConstraintImpl c : constraints) {
             Set<ConstraintImpl> ccc = c.simplifyForUnion();
             if (ccc.isEmpty()) {
                 nonUnion.add(c);
@@ -248,5 +247,25 @@ public class AndImpl extends ConstraintI
         
         return result;
     }
+    
+    @Override
+    public boolean requiresFullTextIndex() {
+        for (ConstraintImpl c : constraints) {
+            if (c.requiresFullTextIndex()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean containsUnfilteredFullTextCondition() {
+        for (ConstraintImpl c : constraints) {
+            if (c.containsUnfilteredFullTextCondition()) {
+                return true;
+            }
+        }
+        return false;
+    }
 
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
 Fri Nov 20 13:04:18 2015
@@ -30,14 +30,11 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.query.fulltext.LikePattern;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * A comparison operation (including "like").
  */
 public class ComparisonImpl extends ConstraintImpl {
-    private static final Logger LOG = 
LoggerFactory.getLogger(ComparisonImpl.class);
     
     private final DynamicOperandImpl operand1;
     private final Operator operator;

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ConstraintImpl.java
 Fri Nov 20 13:04:18 2015
@@ -17,11 +17,9 @@
 package org.apache.jackrabbit.oak.query.ast;
 
 import java.util.Collections;
-import java.util.List;
 import java.util.Set;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -142,13 +140,24 @@ public abstract class ConstraintImpl ext
     }
     
     /**
+     * Whether the constraint contains a fulltext condition that requires
+     * using a fulltext index, because the condition can only be evaluated 
there.
      * 
-     * @return the list of {@link ConstraintImpl} that the current constraint 
could hold. Default
-     *         implementation returns {@code null}.
+     * @return true if yes
      */
-    @Nullable
-    public List<ConstraintImpl> getConstraints() {
-        return null;
+    public boolean requiresFullTextIndex() {
+        return false;
+    }
+    
+    /**
+     * Whether the condition contains a fulltext condition that can not be 
+     * applied to the filter, for example because it is part of an "or" 
condition
+     * of the form "where a=1 or contains(., 'x')".
+     * 
+     * @return true if yes
+     */
+    public boolean containsUnfilteredFullTextCondition() {
+        return false;
     }
     
     /**
@@ -165,7 +174,7 @@ public abstract class ConstraintImpl ext
      * set.
      * </p>
      * 
-     * @return
+     * @return the set of constraints, if available
      */
     @Nonnull
     public Set<ConstraintImpl> simplifyForUnion() {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
 Fri Nov 20 13:04:18 2015
@@ -308,4 +308,10 @@ public class FullTextSearchImpl extends
     public AstElement copyOf() {
         return new FullTextSearchImpl(selectorName, propertyName, 
fullTextSearchExpression);
     }
+
+    @Override
+    public boolean requiresFullTextIndex() {
+        return true;
+    }
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java
 Fri Nov 20 13:04:18 2015
@@ -111,4 +111,10 @@ public class NativeFunctionImpl extends
     public AstElement copyOf() {
         return new NativeFunctionImpl(selectorName, language, 
nativeSearchExpression);
     }
+
+    @Override
+    public boolean requiresFullTextIndex() {
+        return true;
+    }
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotFullTextImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotFullTextImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotFullTextImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotFullTextImpl.java
 Fri Nov 20 13:04:18 2015
@@ -51,6 +51,14 @@ public class NotFullTextImpl extends Not
     
     @Override
     public FullTextExpression getFullTextConstraint(SelectorImpl s) {
+        // TODO is this correct?
+        ;
         return getConstraint().getFullTextConstraint(s);
     }
+
+    @Override
+    public boolean requiresFullTextIndex() {
+        return true;
+    }
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NotImpl.java
 Fri Nov 20 13:04:18 2015
@@ -116,4 +116,20 @@ public class NotImpl extends ConstraintI
     public AstElement copyOf() {
         return new NotImpl((ConstraintImpl) 
copyElementAndCheckReference(constraint));
     }
+
+    @Override
+    public boolean requiresFullTextIndex() {
+        return constraint.requiresFullTextIndex();
+    }
+
+    @Override
+    public boolean containsUnfilteredFullTextCondition() {
+        // If the constraint is a fulltext condition,
+        // then we can not apply it, as in "not contains(., 'x')".
+        // Also, if the constraint _contains_ a unfiltered fulltext condition, 
as in
+        // "not (x=1 or contains(., 'x')".
+        return constraint.requiresFullTextIndex() || 
+                constraint.requiresFullTextIndex();
+    }
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/OrImpl.java
 Fri Nov 20 13:04:18 2015
@@ -47,7 +47,7 @@ public class OrImpl extends ConstraintIm
 
     private final List<ConstraintImpl> constraints;
 
-    OrImpl(List<ConstraintImpl> constraints) {
+    public OrImpl(List<ConstraintImpl> constraints) {
         checkArgument(!constraints.isEmpty());
         this.constraints = constraints;
     }
@@ -56,7 +56,6 @@ public class OrImpl extends ConstraintIm
         this(Arrays.asList(constraint1, constraint2));
     }
 
-    @Override
     public List<ConstraintImpl> getConstraints() {
         return constraints;
     }
@@ -371,4 +370,41 @@ public class OrImpl extends ConstraintIm
         }
         return cc;
     }
+
+    @Override
+    public boolean requiresFullTextIndex() {
+        for (ConstraintImpl c : getConstraints()) {
+            if (c.requiresFullTextIndex()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean containsUnfilteredFullTextCondition() {
+        boolean fulltext = false;
+        boolean plain = false;
+        for (ConstraintImpl c : constraints) {
+            // this part of the condition already contains an unfiltered
+            // condition, so we don't need to check further
+            if (c.containsUnfilteredFullTextCondition()) {
+                return true;
+            }
+            if (c.requiresFullTextIndex()) {
+                // for example "contains(a, 'x')"
+                fulltext = true;
+            } else {
+                // for example "b=123"
+                plain = true;
+            }
+            // the full-text index contains both typescan not be used for 
conditions
+            // of the form "contains(a, 'x') or b=123"
+            if (fulltext && plain) {
+                return true;
+            }
+        }
+        return false;
+    }    
+
 }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SimilarImpl.java
 Fri Nov 20 13:04:18 2015
@@ -132,4 +132,9 @@ public class SimilarImpl extends Constra
         return new SimilarImpl(selectorName, propertyName, pathExpression);
     }
 
+    @Override
+    public boolean requiresFullTextIndex() {
+        return true;
+    }
+
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SpellcheckImpl.java
 Fri Nov 20 13:04:18 2015
@@ -119,4 +119,9 @@ public class SpellcheckImpl extends Cons
         return new SpellcheckImpl(selectorName, expression);
     }
 
+    @Override
+    public boolean requiresFullTextIndex() {
+        return true;
+    }
+
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SuggestImpl.java
 Fri Nov 20 13:04:18 2015
@@ -118,4 +118,10 @@ public class SuggestImpl extends Constra
     public AstElement copyOf() {
         return new SuggestImpl(selectorName, expression);
     }
+
+    @Override
+    public boolean requiresFullTextIndex() {
+        return true;
+    }
+
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
 Fri Nov 20 13:04:18 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("2.5")
+@Version("3.0")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.query;
 

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryCostOverheadTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryCostOverheadTest.java?rev=1715347&r1=1715346&r2=1715347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryCostOverheadTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryCostOverheadTest.java
 Fri Nov 20 13:04:18 2015
@@ -17,9 +17,9 @@
 package org.apache.jackrabbit.oak.query;
 
 import static com.google.common.collect.ImmutableList.of;
-import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import org.apache.jackrabbit.oak.query.ast.AndImpl;
 import org.apache.jackrabbit.oak.query.ast.ComparisonImpl;
@@ -32,70 +32,64 @@ import org.junit.Test;
 public class QueryCostOverheadTest {
     @Test
     public void getCostOverhead() {
-        final double allowedDelta = 10;
         QueryImpl query;
         UnionQueryImpl union;
         ConstraintImpl c, c1, c2, c3, c4, c5;
         
-        union = new UnionQueryImpl(false, null, null, null);
-        assertEquals("we always expect 0 from a `UnionQueryImpl`", 0, 
union.getCostOverhead(),
-            allowedDelta);
+        c1 = new ComparisonImpl(null, null, null);
+        c2 = new FullTextSearchImpl(null, null, null);
+        union = new UnionQueryImpl(false,
+                new QueryImpl(null, null, c1, null, null, null),
+                new QueryImpl(null, null, c2, null, null, null),
+                null);
+        assertFalse("we always expect false from a `UnionQueryImpl`", 
+                union.containsUnfilteredFullTextCondition());
         
-        c = mock(OrImpl.class);
-        c1 = mock(ComparisonImpl.class);
-        c2 = mock(FullTextSearchImpl.class);
-        when(c.getConstraints()).thenReturn(of(c1, c2));
-        query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(Double.MAX_VALUE, query.getCostOverhead(), allowedDelta);
-
-        c = mock(OrImpl.class);
-        c1 = mock(ComparisonImpl.class);
-        c2 = mock(FullTextSearchImpl.class);
-        c3 = mock(FullTextSearchImpl.class);
-        when(c.getConstraints()).thenReturn(of(c1, c2, c3));
+        c1 = new ComparisonImpl(null, null, null);
+        c2 = new FullTextSearchImpl(null, null, null);
+        c = new OrImpl(c1, c2);
+        query = new QueryImpl(null, null, c, null, null, null);
+        assertTrue(query.containsUnfilteredFullTextCondition());
+
+        c1 = new ComparisonImpl(null, null, null);
+        c2 = new FullTextSearchImpl(null, null, null);
+        c3 = new FullTextSearchImpl(null, null, null);
+        c = new OrImpl(of(c1, c2, c3));
         query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(Double.MAX_VALUE, query.getCostOverhead(), allowedDelta);
+        assertTrue(query.containsUnfilteredFullTextCondition());
         
-        c1 = mock(OrImpl.class);
-        c2 = mock(FullTextSearchImpl.class);
-        c3 = mock(FullTextSearchImpl.class);
-        c4 = mock(ComparisonImpl.class);
-        when(c1.getConstraints()).thenReturn(of(c2, c3, c4));
-        c = mock(AndImpl.class);
+        c2 = new FullTextSearchImpl(null, null, null);
+        c3 = new FullTextSearchImpl(null, null, null);
+        c4 = new ComparisonImpl(null, null, null);
+        c1 = new OrImpl(of(c2, c3, c4));
         c5 = mock(DescendantNodeImpl.class);
-        when(c.getConstraints()).thenReturn(of(c1, c5));
+        c = new AndImpl(c1, c5);
         query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(Double.MAX_VALUE, query.getCostOverhead(), allowedDelta);
+        assertTrue(query.containsUnfilteredFullTextCondition());
         
-        c = mock(FullTextSearchImpl.class);
+        c = new FullTextSearchImpl(null, null, null);
         query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(0, query.getCostOverhead(), allowedDelta);
+        assertFalse(query.containsUnfilteredFullTextCondition());
 
-        c = mock(OrImpl.class);
-        c1 = mock(FullTextSearchImpl.class);
-        c2 = mock(FullTextSearchImpl.class);
-        c3 = mock(FullTextSearchImpl.class);
-        when(c.getConstraints()).thenReturn(of(c1, c2, c3));
+        c1 = new FullTextSearchImpl(null, null, null);
+        c2 = new FullTextSearchImpl(null, null, null);
+        c3 = new FullTextSearchImpl(null, null, null);
+        c = new OrImpl(of(c1, c2, c3));
         query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(0, query.getCostOverhead(), allowedDelta);
+        assertFalse(query.containsUnfilteredFullTextCondition());
         
-        c = mock(AndImpl.class);
-        c1 = mock(ComparisonImpl.class);
-        c2 = mock(FullTextSearchImpl.class);
-        c3 = mock(FullTextSearchImpl.class);
-        when(c.getConstraints()).thenReturn(of(c1, c2, c3));
+        c1 = new ComparisonImpl(null, null, null);
+        c2 = new FullTextSearchImpl(null, null, null);
+        c3 = new FullTextSearchImpl(null, null, null);
+        c = new AndImpl(of(c1, c2, c3));
+        query = new QueryImpl(null, null, c, null, null, null);
+        assertFalse(query.containsUnfilteredFullTextCondition());
+
+        c1 = new ComparisonImpl(null, null, null);
+        c2 = new ComparisonImpl(null, null, null);
+        c = new AndImpl(of(c1, c2, c3));
         query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(0, query.getCostOverhead(), allowedDelta);
+        assertFalse(query.containsUnfilteredFullTextCondition());
 
-        c = mock(AndImpl.class);
-        c1 = mock(ComparisonImpl.class);
-        c2 = mock(ComparisonImpl.class);
-        when(c.getConstraints()).thenReturn(of(c1, c2, c3));
-        query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(0, query.getCostOverhead(), allowedDelta);
-
-        c2 = mock(ComparisonImpl.class);
-        query = new QueryImpl(null, null, c, null, null, null);
-        assertEquals(0, query.getCostOverhead(), allowedDelta);
     }
 }


Reply via email to