Repository: jena
Updated Branches:
  refs/heads/master a1c0532c8 -> e57daddab


JENA-1235: Filter placement and OpDisjunction


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/ec02e99e
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/ec02e99e
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/ec02e99e

Branch: refs/heads/master
Commit: ec02e99e264694817244fa815933f4cc377bb51c
Parents: 59e5e06
Author: Andy Seaborne <a...@apache.org>
Authored: Thu Sep 15 12:34:14 2016 +0100
Committer: Andy Seaborne <a...@apache.org>
Committed: Thu Sep 15 12:34:14 2016 +0100

----------------------------------------------------------------------
 .../optimize/TransformFilterPlacement.java      | 79 ++++++++++++++++----
 .../org/apache/jena/sparql/expr/ExprList.java   |  2 +
 .../sparql/algebra/optimize/TestOptimizer.java  | 28 +++++++
 .../optimize/TestTransformFilterPlacement.java  | 56 +++++++++++++-
 4 files changed, 149 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/ec02e99e/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformFilterPlacement.java
----------------------------------------------------------------------
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformFilterPlacement.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformFilterPlacement.java
index 43c15ed..1ff7537 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformFilterPlacement.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformFilterPlacement.java
@@ -43,7 +43,7 @@ import org.apache.jena.sparql.util.VarUtils ;
  * variables.
  * <p>Process BGP (whether triples or quads) is left as a separate step (but 
after this transform)
  * because it can desirable to reorder the BGP before placing filters,
