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 2022/06/10 07:56:36 UTC

[jena] branch main updated: gh-1369: Fix for handling assignments in OpAsQuery

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 4e57638acf gh-1369: Fix for handling assignments in OpAsQuery
     new 9dcfc13d7c Merge pull request #1370 from Aklakan/gh-1369
4e57638acf is described below

commit 4e57638acf3b009644098c6b0b2cb4d5e800fc92
Author: Claus Stadler <Ra...@googlemail.com>
AuthorDate: Mon Jun 6 16:25:46 2022 +0200

    gh-1369: Fix for handling assignments in OpAsQuery
---
 .../org/apache/jena/sparql/algebra/OpAsQuery.java  |  76 ++++++-
 .../apache/jena/sparql/algebra/TestOpAsQuery.java  | 244 +++++++++++----------
 2 files changed, 191 insertions(+), 129 deletions(-)

diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
index 37a106f8b7..ea895114ae 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
@@ -253,12 +253,13 @@ public class OpAsQuery {
             } ;
 
             // The assignments will become part of the project.
-            Map<Var, Expr> assignments = new HashMap<>() ;
+            // Using VarExprList to preserve order; https://github.com/apache/jena/issues/1369
+            VarExprList assignments = new VarExprList();
             if ( level.opExtends != null ) {
                 processExtends(level.opExtends, (var,expr)->{
                     // Internal rename.
                     expr = rewrite(expr, varToExpr) ;
-                    assignments.put(var, expr) ;
+                    assignments.add(var, expr) ;
                 }) ;
 
             }
@@ -286,17 +287,70 @@ public class OpAsQuery {
                 // No project, Make BINDs
                 //processQueryPattern(op, assignments) ;
 
-
             } else {
-                level.opProject.getVars().forEach(v -> {
-                    if ( assignments.containsKey(v) ) {
-                        query.addResultVar(v, assignments.get(v)) ;
-                    } else
-                        query.getProjectVars().add(v) ;
+                // Where assignments and projections align the assignments will become part of the projection
+                // otherwise the assignments will become BINDs; https://github.com/apache/jena/issues/1369
+                List<Var> projectVars = level.opProject.getVars();
+
+                List<Var> assignVars = assignments.getVars();
+                int assignVarsSize = assignVars.size();
+                int projectOffset = assignVarsSize; // Start at end and search backwards
+                int idxThreshold = Integer.MAX_VALUE; // Prevent adding later mentioned expressions earlier to the projection list
+
+                // Find an offset in the assignments from which on
+                // *all remaining* variables appears in the same order as in the projection
+                while (projectOffset-- > 0) {
+                    Var assignVar = assignVars.get(projectOffset);
+
+                    // Ensure that the projection does not shuffle the given order of expressions
+                    // A later assignment must also appear later in the built projection
+                    int idx = projectVars.indexOf(assignVar);
+                    if (idx < 0 || idx > idxThreshold) {
+                        break;
+                    }
+                    idxThreshold = idx;
+                }
 
-                }) ;
-            }
+                // Assignments with index <= projectOffset become BINDs
+                // Note that a projectOffset of -1 means there won't be any BINDs
+                if (projectOffset >= 0) {
+                    Element activeElement = query.getQueryPattern();
+
+                    ElementGroup activeGroup;
+                    if (activeElement instanceof ElementGroup) {
+                        activeGroup = (ElementGroup)activeElement;
+                    } else {
+                        // Not sure whether it's possible here for BINDs to exist with the
+                        // activeElement NOT being a group pattern - but better safe than sorry
+                        activeGroup = new ElementGroup();
+                        activeGroup.addElement(activeElement);
+                        query.setQueryPattern(activeGroup);
+                    }
+
+                    for (int i = 0; i <= projectOffset; ++i) {
+                        Var v = assignVars.get(i);
+                        Expr e = assignments.getExpr(v);
+                        activeGroup.addElement(new ElementBind(v, e));
+                    }
+                }
 
