Author: thomasm
Date: Thu Oct 24 13:40:51 2013
New Revision: 1535377

URL: http://svn.apache.org/r1535377
Log:
OAK-1116 Query: use indexes for queries with "or" conditions (xpath queries 
only so far)

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.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/resources/org/apache/jackrabbit/oak/query/xpath.txt

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java?rev=1535377&r1=1535376&r2=1535377&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
 Thu Oct 24 13:40:51 2013
@@ -202,6 +202,28 @@ abstract class Expression {
         }
     
     }
+    
+    /**
+     * An "or" condition.
+     */
+    static class OrCondition extends Condition {
+
+        OrCondition(Expression left, Expression right) {
+            super(left, "or", right, Expression.PRECEDENCE_OR);
+        }
+        
+    }
+    
+    /**
+     * An "and" condition.
+     */
+    static class AndCondition extends Condition {
+
+        AndCondition(Expression left, Expression right) {
+            super(left, "and", right, Expression.PRECEDENCE_AND);
+        }
+        
+    }
 
     /**
      * A function call.

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=1535377&r1=1535376&r2=1535377&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
 Thu Oct 24 13:40:51 2013
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.query.
 import java.util.ArrayList;
 
 import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.query.xpath.Expression.OrCondition;
 import org.apache.jackrabbit.oak.query.xpath.Expression.Property;
 
 /**
@@ -43,9 +44,36 @@ public class Statement {
      * All selectors.
      */
     private ArrayList<Selector> selectors;
+    
+    private Expression where;
 
     private ArrayList<Order> orderList = new ArrayList<Order>();
     
+    public Statement optimize() {
+        if (explain || measure || orderList.size() > 0) {
+            return this;
+        }
+        if (where == null) {
+            return this;
+        }
+        if (where instanceof OrCondition) {
+            OrCondition or = (OrCondition) where;
+            Statement s1 = new Statement();
+            s1.columnSelector = columnSelector;
+            s1.selectors = selectors;
+            s1.columnList = columnList;
+            s1.where = or.left;
+            Statement s2 = new Statement();
+            s2.columnSelector = columnSelector;
+            s2.selectors = selectors;
+            s2.columnList = columnList;
+            s2.where = or.right;
+            s2.xpathQuery = xpathQuery;
+            return new UnionStatement(s1, s2);
+        }
+        return this;
+    }
+    
     @Override
     public String toString() {
         StringBuilder buff = new StringBuilder();
@@ -101,10 +129,6 @@ public class Statement {
         }
         
         // where ...
-        Expression where = null;
-        for (Selector s : selectors) {
-            where = Expression.and(where, s.condition);
-        }
         if (where != null) {
             buff.append(" where ").append(where.toString());
         }
@@ -121,9 +145,12 @@ public class Statement {
         }
 
         // leave original xpath string as a comment
-        buff.append(" /* xpath: ");
-        buff.append(xpathQuery);
-        buff.append(" */");
+        if (xpathQuery != null) {
+            buff.append(" /* xpath: ");
+            buff.append(xpathQuery);
+            buff.append(" */");
+        }
+        
         return buff.toString();        
     }
 
@@ -142,6 +169,10 @@ public class Statement {
     public void setSelectors(ArrayList<Selector> selectors) {
         this.selectors = selectors;
     }
+    
+    public void setWhere(Expression where) {
+        this.where = where;
+    }
 
     public void addOrderBy(Order order) {
         this.orderList.add(order);
@@ -154,5 +185,24 @@ public class Statement {
     public void setOriginalQuery(String xpathQuery) {
         this.xpathQuery = xpathQuery;
     }
+    
+    /**
+     * A union statement.
+     */
+    static class UnionStatement extends Statement {
+        
+        private final Statement s1, s2;
+        
+        UnionStatement(Statement s1, Statement s2) {
+            this.s1 = s1;
+            this.s2 = s2;
+        }
+        
+        @Override
+        public String toString() {
+            return s1 + " union " + s2;
+        }
+        
+    }
 
 }

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=1535377&r1=1535376&r2=1535377&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
 Thu Oct 24 13:40:51 2013
@@ -279,6 +279,14 @@ public class XPathToSQL2Converter {
         statement.setColumnSelector(currentSelector);
         statement.setSelectors(selectors);
         
+        Expression where = null;
+        for (Selector s : selectors) {
+            where = Expression.and(where, s.condition);
+        }
+        statement.setWhere(where);
+        
+        statement = statement.optimize();
+        
         return statement.toString();
 
     }
@@ -404,7 +412,7 @@ public class XPathToSQL2Converter {
     private Expression parseConstraint() throws ParseException {
         Expression a = parseAnd();
         while (readIf("or")) {
-            a = new Expression.Condition(a, "or", parseAnd(), 
Expression.PRECEDENCE_OR);
+            a = new Expression.OrCondition(a, parseAnd());
         }
         return a;
     }
@@ -412,7 +420,7 @@ public class XPathToSQL2Converter {
     private Expression parseAnd() throws ParseException {
         Expression a = parseCondition();
         while (readIf("and")) {
-            a = new Expression.Condition(a, "and", parseCondition(), 
Expression.PRECEDENCE_AND);
+            a = new Expression.AndCondition(a, parseCondition());
         }
         return a;
     }

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt?rev=1535377&r1=1535376&r2=1535377&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
 Thu Oct 24 13:40:51 2013
@@ -406,7 +406,7 @@ xpath2sql //element(*, my:type)[(not(@my
 select [jcr:path], [jcr:score], * from [my:type] as a where [my:title] is null 
and [my:subject] is not null /* xpath: //element(*, my:type)[(not(@my:title) 
and @my:subject)] */
 
 xpath2sql //element(*, my:type)[not(@my:title) or @my:subject]
-select [jcr:path], [jcr:score], * from [my:type] as a where [my:title] is null 
or [my:subject] is not null /* xpath: //element(*, my:type)[not(@my:title) or 
@my:subject] */
+select [jcr:path], [jcr:score], * from [my:type] as a where [my:title] is null 
union select [jcr:path], [jcr:score], * from [my:type] as a where [my:subject] 
is not null /* xpath: //element(*, my:type)[not(@my:title) or @my:subject] */
 
 xpath2sql //element(*, my:type)[not(@my:value > 0 and @my:value < 100)]
 select [jcr:path], [jcr:score], * from [my:type] as a where not([my:value] > 0 
and [my:value] < 100) /* xpath: //element(*, my:type)[not(@my:value > 0 and 
@my:value < 100)] */


Reply via email to