Author: andy
Date: Sun Nov 17 21:56:55 2013
New Revision: 1542842
URL: http://svn.apache.org/r1542842
Log:
Placement for union (first attempt)
Added:
jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java
Modified:
jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java
jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.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=1542842&r1=1542841&r2=1542842&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java Sun Nov 17 21:56:55 2013
@@ -26,91 +26,118 @@ import com.hp.hpl.jena.query.Query ;
import com.hp.hpl.jena.query.QueryFactory ;
import com.hp.hpl.jena.sparql.ARQConstants ;
import com.hp.hpl.jena.sparql.algebra.* ;
+import com.hp.hpl.jena.sparql.algebra.op.OpJoin ;
import com.hp.hpl.jena.sparql.algebra.op.OpLabel ;
import com.hp.hpl.jena.sparql.algebra.optimize.* ;
import com.hp.hpl.jena.sparql.algebra.optimize.Optimize.RewriterFactory ;
+import com.hp.hpl.jena.sparql.engine.main.JoinClassifier ;
import com.hp.hpl.jena.sparql.sse.SSE ;
import com.hp.hpl.jena.sparql.util.Context ;
public class OptMain {
+ // LeftJoin - Fixed vars only (LHS) OpVars. VarFinder.fixed(null)
+ // UNION - fixed : intersection
+ // Test - UNION
- public static void main(String... argv) throws Exception {
- {
+ // Also TransformDistinctToReduced (JENA-585)and
TransformOrderByDistincApplication
+
+ // JENA-383 : The query optimizer generates a suboptimal query plan in
case of nested optionals followed by a filter
+
+ // JENA-293 : Allow the filter placement optimziation to push FILTER
though BIND.
+ // Filter push throughs.
+ // JENA-384 : SubstituteFilterOptimize :: Interaction of optimization
(TransformFilterEquality) and initial binding
+
+ // Was Op.equals a good idea?
+ // Calculate vars for an expr once and cache : op.getVars.
+
+ // Checking:
+ // filter-equality-13 -- scope issue for leftjoin, conditional in a
sequence.
+ // Can't push in the filer to the sequence as may yield no binding ->
need fixed vars
+ // TestTranformFilters :
+ // optionalEqualitySubQuery_01 -- looks OK -- JENA-432
+ // optionalEquality_01 JENA-383 -- WRONG - Lost RHS of conditional
+ // optionalEqualityScope_01 -- WRONG -
+
+ // Double push in a sequence of conditional then BGP.
+ // JoinStartegy and FilterPlacement interaction.
+
+ public static void main(String... argv) {
+ testFailure() ;
+ }
+
+ public static void testFailure() {
String DIR = "/home/afs/Jena/jena-arq/testing/ARQ/OptFilterEquality" ;
-
- //arq.sparql.main("--engine=ref",
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
- //arq.sparql.main(
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+
+ arq.sparql.main(
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+ rewire() ;
+ arq.sparql.main(
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+ dewire() ;
+// arq.sparql.main(
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+// System.exit(0) ;
Query q = QueryFactory.read(DIR+"/filter-equality-13.rq") ;
Op op1 = Algebra.compile(q) ;
Op op2 = Algebra.optimize(op1) ;
System.out.println(op2);
rewire() ;
+ // Pushing filter over the (conditional) is wrong
+ // Need to look for MUST be fixed variables, which is not what OpVars.
mentioned vars is.
+ // nor is VarFinder.fixed (but is that wrong?)
+
+/*
+(filter (= ?x <http://example.org/x1>)
+ (sequence
+ (conditional
+ (table unit)
+ (bgp (triple ?x <http://example.org/qq> ?o2)))
+ (bgp (triple ?x <http://example.org/p> ?o1))))
+
+Rewrite2
+(sequence
+ (filter (= ?x <http://example.org/x1>)
+ (conditional
+ (table unit)
+ (bgp (triple ?x <http://example.org/qq> ?o2))))
+ (filter (= ?x <http://example.org/x1>)
+ (bgp (triple ?x <http://example.org/p> ?o1))))
+*/
op2 = Algebra.optimize(op1) ;
System.out.println(op2);
-
- //arq.sparql.main(
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
-
System.exit(0) ;
+ }
+
+ static void varFinder() {
+ if ( false )
+ {
+ Op op = SSE.parseOp("(union (bgp (?s ?p ?o1)) (bgp (?s ?p ?o2)))")
;
+ System.out.println(op) ;
+ // ** WRONG?? Exact meaning of "defined"?
+ System.out.println(VarFinder2.fixed(op)) ;
+ System.out.println(VarFinder2.optDefined(op)) ;
+ System.exit(0) ;
}
- // Project (and other blockers?)
-
- // Tests
- // coverage,
- // repeated application.
- // BGPs directly.
- // Complex/recurse tests
-
- // Transformations are applied "bottom up"
- // - should this be top down?
- // - what happens if hits a filter? Currently, it stops.
-
- // test combined with filter equality.
-
- // What about covered left but partial right?
- // Push left (join),)
- // Push left (left join)
- // Other cases
-
- // Check order of all optimziations - equality last.
-
- // 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
-
- // JENA-293 : Allow the filter placement optimziation to push FILTER
though BIND.
- // Filter push throughs.
- // JENA-384 : SubstituteFilterOptimize :: Interaction of optimization
(TransformFilterEquality) and initial binding
-
- // Filter placement
- // * Nesting
- // * Join
- // Need to say what was pushed.
-
- // Full optimization tests
-
- // Was Op.equals a good idea?
- // Calculate vars for an expr once and cache : op.getVars.
-
- // Push in inside a sequence?
-
-
-
- // Checking:
- // filter-equality-13 -- scope issue for leftjoin, conditional in a
sequence.
- // Can't push in the filer to the sequence as may yield no binding
-> need fixed vars
- // TestTranformFilters :
- // optionalEqualitySubQuery_01 -- looks OK -- JENA-432
- // optionalEquality_01 JENA-383 -- WRONG - Lost RHS of conditional
- // optionalEqualityScope_01 -- WRONG -
-
- // Double push in a sequence of conditional then BGP.
- // JonStartegy and FilterPlacement interaction.
-
+ {
+ // See alt VarFinder
+ String[] x = {
+ "(join (bgp (?s ?p ?o)) (union (bgp (?s ?p ?o)) (bgp (?s ?p
?o1))) )",
+ "(join (bgp (?s ?p ?o)) (union (bgp (?s ?p ?z)) (bgp (?s ?p1
?z))) )"
+ } ;
+
+ for (String s : x ) {
+ System.out.println("--------") ;
+ Op op = SSE.parseOp(s) ;
+ System.out.println(op) ;
+ System.out.println("fixed: "+VarFinder2.fixed(op)) ;
+ System.out.println("Opt: "+VarFinder2.optDefined(op)) ;
+ boolean nonLinear = JoinClassifier.isLinear((OpJoin)op) ;
+ System.out.println(nonLinear) ;
+ }
+ System.exit(0) ;
+ }
+ }
+
+ static void placement() {
if ( false ) {
//String input = "(filter (?x 123) (sequence (conditional (table
unit)
String input = StrUtils.strjoinNL
@@ -186,6 +213,10 @@ public class OptMain {
private static void rewire() {
Optimize.setFactory(new RewriterFactory2());
}
+
+ private static void dewire() {
+ Optimize.setFactory(Optimize.stdOptimizationFactory) ;
+ }
static class RewriterFactory2 implements RewriterFactory {
Modified: jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java?rev=1542842&r1=1542841&r2=1542842&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java
(original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java Sun
Nov 17 21:56:55 2013
@@ -121,6 +121,10 @@ public class TransformFilterPlacement_Re
placement = placeLeftJoin(exprs, (OpLeftJoin)input) ;
else if ( input instanceof OpFilter )
placement = placeFilter(exprs, (OpFilter)input) ;
+ else if ( input instanceof OpUnion )
+ placement = placeUnion(exprs, (OpUnion)input) ;
+
+
// These are operations where chnaging the order of operations
// does not in itself make a differencebut enables expressions
// to be pushed own down to where they might make a difference.
@@ -368,8 +372,19 @@ public class TransformFilterPlacement_Re
return result(op, nLeft.unplaced) ;
}
- private static <T> boolean disjoint(Collection<T> collection,
Collection<T> possibleElts) {
- return CollectionUtils.disjoint(collection, possibleElts) ;
+ private static Placement placeUnion(ExprList exprs, OpUnion input) {
+ // Unsubtle - push into both sides.
+ // Neater - for all unpushed put outside the union.
+ Op left = input.getLeft() ;
+ Placement pLeft = transform(exprs, left) ;
+ left = buildFilter(pLeft) ;
+
+ Op right = input.getRight() ;
+ Placement pRight = transform(exprs, right) ;
+ right = buildFilter(pRight) ;
+
+ Op op2 = OpUnion.create(left, right) ;
+ return result(op2, emptyList) ;
}
/** Try to optimize (filter (extend ...)) */
@@ -461,10 +476,16 @@ public class TransformFilterPlacement_Re
return op ;
}
+ private static <T> boolean disjoint(Collection<T> collection,
Collection<T> possibleElts) {
+ return CollectionUtils.disjoint(collection, possibleElts) ;
+ }
+
/** Place expressions around an Op */
private static Op buildFilter(Placement placement) {
if ( placement == null )
return null ;
+ if ( placement.unplaced.isEmpty() )
+ return placement.op ;
return buildFilter(placement.unplaced, placement.op) ;
}
Added: jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java?rev=1542842&view=auto
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java (added)
+++ jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java Sun Nov 17 21:56:55 2013
@@ -0,0 +1,276 @@
+/*
+ * 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 opt;
+
+import static com.hp.hpl.jena.sparql.util.VarUtils.addVar ;
+import static com.hp.hpl.jena.sparql.util.VarUtils.addVars ;
+
+import java.util.* ;
+import java.util.Map.Entry ;
+
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.algebra.OpVisitorBase ;
+import com.hp.hpl.jena.sparql.algebra.op.* ;
+import com.hp.hpl.jena.sparql.core.BasicPattern ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.core.VarExprList ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
+
+public class VarFinder2
+{
+ // See also VarUtils and OpVars.
+ // This class is specific to the needs of the main query engine and
scoping of variables
+
+ public static Set<Var> optDefined(Op op)
+ {
+ return VarUsageVisitor.apply(op).optDefines ;
+ }
+
+ public static Set<Var> fixed(Op op)
+ {
+ return VarUsageVisitor.apply(op).defines ;
+ }
+
+ public static Set<Var> filter(Op op)
+ {
+ return VarUsageVisitor.apply(op).filterMentions ;
+ }
+
+ VarUsageVisitor varUsageVisitor ;
+
+ public VarFinder2(Op op)
+ { varUsageVisitor = VarUsageVisitor.apply(op) ; }
+
+ public Set<Var> getOpt() { return varUsageVisitor.optDefines ; }
+ public Set<Var> getFilter() { return varUsageVisitor.filterMentions ; }
+ public Set<Var> getAssign() { return varUsageVisitor.assignMentions ; }
+ public Set<Var> getFixed() { return varUsageVisitor.defines ; }
+
+ private static class VarUsageVisitor extends OpVisitorBase //implements
OpVisitor
+ {
+ static VarUsageVisitor apply(Op op)
+ {
+ VarUsageVisitor v = new VarUsageVisitor() ;
+ op.visit(v) ;
+ return v ;
+ }
+
+ Set<Var> defines = null ;
+ Set<Var> optDefines = null ;
+ Set<Var> filterMentions = null ;
+ Set<Var> assignMentions = null ;
+
+ VarUsageVisitor()
+ {
+ defines = new HashSet<Var>() ;
+ optDefines = new HashSet<Var>() ;
+ filterMentions = new HashSet<Var>() ;
+ assignMentions = new HashSet<Var>() ;
+ }
+
+ VarUsageVisitor(Set<Var> _defines, Set<Var> _optDefines, Set<Var>
_filterMentions, Set<Var> _assignMentions)
+ {
+ defines = _defines ;
+ optDefines = _optDefines ;
+ filterMentions = _filterMentions ;
+ assignMentions = _assignMentions ;
+ }
+
+ @Override
+ public void visit(OpQuadPattern quadPattern)
+ {
+ addVar(defines, quadPattern.getGraphNode()) ;
+ BasicPattern triples = quadPattern.getBasicPattern() ;
+ addVars(defines, triples) ;
+ }
+
+ @Override
+ public void visit(OpBGP opBGP)
+ {
+ BasicPattern triples = opBGP.getPattern() ;
+ addVars(defines, triples) ;
+ }
+
+ @Override
+ public void visit(OpExt opExt)
+ {
+ opExt.effectiveOp().visit(this) ;
+ }
+
+ @Override
+ public void visit(OpJoin opJoin)
+ {
+ joinAcc(opJoin.getLeft()) ;
+ joinAcc(opJoin.getRight()) ;
+ }
+
+ @Override
+ public void visit(OpSequence opSequence)
+ {
+ for ( Op op : opSequence.getElements() )
+ joinAcc(op) ;
+ }
+
+ private void joinAcc(Op op)
+ {
+ VarUsageVisitor usage = VarUsageVisitor.apply(op) ;
+
+ defines.addAll(usage.defines) ;
+ optDefines.addAll(usage.optDefines) ;
+ filterMentions.addAll(usage.filterMentions) ;
+ }
+
+ @Override
+ public void visit(OpLeftJoin opLeftJoin)
+ {
+ leftJoin(opLeftJoin.getLeft(), opLeftJoin.getRight(),
opLeftJoin.getExprs()) ;
+ }
+
+ @Override
+ public void visit(OpConditional opLeftJoin)
+ {
+ leftJoin(opLeftJoin.getLeft(), opLeftJoin.getRight(), null) ;
+ }
+
+ private void leftJoin(Op left, Op right, ExprList exprs)
+ {
+ VarUsageVisitor leftUsage = VarUsageVisitor.apply(left) ;
+ VarUsageVisitor rightUsage = VarUsageVisitor.apply(right) ;
+
+ defines.addAll(leftUsage.defines) ;
+ optDefines.addAll(leftUsage.optDefines) ;
+ filterMentions.addAll(leftUsage.filterMentions) ;
+ assignMentions.addAll(leftUsage.assignMentions) ;
+
+ optDefines.addAll(rightUsage.defines) ; // Asymmetric.
+ optDefines.addAll(rightUsage.optDefines) ;
+ filterMentions.addAll(rightUsage.filterMentions) ;
+ assignMentions.addAll(rightUsage.assignMentions) ;
+
+ // Remove any definites that are in the optionals
+ // as, overall, they are definites
+ optDefines.removeAll(leftUsage.defines) ;
+
+ // And the associated filter.
+ if ( exprs != null )
+ exprs.varsMentioned(filterMentions);
+ }
+
+ @Override
+ public void visit(OpUnion opUnion)
+ {
+ VarUsageVisitor leftUsage =
VarUsageVisitor.apply(opUnion.getLeft()) ;
+ VarUsageVisitor rightUsage =
VarUsageVisitor.apply(opUnion.getRight()) ;
+
+ // defines = intersection(left.define, right.define)
+ // Optional = optional either side and not in both sides.
+
+// Set<Var> def = SetUtils.intersection(leftUsage.defines,
rightUsage.defines) ;
+// Set<Var> opt1 = SetUtils.difference(leftUsage.defines, def) ;
+// Set<Var> opt2 = SetUtils.difference(rightUsage.defines, def) ;
+//
+//
+// defines.addAll(def) ;
+// optDefines.addAll(opt1) ;
+// optDefines.addAll(opt2) ;
+// optDefines.addAll(leftUsage.optDefines) ;
+// optDefines.addAll(rightUsage.optDefines) ;
+//
+// filterMentions.addAll(leftUsage.filterMentions) ;
+// filterMentions.addAll(rightUsage.filterMentions) ;
+// assignMentions.addAll(rightUsage.assignMentions) ;
+// assignMentions.addAll(leftUsage.assignMentions) ;
+
+ defines.addAll(leftUsage.defines) ;
+ optDefines.addAll(leftUsage.optDefines) ;
+ filterMentions.addAll(leftUsage.filterMentions) ;
+ assignMentions.addAll(leftUsage.assignMentions) ;
+
+ defines.addAll(rightUsage.defines) ;
+ optDefines.addAll(rightUsage.optDefines) ;
+ filterMentions.addAll(rightUsage.filterMentions) ;
+ assignMentions.addAll(rightUsage.assignMentions) ;
+ }
+
+ @Override
+ public void visit(OpGraph opGraph)
+ {
+ addVar(defines, opGraph.getNode()) ;
+ opGraph.getSubOp().visit(this) ;
+ }
+
+ // @Override
+ @Override
+ public void visit(OpFilter opFilter)
+ {
+ opFilter.getExprs().varsMentioned(filterMentions);
+ opFilter.getSubOp().visit(this) ;
+ }
+
+ @Override
+ public void visit(OpAssign opAssign)
+ {
+ opAssign.getSubOp().visit(this) ;
+ processVarExprList(opAssign.getVarExprList()) ;
+ }
+
+ @Override
+ public void visit(OpExtend opExtend)
+ {
+ opExtend.getSubOp().visit(this) ;
+ processVarExprList(opExtend.getVarExprList()) ;
+ }
+
+ private void processVarExprList(VarExprList varExprList)
+ {
+ Map<Var, Expr> map = varExprList.getExprs() ;
+ for ( Entry<Var, Expr> e : map.entrySet() )
+ {
+ defines.add(e.getKey()) ;
+ e.getValue().varsMentioned(assignMentions);
+ }
+ }
+
+ @Override
+ public void visit(OpProject opProject)
+ {
+ List<Var> vars = opProject.getVars() ;
+ VarUsageVisitor subUsage =
VarUsageVisitor.apply(opProject.getSubOp()) ;
+
+ subUsage.defines.retainAll(vars) ;
+ subUsage.optDefines.retainAll(vars) ;
+ subUsage.optDefines.retainAll(vars) ;
+ defines.addAll(subUsage.defines) ;
+ optDefines.addAll(subUsage.optDefines) ;
+ filterMentions.addAll(subUsage.filterMentions) ;
+ assignMentions.addAll(subUsage.assignMentions) ;
+ }
+
+ @Override
+ public void visit(OpTable opTable)
+ {
+ defines.addAll(opTable.getTable().getVars()) ;
+ }
+
+ @Override
+ public void visit(OpNull opNull)
+ { }
+ }
+}