Author: andy
Date: Thu Nov 14 16:51:06 2013
New Revision: 1541973

URL: http://svn.apache.org/r1541973
Log:
Filter placement experiments.

Modified:
    jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java
    jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java
    jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java

Modified: jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java?rev=1541973&r1=1541972&r2=1541973&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java Thu Nov 14 16:51:06 2013
@@ -18,19 +18,35 @@
 
 package opt;
 
+import static opt.TransformFilterPlacement_New.insertAnyFilter ;
+
+import java.util.Collection ;
+import java.util.HashSet ;
+import java.util.Set ;
+
 import com.hp.hpl.jena.query.Query ;
 import com.hp.hpl.jena.query.QueryFactory ;
-import com.hp.hpl.jena.sparql.algebra.Algebra ;
-import com.hp.hpl.jena.sparql.algebra.Op ;
-import com.hp.hpl.jena.sparql.algebra.Transform ;
-import com.hp.hpl.jena.sparql.algebra.Transformer ;
-import com.hp.hpl.jena.sparql.algebra.optimize.TransformFilterConjunction ;
+import com.hp.hpl.jena.sparql.algebra.* ;
+import com.hp.hpl.jena.sparql.algebra.op.OpFilter ;
+import com.hp.hpl.jena.sparql.algebra.op.OpJoin ;
+import com.hp.hpl.jena.sparql.algebra.op.OpSequence ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
 import com.hp.hpl.jena.sparql.sse.SSE ;
 
+
 public class OptMain {
 
     public static void main(String... argv) throws Exception {
-        // Cominations e.g. placement then equality
+        // What about covered left but partial right?
+        // Push left (join),)
+        // Push left (left join) 
+        // Other cases
+        
+        // Also TransformDistinctToReduced (JENA-585)and 
TransformOrderByDistincApplication 
+        
+        // Combinations e.g. placement then equality
         
         
         // JENA-383 : The query optimizer generates a suboptimal query plan in 
case of nested optionals followed by a filter
@@ -45,7 +61,7 @@ public class OptMain {
         // Need to say what was pushed.
         
         
-        if ( true ) {
+        if ( false ) {
             String input = "(filter (= ?x 123) (join (bgp (?s ?p ?x)) (bgp (?s 
?p ?z)) ))" ;
             Transform t_placement = new TransformFilterPlacement_New() ;
             Op op1 = SSE.parseOp(input) ;
@@ -55,20 +71,100 @@ public class OptMain {
             //System.exit(0) ;
         }
 
+        // What about covered left but partial right?
+        // Push left (join),)
+        // Push left (left join) 
+        // Other cases
+        
         if ( true ) {
-            String x = "SELECT * { ?s ?p ?o . FILTER (13=14) FILTER(?o1 > 12) 
FILTER(?o < 56)  OPTIONAL { ?s ?p1 ?o1 } }" ;
+            String x = "SELECT * { {?s ?p ?o} . FILTER (13=14) FILTER(?o1 > 
12) FILTER(?o < 56)  FILTER(?o1+?o > 999) { ?s ?p1 ?o1 } }" ;
             Query query = QueryFactory.create(x) ;
             Op op1 = Algebra.compile(query) ;
+            /*
+Setting                       
+WriterLib.start(IndentedWriter out, String tag, int linePolicy)
+WriterLib.finish(IndentedWriter out, String tag)
+to use ""
+             */
+            
             System.out.println(op1) ;
             
-            // && to list
-            Op op2 = Transformer.transform(new TransformFilterConjunction(), 
op1) ;
-            //Op op2 = Algebra.optimize(op1) ;
-            //System.out.println(op2) ;
+            ExprList exprs = ((OpFilter)op1).getExprs() ;
+            OpJoin opJoin = (OpJoin)((OpFilter)op1).getSubOp() ;
+            
+            Set<Var> scope = new HashSet<Var>() ;
+            Op op = transformFilterJoin(exprs, scope, opJoin) ;
+            if ( ! exprs.isEmpty() )
+                op = OpFilter.filter(exprs, op) ;
             
