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" ;