You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2015/09/22 14:12:57 UTC
[2/2] jena git commit: JENA-1021: Don't execute patterns with a MINUS
in linear fashion.
JENA-1021: Don't execute patterns with a MINUS in linear fashion.
ARQ was not doing this anyway for MINUS at the top level of a pattern.
This fixes the problem for MINUS at any depth.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/6fd8962a
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/6fd8962a
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/6fd8962a
Branch: refs/heads/master
Commit: 6fd8962a51f87dbf908924f30e207a89a444d127
Parents: e1be3aa
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Sep 22 13:10:27 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Sep 22 13:10:27 2015 +0100
----------------------------------------------------------------------
.../jena/sparql/engine/main/JoinClassifier.java | 28 +++++++++++++++++---
.../jena/sparql/algebra/TestClassify.java | 5 ++++
2 files changed, 30 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/6fd8962a/jena-arq/src/main/java/org/apache/jena/sparql/engine/main/JoinClassifier.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/main/JoinClassifier.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/main/JoinClassifier.java
index f81eeaf..d74d8c9 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/main/JoinClassifier.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/main/JoinClassifier.java
@@ -22,6 +22,9 @@ import java.util.Set ;
import org.apache.jena.atlas.lib.SetUtils ;
import org.apache.jena.sparql.algebra.Op ;
+import org.apache.jena.sparql.algebra.OpVisitor ;
+import org.apache.jena.sparql.algebra.OpVisitorBase ;
+import org.apache.jena.sparql.algebra.OpWalker ;
import org.apache.jena.sparql.algebra.op.* ;
import org.apache.jena.sparql.core.Var ;
@@ -45,11 +48,15 @@ public class JoinClassifier
Op left = effectiveOp(_left) ;
Op right = effectiveOp(_right) ;
+ if ( ! isSafeForLinear(left) || ! isSafeForLinear(right) )
+ return false ;
+
+ // Modifiers.
if ( right instanceof OpExtend ) return false ;
if ( right instanceof OpAssign ) return false ;
if ( right instanceof OpGroup ) return false ;
- if ( right instanceof OpDiff ) return false ;
- if ( right instanceof OpMinus ) return false ;
+// if ( right instanceof OpDiff ) return false ;
+// if ( right instanceof OpMinus ) return false ;
if ( right instanceof OpSlice ) return false ;
if ( right instanceof OpTopN ) return false ;
@@ -59,6 +66,20 @@ public class JoinClassifier
return check(left, right) ;
}
+ // -- pre check for ops we can't handle in a linear fashion.
+ // These are the negation patterns (minus and diff)
+ // FILTER NOT EXISTS is safe - it's defined by iteration like the linear execution algorithm.
+ private static class UnsafeLineraOpException extends RuntimeException {}
+ private static OpVisitor checkForUnsafeVisitor = new OpVisitorBase() {
+ @Override public void visit(OpMinus opMinus) { throw new UnsafeLineraOpException(); }
+ @Override public void visit(OpDiff opDiff) { throw new UnsafeLineraOpException(); }
+ };
+ private static boolean isSafeForLinear(Op op) {
+ try { OpWalker.walk(op, checkForUnsafeVisitor); return true; }
+ catch (UnsafeLineraOpException e) { return false; }
+ }
+ // --
+
// Check left can stream into right
static private boolean check(Op leftOp, Op rightOp) {
if ( print ) {
@@ -149,11 +170,12 @@ public class JoinClassifier
// Case 3 : an assign in the RHS uses a variable not introduced
// Scoping means we must hide the LHS value from the RHS
- // TODO Think this may be slightly relaxed, using variables in an
+ // Think this may be slightly relaxed, using variables in an
// assign on the RHS is in principal fine if they're also available on
// the RHS
// vRightAssign.removeAll(vRightFixed);
// boolean bad3 = vRightAssign.size() > 0;
+
boolean bad3 = SetUtils.intersectionP(vRightAssign, vLeftFixed) ;
if ( print )
System.err.println("Case 3 = " + bad3) ;
http://git-wip-us.apache.org/repos/asf/jena/blob/6fd8962a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestClassify.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestClassify.java b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestClassify.java
index d3d4b14..d3819c4 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestClassify.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestClassify.java
@@ -122,6 +122,11 @@ public class TestClassify extends BaseTest
@Test public void testClassify_Join_44()
{ classifyJ("{ BIND(<x> AS ?typeX) { BIND(?typeX AS ?type) ?s ?p ?o FILTER(?o=?type) } }", false) ; }
+ // Unsafe - deep MINUS
+ // JENA-1021
+ @Test public void testClassify_Join_50()
+ { classifyJ("{ ?x ?y ?z { ?x1 ?y1 ?z1 MINUS { ?a ?b ?c } } UNION {} }", false) ; }
+
private void classifyJ(String pattern, boolean expected)
{
String qs1 = "PREFIX : <http://example/>\n" ;