-            Op op3 = Transformer.transform(new TransformFilterPlacement_New(), 
op2) ;
-            System.out.println(op3) ;
+            System.out.println(op) ;
+            
+//            // && to list
+//            Op op2 = Transformer.transform(new TransformFilterConjunction(), 
op1) ;
+//            //Op op2 = Algebra.optimize(op1) ;
+//            //System.out.println(op2) ;
+//            
+//            Op op3 = Transformer.transform(new 
TransformFilterPlacement_New(), op2) ;
+//            System.out.println(op3) ;
             System.exit(0) ;
         }
     }
+    
+    private static Op transformFilterJoin(ExprList exprs, Set<Var> varScope, 
OpJoin opJoin)
+    {
+        
+        // Any filters that depend on no variables. 
+        Op opInitial = insertAnyFilter(exprs, varScope, null) ;
+        if ( opInitial == opJoin )
+            opInitial = null ;
+        
+        Op left = opJoin.getLeft() ;
+        Op right = opJoin.getRight() ;
+        Collection<Var> leftVars = OpVars.mentionedVars(left) ;
+        Collection<Var> rightVars = OpVars.mentionedVars(right) ;
+        ExprList unpushed = new ExprList() ;
+        ExprList pushLeft = new ExprList() ;
+        ExprList pushRight = new ExprList() ;
+        
+        
+        for ( Expr expr : exprs ) {
+            Set<Var> vars = expr.getVarsMentioned() ;
+            boolean pushed = false ;
+            
+            if ( leftVars.containsAll(vars) ) {
+                pushLeft.add(expr) ;
+                pushed = true ;
+            }
+            // If left only, make this "else if"
+            
+            if ( rightVars.containsAll(vars) ) {
+                // Push right
+                pushRight.add(expr) ;
+                pushed = true ;
+            } 
+            
+            if ( ! pushed )
+                unpushed.add(expr); 
+        }
+        
+        if ( pushLeft.isEmpty() && pushRight.isEmpty() )
+            return opJoin ;
+        
+        Op opLeftNew = left ;
+        if ( ! pushLeft.isEmpty() )
+            opLeftNew = OpFilter.filter(pushLeft, opLeftNew) ;
+
+        Op opRightNew = right ;
+        if ( ! pushRight.isEmpty() )
+            opRightNew = OpFilter.filter(pushRight, opRightNew) ;
+        
+        // HACK
+        exprs.getList().clear() ;
+        exprs.getList().addAll(unpushed.getList()) ;
+        
+        Op op = OpJoin.create(opLeftNew, opRightNew) ;
+        if ( opInitial != null )
+            op = OpSequence.create(opInitial, op) ;
+        return op ;
+    }
 }

Modified: jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java?rev=1541973&r1=1541972&r2=1541973&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java Thu Nov 14 
16:51:06 2013
@@ -18,6 +18,7 @@
 
 package opt ;
 
+import org.apache.jena.atlas.lib.StrUtils ;
 import org.junit.Assert ;
 import org.junit.Test ;
 
@@ -90,13 +91,37 @@ public class TestFilterPlacement {
              "(join (filter (= ?x 123) (bgp (?s ?p ?x))) (bgp (?s ?p ?z)) )") ;
     }
 
-    // Join
+    // Join : two side push
     @Test
     public void place_filter_join_02() {
         test("(filter (= ?x 123) (join (bgp (?s ?p ?x)) (bgp (?s ?p ?x)) ))",
              "(join  (filter (= ?x 123) (bgp (?s ?p ?x))) (filter (= ?x 123) 
(bgp (?s ?p ?x))) )") ;
     }
 