+                // For each projected variable determine whether a possible expression was already
+                // added as a BIND or whether it needs to be projected
+                for (Var v : projectVars) {
+                    Expr e = assignments.getExpr(v);
+
+                    int offset = assignVars.indexOf(v);
+                    if (offset > projectOffset) {
+                        // Note that 'query.addResultVar' handles the case where e is null
+                        query.addResultVar(v, e) ;
+                    }
+                    else {
+                        // Either the variable did not map to an expression or
+                        // the expression was added as BIND - in any case just project the variable
+                        query.addResultVar(v, null) ;
+                    }
+                }
+            }
 
             if ( level.opDistinct != null )
                 query.setDistinct(true) ;
@@ -314,7 +368,7 @@ public class OpAsQuery {
         /**
          * Collect the OpExtend in a stack of OpExtend into a list for later
          * processing. (Processing only uses opExtend in the list, not inner one
-         * which wil also be in the list.)
+         * which will also be in the list.)
          */
         private static Op processExtend(Op op, List<OpExtend> assignments) {
             while ( op instanceof OpExtend ) {
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java
index ea96ecff33..2fa959bfbb 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java
@@ -42,58 +42,66 @@ public class TestOpAsQuery {
     @Test public void testBasic02() { test_roundTripQuery("SELECT * { ?s ?p ?o }") ; }
     @Test public void testBasic03() { test_roundTripQuery("SELECT * { ?s ?p ?o FILTER(?o > 5) }") ; }
     @Test public void testBasic04() { test_roundTripQuery("SELECT ?s { ?s ?p ?o FILTER(?o > 5) }") ; }
-    
-    // 01, 02: Same algebra.  
+
+    // 01, 02: Same algebra.
     @Test public void testBind01() { test_roundTripQuery("SELECT ?s (?o + 5 AS ?B) { ?s ?p ?o }") ; }
     @Test public void testBind02() { test_roundTripAlegbra("SELECT ?o ?B  { ?s ?p ?o BIND (?o + 5 AS ?B) }") ; }
     // No project
     @Test public void testBind03() { test_roundTripQuery("SELECT * { ?s ?p ?o BIND (?o + 5 AS ?B)  }") ; }
-    
+
     // Over nested.
-    @Test public void testBind04() { 
+    @Test public void testBind04() {
         test_roundTripQuery("SELECT * { ?s ?p ?o BIND(?o+1 AS ?a1) ?x ?q ?v BIND(?v+2 AS ?a2) }",
-                            "SELECT * { { ?s ?p ?o BIND(( ?o + 1 ) AS ?a1) } ?x ?q ?v BIND(( ?v + 2 ) AS ?a2) } "); 
+                            "SELECT * { { ?s ?p ?o BIND(( ?o + 1 ) AS ?a1) } ?x ?q ?v BIND(( ?v + 2 ) AS ?a2) } ");
     }
-    
+
     // Over nested.
-    @Test public void testBind05() { 
+    @Test public void testBind05() {
         test_roundTripQuery("SELECT * { ?s ?p ?o BIND(?o+1 AS ?a1) ?x ?q ?v BIND(2 AS ?a2) } ORDER BY ?s",
-                            "SELECT * { { { ?s ?p ?o BIND(( ?o + 1 ) AS ?a1) } ?x ?q ?v } BIND(2 AS ?a2) } ORDER BY ?s"); 
+                            "SELECT * { { { ?s ?p ?o BIND(( ?o + 1 ) AS ?a1) } ?x ?q ?v } BIND(2 AS ?a2) } ORDER BY ?s");
     }
-    
+
     // https://issues.apache.org/jira/browse/JENA-1843
     @Test public void testBind06() { test_roundTripQuery("SELECT * { ?s ?p ?o BIND(?o + 1 AS ?a1) BIND(?v+2 as ?a2) }"); }
     @Test public void testBind07() { test_roundTripQuery("SELECT * { BIND(?o + 1 AS ?a1) BIND(?v+2 as ?a2) }"); }
-    
-    @Test public void testOptional01() 
+
+    // https://github.com/apache/jena/issues/1369
+    @Test public void testBind08() { test_roundTripQuery("SELECT (?x AS ?y) { BIND ('x' AS ?x) }"); }
+    @Test public void testBind09() { test_roundTripQuery("SELECT ('y' AS ?y) ?x { BIND ('x' AS ?x) }"); }
+    @Test public void testBind10() { test_roundTripQuery("SELECT ('y' AS ?y) ?s ('x' AS ?x) { ?s ?p ?o }"); }
+    @Test public void testBind11() { test_roundTripQuery("SELECT ?s ('y' AS ?y) ?p ?x ?o { ?s ?p ?o BIND ('x' AS ?x) }"); }
+    @Test public void testBind12() { test_roundTripQuery("SELECT ?w ('y' AS ?y) ?x { BIND('w' AS ?w) ?s ?p ?o BIND ('x' AS ?x) }"); }
+    @Test public void testBind13() { test_roundTripQuery("SELECT ('x' AS ?x) (str(?x) AS ?y) (str(?x) AS ?z) {}"); }
+
+    @Test public void testOptional01()
     { test_roundTripQuery("SELECT * WHERE { ?s ?p ?o OPTIONAL { ?s ?q ?z FILTER (?foo) } }") ; }
-    
+
     // Double {{...}} matter here in SPARQL.
-    @Test public void testOptional02() 
+    @Test public void testOptional02()
     { test_roundTripQuery("SELECT * WHERE { ?s ?p ?o OPTIONAL { { ?s ?q ?z FILTER (?foo) } } }") ; }
-    
-    @Test public void testOptional03() 
+
+    @Test public void testOptional03()
     // Don't currently unnest the LHS of the second optional.  See testOptional03a
     { test_roundTripQuery("SELECT * WHERE { ?s ?p ?o OPTIONAL { ?s ?p1 ?o1 } OPTIONAL { ?s ?p2 ?o2 } } ") ; }
 
-    @Test public void testOptional04() 
+    @Test public void testOptional04()
     { test_roundTripQuery("SELECT * WHERE { ?s ?p ?o OPTIONAL { ?s ?p1 ?o1 } OPTIONAL { ?s ?p2 ?o2 } OPTIONAL { ?s ?p3 ?o3 }} ") ; }
 
     @Test
     public void testCountStar() {
         test_roundTripQuery("select (count(*) as ?cs) { ?s ?p ?o }");
     }
-    
+
     @Test
     public void testCountGroup() {
         test_roundTripQuery("select (count(?p) as ?cp) { ?s ?p ?o } group by ?s");
     }
-    
+
     @Test
     public void testCountGroupAs() {
         test_roundTripQuery("select (count(?p) as ?cp) { ?s ?p ?o }");
     }
-    
+
     @Test
     public void testDoubleCount() {
         Query[] result = test_roundTripQuery("select (count(?s) as ?sc) (count(?p) as ?pc) { ?s ?p ?o }") ;
@@ -101,74 +109,74 @@ public class TestOpAsQuery {
         assertTrue(result[1].getResultVars().contains("sc"));
         assertTrue(result[1].getResultVars().contains("pc"));
     }
-    
+
     /* JENA-166 */
     @Test
     public void testGroupWithExpression() {
         test_roundTripQuery("SELECT (sample(?a) + 1 AS ?c) {} GROUP BY ?x");
     }
-    
+
     /* Coverage developed for JENA-963 : GROUP BY*/
     @Test public void testGroupBy_01()
     { test_roundTripQuery("SELECT ?s { ?s ?p ?o } GROUP BY ?s"); }
-    
+
     @Test public void testGroupBy_02()
     { test_roundTripQuery("SELECT (count(?p) as ?cp) { ?s ?p ?o } GROUP BY ?s"); }
-    
+
     @Test public void testGroupBy_03()
     { test_roundTripQuery("SELECT ?s { ?s ?p ?o } GROUP BY ?s HAVING (count(*) > 1 )"); }
-    
+
     @Test public void testGroupBy_04()
     { test_roundTripQuery("SELECT ?s { ?s ?p ?o } GROUP BY ?s HAVING (?s > 1 )"); }
-    
+
     @Test public void testGroupBy_05()
     { test_roundTripQuery("SELECT (count(?p) as ?cp) { ?s ?p ?o } GROUP BY ?s HAVING (?cp > 1 )"); }
-    
+
     @Test public void testGroupBy_06()
     { test_roundTripQuery("SELECT (count(?p) as ?cp) { ?s ?p ?o } GROUP BY (abs(?o)) HAVING (?cp > 1 )"); }
-    
+
     @Test public void testGroupBy_07()
     { test_roundTripQuery("SELECT (?X+2 AS ?Y) (count(?p) as ?cp) ?Z (1/?X AS ?X1) { ?s ?p ?o } GROUP BY ?Z (abs(?o) AS ?X) HAVING (?cp > 1 )"); }
-    
+
     @Test public void testGroupBy_08()
     { test_roundTripQuery("SELECT (count(?p) as ?cp) { ?s ?p ?o } GROUP BY (abs(?o)) HAVING (?cp > 1 )"); }
-    
+
     @Test public void testGroupBy_09()
     { test_roundTripQuery("SELECT (count(?p) as ?cp) { ?s ?p ?o } GROUP BY (abs(?o)) ORDER BY (COUNT(*))"); }
-    
+
     @Test public void testGroupBy_10()
     { test_roundTripQuery("SELECT (7+count(?p) as ?cp) { ?s ?p ?o } GROUP BY (abs(?o)) HAVING (?cp > 1 && SUM(?o) > 99 ) ORDER BY (6+COUNT(*))"); }
-    
+
     @Test public void testGroupBy_11()
     { test_roundTripQuery("SELECT ?X { ?s ?p ?o } GROUP BY (abs(?o) AS ?X) HAVING (?cp > 1 )"); }
-    
+
     @Test public void testGroupBy_12()
-    { test_roundTripQuery("SELECT * { ?s ?q ?z {SELECT DISTINCT * { ?s ?p ?o }} }"); } 
-    
+    { test_roundTripQuery("SELECT * { ?s ?q ?z {SELECT DISTINCT * { ?s ?p ?o }} }"); }
+
     // https://issues.apache.org/jira/browse/JENA-1844
     @Test public void testGroupBy_13()
     { test_roundTripQuery("SELECT * { ?s ?p ?o BIND(?o+1 AS ?a1) } ORDER BY ?s"); }
-    
+
     @Test public void testSubQuery_01()
     { test_roundTripQuery("SELECT ?s { SELECT (count(*) as ?cp) { ?s ?p ?o } }") ; }
-    
+
     @Test public void testSubQuery_02()
     { test_roundTripQuery("SELECT ?s { ?s ?p ?o { SELECT (count(*) as ?cp) { ?s ?p ?o } }}") ; }
-    
+
     @Test public void testSubQuery_03()
     { test_roundTripQuery("SELECT ?s { { SELECT (count(*) as ?cp) { ?s ?p ?o } } ?s ?p ?o }") ; }
-    
+
     @Test public void testSubQuery_04()
     { test_roundTripQuery("SELECT * WHERE { ?s ?p ?o . BIND(?o AS ?x) }") ; }
-    
+
     @Test public void testSubQuery_05()
     { test_roundTripQuery("SELECT (?o AS ?x) WHERE { ?s ?p ?o .}") ; }
-    
+
     @Test
     public void testProject1() {
         test_roundTripQuery("SELECT (?x + 1 AS ?c) {}");
     }
-    
+
     @Test
     public void testProject2() {
         Query[] result = test_roundTripQuery("SELECT (?x + 1 AS ?c) ?d {}");
@@ -176,72 +184,72 @@ public class TestOpAsQuery {
         assertTrue(result[1].getResultVars().contains("c"));
         assertTrue(result[1].getResultVars().contains("d"));
     }
-    
+
     @Test
     public void testNestedBind() {
         test_roundTripQuery("SELECT ?c { { } UNION { BIND(?x + 1 AS ?c) } }");
     }
-    
+
     @Test
     public void testNestedProject() {
         test_roundTripQuery("SELECT (?x + 1 AS ?c) { { } UNION { } }");
     }
-    
+
     @Test
     public void testGroupExpression() {
         test_roundTripQuery("SELECT ?z { } GROUP BY (?x + ?y AS ?z)");
     }
-    
+
     @Test
     public void testNestedProjectWithGroup() {
         test_roundTripQuery("SELECT (SAMPLE(?c) as ?s) { {} UNION {BIND(?x + 1 AS ?c)} } GROUP BY ?x");
     }
-    
+
     @Test
     public void testQuadPatternInDefaultGraph() {
         test_roundTripQueryQuads("SELECT * WHERE { ?s a ?type }");
     }
-    
+
     @Test
     public void testGraphClauseUri() {
         test_roundTripQuery("SELECT * WHERE { GRAPH <http://example> { ?s a ?type } }");
     }
-    
+
     @Test
     public void testGraphClauseComplex() {
         test_roundTripQuery("SELECT * WHERE { GRAPH <http://example> { ?s a ?type . OPTIONAL { ?s <http://label> ?label } } }");
     }
-    
+
     @Test
     public void testQuadPatternInGraph() {
         test_roundTripQueryQuads("SELECT * WHERE { GRAPH <http://example> { ?s a ?type } }");
     }
-    
+
     @Test
     public void testQuadPatternInGraphComplex01() {
         //This fails because OpQuadPattern's are converted back to individual GRAPH clauses
         Object[] result = roundTripQueryQuad("SELECT * WHERE { GRAPH <http://example> { ?s a ?type . OPTIONAL { ?s <http://label> ?label } } }");
         assertFalse(result[0].equals(result[1]));
     }
-    
+
     @Test
     public void testQuadPatternInGraphComplex02() {
         //This succeeds since each OpQuadPattern is from a single simple GRAPH clause
         test_roundTripQueryQuads("SELECT * WHERE { GRAPH <http://example> { ?s a ?type } OPTIONAL { GRAPH <http://example> { ?s <http://label> ?label } } }");
     }
-    
+
     @Test
     public void testExtend1() {
         // Top Level BIND should now be round trippable
         test_roundTripQuery("SELECT * WHERE { ?s ?p ?o . BIND(?o AS ?x) }");
     }
-    
+
     @Test
     public void testExtend2() {
         // Nested BIND should always have been round trippable
         test_roundTripQuery("SELECT * WHERE { GRAPH ?g { ?s ?p ?o . BIND(?o AS ?x) } }");
     }
-    
+
     @Test
     public void testExtend3() {
         //JENA-429
@@ -250,7 +258,7 @@ public class TestOpAsQuery {
                  "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>" ,
                  "PREFIX mylib: <java:dateadd.lib.pkgfor.arq.>",
                  "",
-                 "SELECT ?yearmonth ( count(?document) as ?total )", 
+                 "SELECT ?yearmonth ( count(?document) as ?total )",
                  "{" ,
                  "    ?document a :Document;",
                  "   :documentDateOfCreation ?date ;",
@@ -259,25 +267,25 @@ public class TestOpAsQuery {
                 "} group by ?yearmonth") ;
         test_roundTripQuery(query);
     }
-    
+
     @Test
     public void testExtend4() {
         //Simplified repo of JENA-429
         test_roundTripQuery("SELECT ?key (COUNT(?member) AS ?total) WHERE { ?s ?p ?o . BIND(LCASE(?o) AS ?key) } GROUP BY ?key");
     }
-    
+
     @Test
     public void testExtendInService() {
         //Original test case from JENA-422
         Query[] result = test_roundTripQuery("SELECT * WHERE { SERVICE <http://example/endpoint> { ?s ?p ?o . BIND(?o AS ?x) } }");
         assertTrue(result[1].toString().contains("BIND"));
     }
-    
+
     @Test
     public void testSubQuery1() {
         test_roundTripQuery("SELECT ?s WHERE { SELECT ?s ?p WHERE { ?s ?p ?o } }");
     }
-    
+
     @Test
     public void testSubQuery2() {
         String query = "SELECT ?s ?x WHERE { { SELECT ?s ?p WHERE { ?s ?p ?o } } { SELECT ?x WHERE { ?x ?p ?o } } }";
@@ -285,53 +293,53 @@ public class TestOpAsQuery {
         // Not all cases of sub-query have unnecessary {} removed.
         test_roundTripQuery(query) ;
     }
-    
+
     @Test
     public void testSubQuery3() {
         String query = "SELECT * WHERE { { SELECT ?s ?p WHERE { ?s ?p ?o } } { SELECT ?x WHERE { ?x ?p ?o } } }";
         test_roundTripQuery(query) ;
     }
-    
+
     @Test
     public void testAggregatesInSubQuery1() {
         //Simplified form of a test case provided via the mailing list (JENA-445)
         String query = "SELECT ?key ?agg WHERE { SELECT ?key (COUNT(*) AS ?agg) { ?key ?p ?o } GROUP BY ?key }";
         test_roundTripQuery(query);
     }
-    
+
     @Test
     public void testAggregatesInSubQuery2() {
         //Simplified form of a test case provided via the mailing list (JENA-445)
         test_roundTripAlegbra("SELECT * WHERE { { SELECT ?key (COUNT(*) AS ?agg) { ?key ?p ?o } GROUP BY ?key } }");
     }
-    
+
     @Test
     public void testAggregatesInSubQuery3() {
         //Actual test case from JENA-445 bug report
-        String queryString = 
-                "PREFIX dcterms: <http://purl.org/dc/terms/> \n" + 
-                "PREFIX dbpedia: <http://dbpedia.org/resource/> \n" + 
-
-                "SELECT ?num_of_holidays ?celebrate_Chinese_New_Year WHERE { \n" + 
-                "{" + 
-                "SELECT ?country_cat (COUNT(?holiday) as ?num_of_holidays) \n" + 
-                "WHERE {" + 
-                "?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. \n" + 
-                "?holiday dcterms:subject ?country_cat \n" + 
-                "}GROUP by ?country_cat \n" + 
-                "} \n" + 
-                "{ \n" + 
-                "SELECT ?country_cat (COUNT(?holiday) as ?celebrate_Chinese_New_Year) \n" + 
-                "WHERE { \n" + 
-                "?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. \n" + 
-                "?holiday dcterms:subject ?country_cat \n" + 
-                "FILTER(?holiday=\"http://dbpedia.org/resource/Lunar_New_Year\'s_Day\") \n" + 
-                "}GROUP by ?country_cat \n" + 
-                "} \n" + 
-                "}\n"; 
+        String queryString =
+                "PREFIX dcterms: <http://purl.org/dc/terms/> \n" +
+                "PREFIX dbpedia: <http://dbpedia.org/resource/> \n" +
+
+                "SELECT ?num_of_holidays ?celebrate_Chinese_New_Year WHERE { \n" +
+                "{" +
+                "SELECT ?country_cat (COUNT(?holiday) as ?num_of_holidays) \n" +
+                "WHERE {" +
+                "?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. \n" +
+                "?holiday dcterms:subject ?country_cat \n" +
+                "}GROUP by ?country_cat \n" +
+                "} \n" +
+                "{ \n" +
+                "SELECT ?country_cat (COUNT(?holiday) as ?celebrate_Chinese_New_Year) \n" +
+                "WHERE { \n" +
+                "?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. \n" +
+                "?holiday dcterms:subject ?country_cat \n" +
+                "FILTER(?holiday=\"http://dbpedia.org/resource/Lunar_New_Year\'s_Day\") \n" +
+                "}GROUP by ?country_cat \n" +
+                "} \n" +
+                "}\n";
         test_roundTripQuery(queryString);
     }
-    
+
     @Test
     public void testModifiersOnSubQuery1() {
         // From JENA-954
@@ -342,10 +350,10 @@ public class TestOpAsQuery {
                                           "      }",
                                           "    } LIMIT 1",
                                           "}");
-        
+
         test_roundTripQuery(query) ;
     }
-    
+
     @Test
     public void testModifiersOnSubQuery2() {
         // From JENA-954
@@ -356,10 +364,10 @@ public class TestOpAsQuery {
                                           "      }",
                                           "    } LIMIT 1",
                                           "}");
-        
+
         test_roundTripQuery(query);
     }
-    
+
     @Test
     public void testModifiersOnSubQuery3() {
         // From JENA-954
@@ -370,10 +378,10 @@ public class TestOpAsQuery {
                                           "      }",
                                           "    } LIMIT 1",
                                           "}");
-        
+
         test_roundTripQuery(query);
     }
-    
+
     @Test
     public void testModifiersOnSubQuery4() {
         // From JENA-954
@@ -384,16 +392,16 @@ public class TestOpAsQuery {
                                           "      }",
                                           "    } OFFSET 1",
                                           "}");
-        
+
         test_roundTripQuery(query);
     }
-    
+
     @Test
     public void testPathExpressions1() {
         String query = "PREFIX : <http://example/> SELECT * { ?s :p* ?o . ?x :r 123 . }" ;
         test_roundTripQuery(query);
     }
-        
+
     @Test
     public void testPathExpressions2() {
         String query = "PREFIX : <http://example/> SELECT * { ?s :p*/:q ?o . ?x :r 123 . }" ;
@@ -402,41 +410,41 @@ public class TestOpAsQuery {
 
     @Test
     public void testMinus1() {
-        test_roundTripQuery("PREFIX : <http://example/> SELECT * { ?s :p ?o MINUS { ?s :q ?v .FILTER(?v<5) } }") ; 
+        test_roundTripQuery("PREFIX : <http://example/> SELECT * { ?s :p ?o MINUS { ?s :q ?v .FILTER(?v<5) } }") ;
     }
-    
+
     @Test
     public void testMinus2() {
         // query gains a level of {} but the meaning is the same.
         String query = "PREFIX : <http://example/> SELECT * { ?s :p ?o OPTIONAL { ?s :x ?2 } MINUS { ?s :q ?v .FILTER(?v<5) } }" ;
         test_roundTripAlegbra(query) ;
     }
-    
+
     @Test
     public void testTable1() {
         String query = "SELECT * WHERE { ?x ?p ?z . VALUES ?y { } }" ;
         roundTripQuery(query);
     }
-    
+
     @Test
     public void testTable2() {
         // JENA-1468 : op to string and back.
         String qs = "SELECT * WHERE { ?x ?p ?z . VALUES ?y { } }" ;
-        Query query = QueryFactory.create(qs); 
+        Query query = QueryFactory.create(qs);
         Op op = Algebra.compile(query);
         String x = op.toString();
         Op op1 = SSE.parseOp(x);
         Query query2 = OpAsQuery.asQuery(op1);
         assertEquals(query, query2);
     }
-    
+
 
     @Test
     public void testValues1() {
         String query = "SELECT  * { VALUES ?x {1 2} ?s ?p ?x }" ;
         test_roundTripQuery(query) ;
     }
-    
+
     @Test
     public void testValues2() {
         String query = "SELECT  * { ?s ?p ?x  VALUES ?x {1 2} }" ;
@@ -444,14 +452,14 @@ public class TestOpAsQuery {
     }
 
     // Algebra to query : optimization cases OpAsQuery can handle.
-    
+
     @Test
     public void testAlgebra01() {
         String opStr = "(sequence (bgp (?s1 ?p1 ?o1)) (bgp (?s2 ?p2 ?o2)) )" ;
         String query = "SELECT * { ?s1 ?p1 ?o1. ?s2 ?p2 ?o2}" ;
         test_AlgebraToQuery(opStr, query);
     }
-    
+
     @Test
     public void testAlgebra02() {
         String opStr = "(sequence (bgp (?s1 ?p1 ?o1)) (path ?x (path* :p) ?z) )" ;
@@ -465,57 +473,57 @@ public class TestOpAsQuery {
         String query = "PREFIX : <http://example/> SELECT * { ?x :p* ?z . ?s1 ?p1 ?o1. }" ;
         test_AlgebraToQuery(opStr, query);
     }
-    
+
     // There 3 classes of transformations: there are 3 main test operations.
     //   test_roundTripQuery: The same query is recovered from OpAsQuery
     //   test_roundTripAlegbra: Different queries with the same alegra forms
     //   test_equivalentQuery: Different equivalent queries - same answers, different algebra.
     //   test_algebraToQuery: algebra to query (e.g. optimization shapes)
-    // 
+    //
     // test_roundTripQuery is test_equivalentQuery with same input and expected.
     // + quad variants.
-    
+
     public static void test_equivalentQuery(String input, String expected) {
         Query orig = QueryFactory.create(input, Syntax.syntaxSPARQL_11);
         Op toReconstruct = Algebra.compile(orig);
         Query got = OpAsQuery.asQuery(toReconstruct);
         Query result = QueryFactory.create(expected, Syntax.syntaxSPARQL_11);
-        assertEquals(result, got); 
+        assertEquals(result, got);
     }
-    
+
     // Test for queries that do query->algebra->OpAsQuery->query
     // to produce an output that is .equals the input.
     /** query->algebra->OpAsQuery->query */
     public static Query[] test_roundTripQuery(String query) {
         // [original, got]
         Query[] r = roundTripQuery(query) ;
-        stripNamespacesAndBase(r[0]) ; 
+        stripNamespacesAndBase(r[0]) ;
         stripNamespacesAndBase(r[1]) ;
         assertEquals(r[0], r[1]) ;
         return r ;
     }
-    
+
     public static void test_roundTripQuery(String query, String outcome) {
         Query[] r = roundTripQuery(query) ;
         Query orig = r[0];
         Query output = r[1];
         Query q2 = QueryFactory.create(outcome);
-        stripNamespacesAndBase(orig) ; 
+        stripNamespacesAndBase(orig) ;
         stripNamespacesAndBase(output) ;
         stripNamespacesAndBase(q2) ;
         assertEquals(q2, output) ;
     }
-    
-    // Test via quads  
+
+    // Test via quads
     public static Query[] test_roundTripQueryQuads(String query) {
         Query[] r = roundTripQueryQuad(query) ;
         assertEquals(r[0], r[1]) ;
         return r ;
     }
 
-    // Compare A1 and A2 where 
+    // Compare A1 and A2 where
     //  query[Q1]->algebra[A1]->OpAsQuery->query[Q2]->algebra[A2]
-    // Sometimes Q1 and Q2 are equivalent but not .equals.  
+    // Sometimes Q1 and Q2 are equivalent but not .equals.
     public void test_roundTripAlegbra(String query) {
         Query[] r = roundTripQuery(query);
         // Even if the strings come out as non-equal because of the translation from algebra to query
@@ -525,7 +533,7 @@ public class TestOpAsQuery {
         Op a2 = Algebra.compile(r[1]);
         Assert.assertEquals(a1, a2);
     }
-    
+
     /** algebra->OpAsQuery->query */
     public static void test_AlgebraToQuery(String input, String expected) {
         Op op = SSE.parseOp(input) ;
@@ -543,7 +551,7 @@ public class TestOpAsQuery {
         Query[] r = { orig, got };
         return r;
     }
-    
+
     /** query->algebra/quads->OpAsQuery->query */
     private static Query[] roundTripQueryQuad(String query) {
         Query orig = QueryFactory.create(query, Syntax.syntaxSPARQL_11);
@@ -553,7 +561,7 @@ public class TestOpAsQuery {
         Query[] r = { orig, got };
         return r;
     }
-    
+
     protected static void stripNamespacesAndBase(Query q) {
         Map<String, String> prefixes = q.getPrefixMapping().getNsPrefixMap();
         for (String prefix : prefixes.keySet()) {