Author: andy
Date: Mon Nov 11 22:37:03 2013
New Revision: 1540871
URL: http://svn.apache.org/r1540871
Log:
Tidy/reorganize scratch area.
Added:
jena/Scratch/AFS/Dev/src-dev/opt/
jena/Scratch/AFS/Dev/src-dev/opt/Jena383_BadPlanOptionals.java
- copied, changed from r1523030,
jena/Scratch/AFS/Dev/src-dev/dev/Jena383_BadPlanOptionals.java
jena/Scratch/AFS/Dev/src-dev/opt/Jena384_SubstitueFilterOptimize.java
- copied, changed from r1523030,
jena/Scratch/AFS/Dev/src-dev/dev/Jena384_SubstitueFilterOptimize.java
jena/Scratch/AFS/Dev/src-dev/opt/JenaNNN_FilterEquality.java
- copied, changed from r1523030,
jena/Scratch/AFS/Dev/src-dev/dev/JenaNNN_FilterEquality.java
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/TransformFilterEquality2.java
- copied, changed from r1523030,
jena/Scratch/AFS/Dev/src-dev/dev/TransformFilterEquality2.java
jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java
Removed:
jena/Scratch/AFS/Dev/src-dev/dev/Jena383_BadPlanOptionals.java
jena/Scratch/AFS/Dev/src-dev/dev/Jena384_SubstitueFilterOptimize.java
jena/Scratch/AFS/Dev/src-dev/dev/JenaNNN_FilterEquality.java
jena/Scratch/AFS/Dev/src-dev/dev/TransformFilterEquality2.java
jena/Scratch/AFS/Dev/src-dev/reports/
jena/Scratch/AFS/Dev/src/main/java/algebra2/
Modified:
jena/Scratch/AFS/Dev/src-dev/dev/TestModelCreation.java
Modified: jena/Scratch/AFS/Dev/src-dev/dev/TestModelCreation.java
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/dev/TestModelCreation.java?rev=1540871&r1=1540870&r2=1540871&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/dev/TestModelCreation.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/dev/TestModelCreation.java Mon Nov 11 22:37:03
2013
@@ -18,9 +18,8 @@
package dev;
-import java.util.HashMap ;
-import java.util.Map ;
-
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
import com.hp.hpl.jena.sparql.util.Timer ;
public class TestModelCreation
@@ -34,8 +33,8 @@ public class TestModelCreation
t.startTimer() ;
for ( int i = 0 ; i < N; i++ )
{
- //Model m = ModelFactory.createDefaultModel() ;
- Map<Object, Object> m = new HashMap<Object, Object>() ;
+ Model m = ModelFactory.createDefaultModel() ;
+ //Map<Object, Object> m = new HashMap<Object, Object>() ;
objects[i%100] = m ;
}
long millis = t.endTimer() ;
Copied: jena/Scratch/AFS/Dev/src-dev/opt/Jena383_BadPlanOptionals.java (from
r1523030, jena/Scratch/AFS/Dev/src-dev/dev/Jena383_BadPlanOptionals.java)
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/Jena383_BadPlanOptionals.java?p2=jena/Scratch/AFS/Dev/src-dev/opt/Jena383_BadPlanOptionals.java&p1=jena/Scratch/AFS/Dev/src-dev/dev/Jena383_BadPlanOptionals.java&r1=1523030&r2=1540871&rev=1540871&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/dev/Jena383_BadPlanOptionals.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/Jena383_BadPlanOptionals.java Mon Nov 11
22:37:03 2013
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-package dev;
+package opt;
import org.apache.jena.atlas.lib.StrUtils ;
Copied: jena/Scratch/AFS/Dev/src-dev/opt/Jena384_SubstitueFilterOptimize.java
(from r1523030,
jena/Scratch/AFS/Dev/src-dev/dev/Jena384_SubstitueFilterOptimize.java)
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/Jena384_SubstitueFilterOptimize.java?p2=jena/Scratch/AFS/Dev/src-dev/opt/Jena384_SubstitueFilterOptimize.java&p1=jena/Scratch/AFS/Dev/src-dev/dev/Jena384_SubstitueFilterOptimize.java&r1=1523030&r2=1540871&rev=1540871&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/dev/Jena384_SubstitueFilterOptimize.java
(original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/Jena384_SubstitueFilterOptimize.java Mon
Nov 11 22:37:03 2013
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-package dev;
+package opt;
import com.hp.hpl.jena.query.* ;
import com.hp.hpl.jena.rdf.model.ModelFactory ;
Copied: jena/Scratch/AFS/Dev/src-dev/opt/JenaNNN_FilterEquality.java (from
r1523030, jena/Scratch/AFS/Dev/src-dev/dev/JenaNNN_FilterEquality.java)
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/JenaNNN_FilterEquality.java?p2=jena/Scratch/AFS/Dev/src-dev/opt/JenaNNN_FilterEquality.java&p1=jena/Scratch/AFS/Dev/src-dev/dev/JenaNNN_FilterEquality.java&r1=1523030&r2=1540871&rev=1540871&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/dev/JenaNNN_FilterEquality.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/JenaNNN_FilterEquality.java Mon Nov 11
22:37:03 2013
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-package dev;
+package opt;
import org.apache.jena.atlas.lib.StrUtils ;
import org.junit.Assert ;
@@ -36,12 +36,7 @@ import com.hp.hpl.jena.sparql.sse.SSE ;
public class JenaNNN_FilterEquality
{
- // remove assignment from projection?
- // No need! It's going to be a no-op!
-
- // [DONE] JENA-432 : Filter optimization messes up when a nested select is
present in the same block
// JENA-383 : The query optimizer generates a suboptimal query plan in
case of nested optionals followed by a filter
- // [DONE] JENA-294 : TransformFilterEquality does not handle starting
OPTIONAL well
// Unrelated
// JENA-293 : Allow the filter placement optimziation to push FILTER
though BIND.
Added: 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=1540871&view=auto
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java (added)
+++ jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java Mon Nov 11 22:37:03 2013
@@ -0,0 +1,74 @@
+/**
+ * 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 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.sse.SSE ;
+
+public class OptMain {
+
+ public static void main(String... argv) throws Exception {
+ // Cominations 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 : SubstitueFilterOptimize :: Interaction of optimization
(TransformFilterEquality) and initial binding
+
+ // Filter placement
+ // * Nesting
+ // * Join
+ // Need to say what was pushed.
+
+
+ if ( true ) {
+ 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) ;
+ Op op2 = Transformer.transform(t_placement, op1) ;
+ System.out.print(op2) ;
+ System.out.println("------------------------");
+ //System.exit(0) ;
+ }
+
+ if ( true ) {
+ String x = "SELECT * { ?s ?p ?o . FILTER (13=14) FILTER(?o1 > 12)
FILTER(?o < 56) OPTIONAL { ?s ?p1 ?o1 } }" ;
+ Query query = QueryFactory.create(x) ;
+ Op op1 = Algebra.compile(query) ;
+ System.out.println(op1) ;
+
+ // && 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) ;
+ }
+ }
+}
Added: 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=1540871&view=auto
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java (added)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TestFilterPlacement.java Mon Nov 11
22:37:03 2013
@@ -0,0 +1,137 @@
+/**
+ * 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 org.junit.Assert ;
+import org.junit.Test ;
+
+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.sse.SSE ;
+
+public class TestFilterPlacement {
+ @Test
+ public void place_filter_bgp_01() {
+ test("(filter (= ?x 1) (bgp ( ?s ?p ?x)))", "(filter (= ?x 1) (bgp (
?s ?p ?x)))") ;
+ }
+
+ @Test
+ public void place_filter_bgp_02() {
+ test("(filter (= ?x 1) (bgp (?s ?p ?x) (?s1 ?p1 ?x1) ))",
+ "(sequence (filter (= ?x 1) (bgp ( ?s ?p ?x))) (bgp (?s1 ?p1
?x1)))") ;
+ }
+
+ @Test
+ public void place_filter_bgp_03() {
+ test("(filter (= ?x 1) (bgp (?s ?p ?x) (?s1 ?p1 ?x) ))",
+ "(sequence (filter (= ?x 1) (bgp ( ?s ?p ?x))) (bgp (?s1 ?p1
?x)))") ;
+ }
+
+ @Test
+ public void place_filter_bgp_04() {
+ test("(filter (= ?XX 1) (bgp (?s ?p ?x) (?s1 ?p1 ?XX) ))", "(filter (=
?XX 1) (bgp (?s ?p ?x) (?s1 ?p1 ?XX) ))") ;
+ }
+
+ @Test
+ public void place_filter_no_match_01() {
+ // Unbound
+ test("(filter (= ?x ?unbound) (bgp (?s ?p ?x)))", null) ;
+ }
+
+ @Test
+ public void place_filter_no_match_02() {
+ test("(filter (= ?x ?unbound) (bgp (?s ?p ?x)))", null) ;
+ }
+
+ @Test
+ public void place_filter_no_match_03() {
+ test("(filter (= ?x ?unbound) (bgp (?s ?p ?x) (?s1 ?p1 ?XX)))", null) ;
+ }
+
+ // Sequence
+
+ @Test
+ public void place_filter_sequence_01() {
+ test("(filter (= ?x 123) (sequence (bgp (?s ?p ?x)) (bgp (?s ?p ?z))
))",
+ "(sequence (filter (= ?x 123) (bgp (?s ?p ?x))) (bgp (?s ?p ?z))
)") ;
+
+ }
+
+ @Test
+ public void place_filter_sequence_02() {
+ // Given the sequence flows left into right, only need to filter in the
+ // LHS. The RHS can't introduce ?x because it woudl not be a legal
sequence
+ // if, for example, it had a BIND in it.
+ test("(filter (= ?x 123) (sequence (bgp (?s ?p ?x)) (bgp (?s ?p ?x))
))",
+ "(sequence (filter (= ?x 123) (bgp (?s ?p ?x))) (bgp (?s ?p ?x))
)") ;
+ }
+
+ // Join : one sided push.
+ @Test
+ public void place_filter_join_01() {
+ test("(filter (= ?x 123) (join (bgp (?s ?p ?x)) (bgp (?s ?p ?z)) ))",
+ "(join (filter (= ?x 123) (bgp (?s ?p ?x))) (bgp (?s ?p ?z)) )") ;
+ }
+
+ // Join
+ @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_conditional_01() {
+ // conditional
+ test("(filter (= ?x 123) (conditional (bgp (?s ?p ?x)) (bgp (?s ?p
?z)) ))",
+ "(conditional (filter (= ?x 123) (bgp (?s ?p ?x))) (bgp (?s ?p
?z)) )") ;
+ }
+
+ @Test
+ public void place_filter_conditional_02() {
+ // conditional
+ test("(filter (= ?z 123) (conditional (bgp (?s ?p ?x)) (bgp (?s ?p
?z)) ))",
+ "(filter (= ?z 123) (conditional (bgp (?s ?p ?x)) (bgp (?s ?p
?z)) ))") ;
+ }
+
+ @Test
+ public void place_filter_conditional_03() {
+ // conditional
+ test("(filter (= ?x 123) (conditional (bgp (?s ?p ?x)) (bgp (?s ?p
?x)) ))",
+ "(conditional (filter (= ?x 123) (bgp (?s ?p ?x))) (bgp (?s ?p
?x)) )") ;
+ }
+
+ // LeftJoin
+
+ public static void test(String input, String output) {
+ Transform t_placement = new TransformFilterPlacement_New() ;
+ Op op1 = SSE.parseOp(input) ;
+ Op op2 = Transformer.transform(t_placement, op1) ;
+ if ( output == null ) {
+ // No transformation.
+ Assert.assertEquals(op1, op2) ;
+ return ;
+ }
+
+ Op op3 = SSE.parseOp(output) ;
+ Assert.assertEquals(op3, op2) ;
+ }
+
+}
Copied: jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterEquality2.java (from
r1523030, jena/Scratch/AFS/Dev/src-dev/dev/TransformFilterEquality2.java)
URL:
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterEquality2.java?p2=jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterEquality2.java&p1=jena/Scratch/AFS/Dev/src-dev/dev/TransformFilterEquality2.java&r1=1523030&r2=1540871&rev=1540871&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/dev/TransformFilterEquality2.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterEquality2.java Mon Nov 11
22:37:03 2013
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-package dev;
+package opt;
import static org.apache.jena.atlas.lib.CollectionUtils.disjoint ;
Added: 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=1540871&view=auto
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java (added)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_New.java Mon Nov
11 22:37:03 2013
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+
+/* Contains code submitted in email to [email protected]
+ * so software grant and relicensed under the Apache Software License.
+ * transformFilterConditional
+ */
+
+package opt;
+
+import java.util.HashSet ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.Set ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.algebra.OpVars ;
+import com.hp.hpl.jena.sparql.algebra.TransformCopy ;
+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.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
+import com.hp.hpl.jena.sparql.util.VarUtils ;
+
+/** Rewrite an algebra expression to put filters as close to their bound
variables in a BGP.
+ * Works on (filter (BGP ...) )
+ * Could be made to work on a wider class of forms.
+ */
+
+public class TransformFilterPlacement_New extends TransformCopy
+{
+ static boolean doFilterPlacement = true ;
+
+ public static Op transform(ExprList exprs, BasicPattern bgp)
+ {
+ if ( ! doFilterPlacement )
+ return OpFilter.filter(exprs, new OpBGP(bgp)) ;
+ // Mutated
+ ExprList exprs2 = new ExprList(exprs) ;
+ Op op = transformFilterBGP(exprs2, new HashSet<Var>(), bgp) ;
+ // Remaining filters? e.g. ones mentioning var s not used anywhere.
+ op = buildFilter(exprs2, op) ;
+ return op ;
+ }
+
+ public static Op transform(ExprList exprs, Node graphNode, BasicPattern
bgp)
+ {
+ if ( ! doFilterPlacement )
+ return OpFilter.filter(exprs, new OpQuadPattern(graphNode, bgp)) ;
+ // Mutated
+ ExprList exprs2 = new ExprList(exprs) ;
+ Op op = transformFilterQuadPattern(exprs2, new HashSet<Var>(),
graphNode, bgp);
+ op = buildFilter(exprs2, op) ;
+ return op ;
+ }
+
+ public TransformFilterPlacement_New()
+ { }
+
+ @Override
+ public Op transform(OpFilter opFilter, Op x)
+ {
+ if ( ! doFilterPlacement )
+ return super.transform(opFilter, x) ;
+
+ // Destructive use of exprs - copy it.
+ ExprList exprs = new ExprList(opFilter.getExprs()) ;
+ Set<Var> varsScope = new HashSet<Var>() ;
+
+ Op op = transform(exprs, varsScope, x) ;
+ if ( op == x )
+ // Didn't do anything.
+ return super.transform(opFilter, x) ;
+
+ // Remaining exprs
+ op = buildFilter(exprs, op) ;
+ return op ;
+ }
+
+ 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.
+ // Dispatch by visitor??
+ Op opOutput = null ;
+
+ if ( input instanceof OpBGP )
+ opOutput = transformFilterBGP(exprs, varsScope, (OpBGP)input) ;
+ else if ( input instanceof OpSequence )
+ opOutput = transformFilterSequence(exprs, varsScope,
(OpSequence)input) ;
+ else if ( input instanceof OpQuadPattern )
+ opOutput = transformFilterQuadPattern(exprs, varsScope,
(OpQuadPattern)input) ;
+ else if ( input instanceof OpSequence )
+ opOutput = transformFilterSequence(exprs, varsScope,
(OpSequence)input) ;
+ else if ( input instanceof OpJoin )
+ opOutput = transformFilterJoin(exprs, varsScope, (OpJoin)input) ;
+ else if ( input instanceof OpConditional )
+ opOutput = transformFilterConditional(exprs, varsScope,
(OpConditional)input) ;
+ else if ( input instanceof OpLeftJoin )
+ opOutput = transformFilterLeftJoin(exprs, varsScope,
(OpLeftJoin)input) ;
+ else {
+ OpVars.visibleVars(input, varsScope) ;
+ return input ;
+ }
+
+ if ( opInitial != null )
+ opOutput = OpSequence.create(opInitial, opOutput) ;
+ return opOutput ;
+ }
+
+ // == The transformFilter* modify the exprs and patternVarsScope arguments
+
+ private static Op transformFilterBGP(ExprList exprs, Set<Var>
patternVarsScope, OpBGP x)
+ {
+ return transformFilterBGP(exprs, patternVarsScope, x.getPattern()) ;
+ }
+
+ // Mutates exprs
+ private static Op transformFilterBGP(ExprList exprs, Set<Var>
patternVarsScope, BasicPattern pattern)
+ {
+ // Any filters that depend on no variables.
+ Op op = insertAnyFilter(exprs, patternVarsScope, null) ;
+
+ for ( Triple triple : pattern )
+ {
+ OpBGP opBGP = getBGP(op) ;
+ if ( opBGP == null )
+ {
+ // Last thing was not a BGP (so it likely to be a filter)
+ // Need to pass the results from that into the next triple.
+ // Which is a join and sequence is a special case of join
+ // which always evaluates by passing results of the early
+ // part into the next element of the sequence.
+
+ opBGP = new OpBGP() ;
+ op = OpSequence.create(op, opBGP) ;
+ }
+
+ opBGP.getPattern().add(triple) ;
+ // Update variables in scope.
+ VarUtils.addVarsFromTriple(patternVarsScope, triple) ;
+
+ // Attempt to place any filters
+ op = insertAnyFilter(exprs, patternVarsScope, op) ;
+ }
+ // Leave any remaining filter expressions - don't wrap up any as
something else may take them.
+ return op ;
+ }
+
+ /** Find the current OpBGP, or return null. */
+ private static OpBGP getBGP(Op op)
+ {
+ if ( op instanceof OpBGP )
+ return (OpBGP)op ;
+
+ if ( op instanceof OpSequence )
+ {
+ // Is last in OpSequence an BGP?
+ OpSequence opSeq = (OpSequence)op ;
+ List<Op> x = opSeq.getElements() ;
+ if ( x.size() > 0 )
+ {
+ Op opTop = x.get(x.size()-1) ;
+ if ( opTop instanceof OpBGP )
+ return (OpBGP)opTop ;
+ // Drop through
+ }
+ }
+ // Can't find.
+ return null ;
+ }
+
+ private static Op transformFilterQuadPattern(ExprList exprs, Set<Var>
patternVarsScope, OpQuadPattern pattern)
+ {
+ return transformFilterQuadPattern(exprs, patternVarsScope,
pattern.getGraphNode(), pattern.getBasicPattern()) ;
+ }
+
+ private static Op transformFilterQuadPattern(ExprList exprs, Set<Var>
patternVarsScope, Node graphNode, BasicPattern pattern)
+ {
+ // Any filters that depend on no variables.
+ Op op = insertAnyFilter(exprs, patternVarsScope, null) ;
+ if ( Var.isVar(graphNode) )
+ {
+ // Add in the graph node of the quad block.
+ // It's picked up after the first triple is processed.
+ VarUtils.addVar(patternVarsScope, Var.alloc(graphNode)) ;
+ }
+
+ for ( Triple triple : pattern )
+ {
+ OpQuadPattern opQuad = getQuads(op) ;
+ if ( opQuad == null )
+ {
+ opQuad = new OpQuadPattern(graphNode, new BasicPattern()) ;
+ op = OpSequence.create(op, opQuad) ;
+ }
+
+ opQuad.getBasicPattern().add(triple) ;
+ // Update variables in scope.
+ VarUtils.addVarsFromTriple(patternVarsScope, triple) ;
+
+ // Attempt to place any filters
+ op = insertAnyFilter(exprs, patternVarsScope, op) ;
+ }
+
+
+ return op ;
+ }
+
+ /** Find the current OpQuadPattern, or return null. */
+ private static OpQuadPattern getQuads(Op op)
+ {
+ if ( op instanceof OpQuadPattern )
+ return (OpQuadPattern)op ;
+
+ if ( op instanceof OpSequence )
+ {
+ // Is last in OpSequence an BGP?
+ OpSequence opSeq = (OpSequence)op ;
+ List<Op> x = opSeq.getElements() ;
+ if ( x.size() > 0 )
+ {
+ Op opTop = x.get(x.size()-1) ;
+ if ( opTop instanceof OpQuadPattern )
+ return (OpQuadPattern)opTop ;
+ // Drop through
+ }
+ }
+ // Can't find.
+ return null ;
+ }
+
+ private static Op transformFilterSequence(ExprList exprs, Set<Var>
varScope, OpSequence opSequence)
+ {
+ List<Op> ops = opSequence.getElements() ;
+
+ // Any filters that depend on no variables.
+ Op op = insertAnyFilter(exprs, varScope, null) ;
+
+ for ( Iterator<Op> iter = ops.iterator() ; iter.hasNext() ; )
+ {
+ Op seqElt = iter.next() ;
+ // Process the sequence element. This may insert filters
(sequence or BGP)
+ // Only need inserting once because sequence implies legal for a
substituion join
+ // so later ops can't introduce a variable with a value outside
the filter.
+ seqElt = transform(exprs, varScope, seqElt) ;
+ // Merge into sequence.
+ op = OpSequence.create(op, seqElt) ;
+ // Place any filters now ready.
+ op = insertAnyFilter(exprs, varScope, op) ;
+ }
+ return op ;
+ }
+
+ private static Op transformFilterJoin(ExprList exprs, Set<Var> varScope,
OpJoin opJoin)
+ {
+ // Any filters that depend on no variables.
+ Op opInitial = insertAnyFilter(exprs, varScope, null) ;
+
+ // Check: Can push down either side or both. Both is better.
+
+ // WROnG: code removes
+
+ // Be careful about exprs.
+ // accumulate scope.
+
+ ExprList exprs1 = new ExprList(exprs) ;
+ ExprList exprs2 = new ExprList(exprs) ;
+
+ Op opLeft = transform(exprs, varScope, opJoin.getLeft());
+ Op opRight = transform(exprs, varScope, opJoin.getRight());
+
+ // WRONG
+ exprs.getList().clear() ;
+ //exprs.getList().addAll(exprs1.getList()) ;
+
+
+ Op op = OpJoin.create(opLeft, opRight) ;
+ return OpSequence.create(opInitial, op) ;
+ }
+
+ // Modularize.
+ private static Op transformFilterConditional(ExprList exprs, Set<Var>
varScope, OpConditional opConditional)
+ {
+ // Any filters that depend on no variables.
+ Op opInitial = insertAnyFilter(exprs, varScope, null) ;
+ Op left = opConditional.getLeft();
+ left = transform(exprs, varScope, left);
+ Op right = opConditional.getRight();
+ Op op = new OpConditional(left, right);
+ op = insertAnyFilter(exprs, varScope, op);
+ return OpSequence.create(opInitial, op) ;
+ }
+
+ // Modularize.
+ 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) ;
+ }
+
+ // ---- Utilities
+
+ /** For any expression now in scope, wrap the op with a filter */
+ private static Op insertAnyFilter(ExprList exprs, Set<Var>
patternVarsScope, Op op)
+ {
+ for ( Iterator<Expr> iter = exprs.iterator() ; iter.hasNext() ; )
+ {
+ Expr expr = iter.next() ;
+ // Cache
+ Set<Var> exprVars = expr.getVarsMentioned() ;
+ if ( patternVarsScope.containsAll(exprVars) )
+ {
+ if ( op == null )
+ op = OpTable.unit() ;
+ op = OpFilter.filter(expr, op) ;
+ iter.remove() ;
+ // Record expr.
+ }
+ }
+ return op ;
+ }
+
+ /** Place expressions around an Op */
+ private static Op buildFilter(ExprList exprs, Op op)
+ {
+ if ( exprs.isEmpty() )
+ return op ;
+
+ for ( Iterator<Expr> iter = exprs.iterator() ; iter.hasNext() ; )
+ {
+ Expr expr = iter.next() ;
+ if ( op == null )
+ op = OpTable.unit() ;
+ op = OpFilter.filter(expr, op) ;
+ iter.remove();
+ }
+ return op ;
+ }
+}