+
+    @Test
+    public void place_filter_join_03() {
+        String x = StrUtils.strjoinNL
+            ("(filter ((= 13 14) (> ?o1 12) (< ?o 56) (< (+ ?o ?o1) 999))",
+             "   (join", 
+             "      (bgp (triple ?s ?p ?o))" ,
+             "      (bgp (triple ?s ?p1 ?o1))))") ;
+        
+        String y = StrUtils.strjoinNL
+            ("(filter (< (+ ?o ?o1) 999)",
+             "  (sequence",
+             "    (filter (= 13 14)",
+             "    (table unit))",
+             " (join",
+             "   (filter (< ?o 56)", 
+             "     (bgp (triple ?s ?p ?o)))", 
+             "   (filter (> ?o1 12)", 
+             "     (bgp (triple ?s ?p1 ?o1))))))") ;
+        
+        test(x, y) ;
+    }
+
+
     @Test
     public void place_filter_conditional_01() {
         // conditional

Modified: jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java?rev=1541973&r1=1541972&r2=1541973&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java 
(original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java Thu Nov 
14 16:51:06 2013
@@ -23,10 +23,9 @@
 
 package opt;
 
-import java.util.HashSet ;
-import java.util.Iterator ;
-import java.util.List ;
-import java.util.Set ;
+import java.util.* ;
+
+import org.apache.jena.atlas.lib.CollectionUtils ;
 
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.graph.Triple ;
@@ -95,7 +94,7 @@ public class TransformFilterPlacement_Ne
         return op ;
     }
     
-    private static Op transform(ExprList exprs, Set<Var> varsScope, Op input)
+    /*private*/ static Op transform(ExprList exprs, Set<Var> varsScope, Op 
input)
     {
         Op opInitial = insertAnyFilter(exprs, varsScope, null) ;
         // OpAssign/OpExtend could be done if the assignment and exprs are 
independent.
@@ -272,31 +271,62 @@ public class TransformFilterPlacement_Ne
     
     private static Op transformFilterJoin(ExprList exprs, Set<Var> varScope, 
OpJoin opJoin)
     {
+        
         // Any filters that depend on no variables. 
         Op opInitial = insertAnyFilter(exprs, varScope, null) ;
+        if ( opInitial == opJoin )
+            opInitial = null ;
         
-        // Check: Can push down either side or both.  Both is better.
-        
-        // WROnG: code removes 
-        
-        // Be careful about exprs.
-        // accumulate scope.
+        Op left = opJoin.getLeft() ;
+        Op right = opJoin.getRight() ;
+        Collection<Var> leftVars = OpVars.mentionedVars(left) ;
+        Collection<Var> rightVars = OpVars.mentionedVars(right) ;
+        ExprList unpushed = new ExprList() ;
+        ExprList pushLeft = new ExprList() ;
+        ExprList pushRight = new ExprList() ;
+        
+        for ( Expr expr : exprs ) {
+            Set<Var> vars = expr.getVarsMentioned() ;
+            boolean pushed = false ;
+            
+            if ( leftVars.containsAll(vars) ) {
+                pushLeft.add(expr) ;
+                pushed = true ;
+            }
+            // If left only, make this "else if"
+            
+            if ( rightVars.containsAll(vars) ) {
+                // Push right
+                pushRight.add(expr) ;
+                pushed = true ;
+            } 
+            
+            if ( ! pushed )
+                unpushed.add(expr); 
+        }
         
-        ExprList exprs1 = new ExprList(exprs) ;
-        ExprList exprs2 = new ExprList(exprs) ; 
+        if ( pushLeft.isEmpty() && pushRight.isEmpty() )
+            return opJoin ;
         
-        Op opLeft = transform(exprs, varScope, opJoin.getLeft());
-        Op opRight = transform(exprs, varScope, opJoin.getRight());
+        Op opLeftNew = left ;
+        if ( ! pushLeft.isEmpty() )
+            opLeftNew = OpFilter.filter(pushLeft, opLeftNew) ;
+
+        Op opRightNew = right ;
+        if ( ! pushRight.isEmpty() )
+            opRightNew = OpFilter.filter(pushRight, opRightNew) ;
         
-        // WRONG
+        // HACK
         exprs.getList().clear() ;
-        //exprs.getList().addAll(exprs1.getList()) ;
+        exprs.getList().addAll(unpushed.getList()) ;
         
-        
-        Op op = OpJoin.create(opLeft, opRight) ;
-        return OpSequence.create(opInitial, op) ;
+        Op op = OpJoin.create(opLeftNew, opRightNew) ;
+        if ( opInitial != null )
+            op = OpSequence.create(opInitial, op) ;
+        return op ;
     }
 
+
     // Modularize.
     private static Op transformFilterConditional(ExprList exprs, Set<Var> 
varScope, OpConditional opConditional)
     {
@@ -308,25 +338,78 @@ public class TransformFilterPlacement_Ne
         Op op = new OpConditional(left, right);
         op = insertAnyFilter(exprs, varScope, op);
         return OpSequence.create(opInitial, op) ;
-     }
+    }
     
-    // Modularize.
+    // Much in common with Join.
     private static Op transformFilterLeftJoin(ExprList exprs, Set<Var> 
varScope, OpLeftJoin opLeftJoin)
     {
         // Any filters that depend on no variables. 
         Op opInitial = insertAnyFilter(exprs, varScope, null) ;
-        Op left = opLeftJoin.getLeft();
-        left = transform(exprs, varScope, left);
-        Op right = opLeftJoin.getRight();
-        Op op = OpLeftJoin.create(left, right, opLeftJoin.getExprs());
-        op = insertAnyFilter(exprs, varScope, op);
-        return OpSequence.create(opInitial, op) ;
-     }
+        
+        if ( opInitial == opLeftJoin )
+            opInitial = null ;
+        
+        // ?? Anything magic for the filters in the LeftJoin itself?
+        ExprList leftJoinExpr = opLeftJoin.getExprs() ;
+ 
+        Op left = opLeftJoin.getLeft() ;
+        Op right = opLeftJoin.getRight() ;
+        Collection<Var> leftVars = OpVars.mentionedVars(left) ;
+        Collection<Var> rightVars = OpVars.mentionedVars(right) ;
+        ExprList unpushed = new ExprList() ;
+        ExprList pushLeft = new ExprList() ;
+        ExprList pushRight = new ExprList() ;
+
+        for ( Expr expr : exprs ) {
+            Set<Var> vars = expr.getVarsMentioned() ;
+            boolean pushed = false ;
+
+            if ( leftVars.containsAll(vars) 
+                //&& disjoint(rightVars, vars)
+                ) {
+                // If not disjoint can push in, put also retain it.
+                //if ( rightVars.containsAny() 
+                //&& right does not mention.
+
+                pushLeft.add(expr) ;
+                pushed = true ;
+            }
+            // Right?????
+            
+            
+            if ( ! pushed )
+                unpushed.add(expr); 
+        }
+
+        if ( pushLeft.isEmpty() && pushRight.isEmpty() )
+            return opLeftJoin ;
+
+        Op opLeftNew = left ;
+        if ( ! pushLeft.isEmpty() )
+            opLeftNew = OpFilter.filter(pushLeft, opLeftNew) ;
+
+        Op opRightNew = right ;
+        if ( ! pushRight.isEmpty() )
+            opRightNew = OpFilter.filter(pushRight, opRightNew) ;
+
+        // HACK
+        exprs.getList().clear() ;
+        exprs.getList().addAll(unpushed.getList()) ;
+
+        Op op = OpJoin.create(opLeftNew, opRightNew) ;
+        if ( opInitial != null )
+            op = OpSequence.create(opInitial, op) ;
+        return op ;
+    }
+
+    private static <T> boolean disjoint(Collection<T> collection, 
Collection<T> possibleElts) {
+        return CollectionUtils.disjoint(collection, possibleElts) ;
+    }
 
     // ---- Utilities
     
     /** For any expression now in scope, wrap the op with a filter */
-    private static Op insertAnyFilter(ExprList exprs, Set<Var> 
patternVarsScope, Op op)
+    /*private*/ static Op insertAnyFilter(ExprList exprs, Set<Var> 
patternVarsScope, Op op)
     {
         for ( Iterator<Expr> iter = exprs.iterator() ; iter.hasNext() ; )
         {


Reply via email to