- * or afterwards.   
+ * or afterwards.
  */
 
 public class TransformFilterPlacement extends TransformCopy {
@@ -194,6 +194,8 @@ public class TransformFilterPlacement extends TransformCopy 
{
             placement = placeJoin(exprs, (OpJoin)input) ;
         else if ( input instanceof OpConditional )
             placement = placeConditional(exprs, (OpConditional)input) ;
+        else if ( input instanceof OpDisjunction )
+            placement = placeDisjunction(exprs, (OpDisjunction)input) ;
         else if ( input instanceof OpLeftJoin )
             placement = placeLeftJoin(exprs, (OpLeftJoin)input) ;
         else if ( input instanceof OpFilter )
@@ -584,12 +586,10 @@ public class TransformFilterPlacement extends 
TransformCopy {
     }
     
     private Placement placeUnion(ExprList exprs, OpUnion input) {
-        if ( false )
-            // Safely but inefficiently do nothing.
-            return null ; //new Placement(input, exprs) ;
-        
         if ( false ) {
-         // Push into both sides.
+            // Push into both sides without thinking.
+            // Left as a safety fallback.
+            
             Op left = input.getLeft() ;
             Placement pLeft = transform(exprs, left) ;
             
@@ -655,11 +655,64 @@ public class TransformFilterPlacement extends 
TransformCopy {
         if ( exprs2 == null )
             exprs2 = emptyList ;
         
-        Op op2 = OpUnion.create(newLeft, newRight) ;
+        //Op op2 = OpUnion.create(newLeft, newRight) ;
+        Op op2 = input.copy(newLeft, newRight) ;
         return result(op2, exprs2) ;
     }
 
-    /** Try to optimize (filter (extend ...)) */
+    private Placement placeDisjunction(ExprList exprs, OpDisjunction input) {
+        // Do on each arm.
+        // better (neater) would be to pass out exprs not placed anywhere. 
+        // Combine with union.
+        
+        if ( false ) {
+            // Push everything, always
+            // Left as a safty fall back.
+            List<Op> x = new ArrayList<>() ;
+            input.getElements().forEach(op->{
+                Placement p = transform(exprs, op) ;
+                if ( isNoChange(p) ) {
+                    x.add(buildFilter(exprs, op)) ;
+                } else {
+                    Op op1 = buildFilter(p) ;
+                    x.add(op1) ;
+                }
+            });
+            return result(input.copy(x), emptyList) ; 
+        }
+
+        // Don't push any expressions that aren't used in any of the arms of 
the disjunction.
+        // This is more about being tidy.
+        List<Expr> unplaced = new ArrayList<>(exprs.getList()) ;
+        //List<Placement> x = 
input.getElements().stream().map(op->transform(exprs, 
op)).collect(Collectors.toList()) ;
+        List<Placement> placements = new ArrayList<>(exprs.size()) ;
+        Boolean someChange = Boolean.FALSE ; 
+        for ( Op op : input.getElements() ) {
+            Placement p = transform(exprs, op) ;
+            if ( isChange(p) ) {
+                unplaced.retainAll(p.unplaced.getList()) ;
+                someChange = Boolean.TRUE ; 
+            } else
+                p = result(op, exprs) ; 
+            placements.add(p) ;
+        };
+
+        if ( ! someChange )
+            return noChangePlacement ;
+
+        List<Expr> retained = new ArrayList<>(exprs.getList()) ;
+        retained.removeAll(unplaced) ;
+
+        // Mutate placements to remove the expres going outside.
+        List<Op> ops = new ArrayList<>(input.size()) ;
+        for ( Placement p : placements ) {
+            // No "noChange" at this point.
+            p.unplaced.getListRaw().removeAll(unplaced) ;
+            ops.add(buildFilter(p)) ;
+        } ;
+        return result(input.copy(ops), new ExprList(unplaced)) ; 
+    }
+
     private Placement placeExtend(ExprList exprs, OpExtend input) {
         return processExtendAssign(exprs, input) ;
     }
@@ -668,6 +721,7 @@ public class TransformFilterPlacement extends TransformCopy 
{
         return processExtendAssign(exprs, input) ;
     }
     
+    /** Try to optimize (filter (extend ...)) , (filter (let ...)) */
     private Placement processExtendAssign(ExprList exprs, OpExtendAssign 
input) {
         // We assume that each (extend) and (assign) is usually in simple form 
-
         // always one assignment. We cope with the general form (multiple
@@ -790,11 +844,7 @@ public class TransformFilterPlacement extends 
TransformCopy {
         return OpVars.fixedVars(op) ;
     }
 
-    /** For any expression now in scope, wrap the op with a filter.
-     * Caution - the ExprList is an in-out argument which is modified.
-     * This function modifies ExprList passed in to remove any filter
-     * that is placed. 
-     */
+    /** For any expression now in scope, wrap the op with a filter. */
     
     private static Op insertAnyFilter$(ExprList unplacedExprs, Collection<Var> 
patternVarsScope, Op op) {
         for (Iterator<Expr> iter = unplacedExprs.iterator(); iter.hasNext();) {
@@ -829,9 +879,8 @@ public class TransformFilterPlacement extends TransformCopy 
{
             return op ;
 
         for ( Expr expr : exprs ) {
-            if ( op == null ) {
+            if ( op == null )
                 op = OpTable.unit() ;
-            }
             op = OpFilter.filter(expr, op) ;
         }
         return op ;

http://git-wip-us.apache.org/repos/asf/jena/blob/ec02e99e/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprList.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprList.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprList.java
index a0c8863..297958c 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprList.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprList.java
@@ -104,6 +104,8 @@ public class ExprList implements Iterable<Expr>
     public void addAll(ExprList exprs)      { 
expressions.addAll(exprs.getList()) ; }
     public void add(Expr expr)              { expressions.add(expr) ; }
     public List<Expr> getList()             { return 
Collections.unmodifiableList(expressions) ; }
+    /** Use only while building ExprList */
+    public List<Expr> getListRaw()          { return expressions ; }
     @Override
     public Iterator<Expr> iterator()        { return expressions.iterator() ; }
     

http://git-wip-us.apache.org/repos/asf/jena/blob/ec02e99e/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestOptimizer.java
----------------------------------------------------------------------
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestOptimizer.java
 
b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestOptimizer.java
index b8656d0..94c0b8d 100644
--- 
a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestOptimizer.java
+++ 
b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestOptimizer.java
@@ -227,6 +227,34 @@ public class TestOptimizer extends AbstractTestTransform
         check(queryString, opExpectedString) ; 
     }
     
+    // JENA-1235
+    @Test public void optimize_02() {
+        String in = StrUtils.strjoinNL
+            (
+             "(filter (exprlist (|| (= ?var3 'ABC') (= ?var3 'XYZ')) (&& 
(regex ?var4 'pat1') (!= ?VAR 123)))"
+             ,"    (bgp"
+             ,"      (triple ?var2 :p1 ?var4)"
+             ,"      (triple ?var2 :p2 ?var3)"
+             ,"    ))") ;
+
+        String out = StrUtils.strjoinNL
+            ("(filter (!= ?VAR 123)"
+             ," (disjunction"
+             ,"  (assign ((?var3 'ABC'))"
+             ,"    (sequence"
+             ,"      (filter (regex ?var4 'pat1')"
+             ,"        (bgp (triple ?var2 :p1 ?var4)))"
+             ,"      (bgp (triple ?var2 :p2 'ABC'))))"
+             ,"  (assign ((?var3 'XYZ'))"
+             ,"    (sequence"
+             ,"      (filter (regex ?var4 'pat1')"
+             ,"        (bgp (triple ?var2 :p1 ?var4)))"
+             ,"      (bgp (triple ?var2 :p2 'XYZ'))))))"
+             ) ;
+        checkAlgebra(in, out) ;
+    }
+
+    
     @Test public void combine_extend_01()
     {
         Op extend = OpExtend.create(OpTable.unit(), new 
VarExprList(Var.alloc("x"), new NodeValueInteger(1)));

http://git-wip-us.apache.org/repos/asf/jena/blob/ec02e99e/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformFilterPlacement.java
----------------------------------------------------------------------
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformFilterPlacement.java
 
b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformFilterPlacement.java
index f06ce3e..494abc2 100644
--- 
a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformFilterPlacement.java
+++ 
b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformFilterPlacement.java
@@ -80,7 +80,6 @@ public class TestTransformFilterPlacement extends BaseTest { 
//extends AbstractT
         testNoBGP("(filter (= ?x 123) (bgp (?s ?p ?x) (?s ?p ?x1) (?s ?p ?x2)) 
)",
                 null) ;
     }
-    
 
     @Test public void place_bgp_06() {
         testNoChange("(filter (isURI ?g) (quadpattern (?g ?s ?p ?o) ))") ;
@@ -811,6 +810,61 @@ public class TestTransformFilterPlacement extends BaseTest 
{ //extends AbstractT
         test( in, out ) ;
     }
     
+    // JENA-1235
+    @Test public void place_disjunction_01() {
+        String in = StrUtils.strjoinNL
+            (
+             "(filter (exprlist (!= ?VAR 123) (regex ?var4 'pat1'))"
+             ,"  (disjunction"
+             ,"    (bgp (?var2 :p1 ?var4) (?var2 :p2 ?var3))"
+             ,"    (bgp (?var2 :p3 ?var4) (?var2 :p4 ?var3))"
+             ,"    ))"
+             ) ;
+
+        String out = StrUtils.strjoinNL
+            ("(filter (!= ?VAR 123)"
+            ,"    (disjunction"
+            ,"      (sequence"
+            ,"        (filter (regex ?var4 'pat1')"
+            ,"          (bgp (triple ?var2 :p1 ?var4)))"
+            ,"        (bgp (triple ?var2 :p2 ?var3)))"
+            ,"      (sequence"
+            ,"        (filter (regex ?var4 'pat1')"
+            ,"          (bgp (triple ?var2 :p3 ?var4)))"
+            ,"        (bgp (triple ?var2 :p4 ?var3)))))"
+                ) ;
+        test( in, out ) ;
+    }
+    
+    // Push in, push and wrap, wrap.
+    @Test public void place_disjunction_02() {
+        String in = StrUtils.strjoinNL
+            (
+             "(filter (exprlist (!= ?VAR 123) (regex ?var4 'pat1'))"
+             ,"  (disjunction"
+             ,"    (bgp (?var2 :p1 ?var4) (?var2 :p2 ?var3))"
+             ,"    (bgp (?var2 :p4 ?var3) (?var2 :p3 ?var4))"
+             ,"    (bgp (?var2 :p4 ?var9))"
+             ,"    ))"
+             ) ;
+        String out = StrUtils.strjoinNL
+            ("(filter (!= ?VAR 123)"
+            ,"  (disjunction"
+            ,"    (sequence"
+            ,"      (filter (regex ?var4 'pat1')"
+            ,"        (bgp (triple ?var2 :p1 ?var4)))"
+            ,"      (bgp (triple ?var2 :p2 ?var3)))"
+            ,"    (filter (regex ?var4 'pat1')"
+            ,"      (bgp"
+            ,"        (triple ?var2 :p4 ?var3)"
+            ,"        (triple ?var2 :p3 ?var4)"
+            ,"      ))"
+            ,"    (filter (regex ?var4 'pat1')"
+            ,"      (bgp (triple ?var2 :p4 ?var9)))))"
+             ) ;
+        test( in, out ) ;
+    }
+    
     private static String propertyFunctionURI = "http://example/PF"; ;
     // Dummy property 
     private static PropertyFunction dummyPropertyFunction = new 
PropertyFunction() {

Reply via email to