You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2013/04/23 22:26:31 UTC

svn commit: r1471133 - in /jena/trunk/jena-arq/src: main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java

Author: rvesse
Date: Tue Apr 23 20:26:30 2013
New Revision: 1471133

URL: http://svn.apache.org/r1471133
Log:
Improve handling of sub-queries in OpAsQuery plus additional unit tests for this

Modified:
    jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java
    jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java

Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java?rev=1471133&r1=1471132&r2=1471133&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java (original)
+++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java Tue Apr 23 20:26:30 2013
@@ -44,30 +44,9 @@ import com.hp.hpl.jena.vocabulary.RDF ;
 public class OpAsQuery
 {
     public static Query asQuery(Op op)
-    {
-        Query query = QueryFactory.make() ;
-        
-        Converter v = new Converter(query) ;
-        //OpWalker.walk(op, v) ;
-        op.visit(v) ;
-        
-        Collection<Var> vars = v.projectVars;
-        query.setQueryResultStar(vars.isEmpty());   // SELECT * unless we are projecting
-
-        Iterator<Var> iter = vars.iterator();
-        for (; iter.hasNext();) {
-            Var var = iter.next();           
-            if (v.varExpression.containsKey(var))
-                query.addResultVar(var, v.varExpression.get(var));
-            else
-                query.addResultVar(var);
-        }
-        
-        ElementGroup eg = v.currentGroup ;
-        query.setQueryPattern(eg) ;
-        query.setQuerySelectType() ;
-        query.setResultVars() ;                     // Variables from the group.
-        return query ; 
+    {        
+        Converter converter = new Converter(op) ;
+        return converter.convert();
     }
     
     private static Set<Var> allocProjectVars()
@@ -85,18 +64,52 @@ public class OpAsQuery
     public static class Converter implements OpVisitor
     {
         private Query query ;
+        private Op op ;
         private Element element = null ;
         private ElementGroup currentGroup = null ;
         private Deque<ElementGroup> stack = new ArrayDeque<ElementGroup>() ;
         private Collection<Var> projectVars = allocProjectVars();
         private Map<Var, Expr> varExpression = new HashMap<Var, Expr>() ;
         private int groupDepth = 0;
+        private boolean inProject = false;
+        private boolean hasRun = false;
         
-        public Converter(Query query)
+        public Converter(Op op)
         {
-            this.query = query ;
+            this.query = QueryFactory.create() ;
+            this.op = op;
             currentGroup = new ElementGroup() ;
         }
+        
+        Query convert() {
+            if (hasRun) {
+                return this.query;
+            } else {
+                try {
+                    op.visit(this) ;
+                    
+                    Collection<Var> vars = this.projectVars;
+                    query.setQueryResultStar(vars.isEmpty());   // SELECT * unless we are projecting
+        
+                    Iterator<Var> iter = vars.iterator();
+                    for (; iter.hasNext();) {
+                        Var var = iter.next();           
+                        if (this.varExpression.containsKey(var))
+                            query.addResultVar(var, this.varExpression.get(var));
+                        else
+                            query.addResultVar(var);
+                    }
+                    
+                    ElementGroup eg = this.currentGroup ;                   
+                    query.setQueryPattern(eg) ;
+                    query.setQuerySelectType() ;
+                    query.setResultVars() ;                     // Variables from the group.
+                    return query ; 
+                } finally {
+                    this.hasRun = true;
+                }
+            }
+        }
 
         Element asElement(Op op)
         {
@@ -517,11 +530,22 @@ public class OpAsQuery
         @Override
         public void visit(OpProject opProject)
         {
-            // Defer adding result vars until the end.
-            // OpGroup generates dupes otherwise
-            this.projectVars = allocProjectVars() ;
-            this.projectVars.addAll(opProject.getVars());
-            opProject.getSubOp().visit(this) ;
+            if (inProject) {
+                // If we've already inside a project then we are reconstructing a sub-query
+                // Create a new converter and call on the sub-op to get the sub-query
+                Converter subConverter = new Converter(opProject);
+                ElementSubQuery subQuery = new ElementSubQuery(subConverter.convert());
+                ElementGroup g = currentGroup();
+                g.addElement(subQuery);
+            } else {
+                // Defer adding result vars until the end.
+                // OpGroup generates dupes otherwise
+                this.projectVars = allocProjectVars() ;
+                this.projectVars.addAll(opProject.getVars());
+                inProject = true;
+                opProject.getSubOp().visit(this) ;
+                inProject = false;
+            }
         }
 
         @Override

Modified: jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java?rev=1471133&r1=1471132&r2=1471133&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java (original)
+++ jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java Tue Apr 23 20:26:30 2013
@@ -18,6 +18,8 @@
 
 package com.hp.hpl.jena.sparql.algebra;
 
+import java.util.Map;
+
 import com.hp.hpl.jena.query.Syntax;
 import com.hp.hpl.jena.query.QueryFactory;
 import com.hp.hpl.jena.query.Query;
@@ -175,25 +177,14 @@ public class OpAsQueryTest {
                  "   :documentType \"exam results\" ." ,
                  "    BIND( mylib:DateFormat( xsd:string(?date), \"yyyy-MM\" ) as ?yearmonth )",
                 "} group by ?yearmonth") ;
-        
-        Query[] r = checkQuery(query);
-        // Won't be equal due to lack of prefixes
-        Assert.assertNotEquals(r[0], r[1]);
-        
-        String query2 = r[1].toString();
-        Query q = QueryFactory.create(query2);
+        checkQueryParseable(query, true);
     }
     
     @Test
     public void testExtend4() {
         //Simplified repo of JENA-429
         String query  = "SELECT ?key (COUNT(?member) AS ?total) WHERE { ?s ?p ?o . BIND(LCASE(?o) AS ?key) } GROUP BY ?key";
-        
-        Query[] r = checkQuery(query);
-        Assert.assertEquals(r[0], r[1]);
-        
-        String query2 = r[1].toString();
-        Query q = QueryFactory.create(query2);
+        checkQueryParseable(query, true);
     }
     
     @Test
@@ -203,6 +194,34 @@ public class OpAsQueryTest {
         assertEquals(result[0], result[1]);
         assertTrue(result[1].toString().contains("BIND"));
     }
+    
+    @Test
+    public void testSubQuery1() {
+        String query = "SELECT ?s WHERE { { SELECT ?s ?p WHERE { ?s ?p ?o } } }";
+        checkQueryParseable(query, true);
+    }
+    
+    @Test
+    public void testSubQuery2() {
+        String query = "SELECT ?s ?x WHERE { { SELECT ?s ?p WHERE { ?s ?p ?o } } { SELECT ?x WHERE { ?x ?p ?o } } }";
+        //These end up being non-equal queries because the nesting in the final query is a little funky
+        //but the results should still be semantically equivalent
+        checkQueryParseable(query, false);
+    }
+    
+    @Test
+    public void testAggregatesInSubQuery1() {
+        //Simplified form of a test case provided via the mailing list
+        String query = "SELECT ?key ?agg WHERE { { SELECT ?key (COUNT(*) AS ?agg) { ?key ?p ?o } GROUP BY ?key } }";
+        checkQueryParseable(query, true);
+    }
+    
+    @Test
+    public void testAggregatesInSubQuery2() {
+        //Simplified form of a test case provided via the mailing list
+        String query = "SELECT * WHERE { { SELECT ?key (COUNT(*) AS ?agg) { ?key ?p ?o } GROUP BY ?key } }";
+        checkQueryParseable(query, false);
+    }
         
     public Query[] checkQuery(String query) {
         Query orig = QueryFactory.create(query, Syntax.syntaxSPARQL_11);
@@ -212,7 +231,7 @@ public class OpAsQueryTest {
         return r;
     }
     
-    public Object[] checkQuadQuery(String query) {
+    public Query[] checkQuadQuery(String query) {
         Query orig = QueryFactory.create(query, Syntax.syntaxSPARQL_11);
         Op toReconstruct = Algebra.compile(orig);
         toReconstruct = Algebra.toQuadForm(toReconstruct);
@@ -220,4 +239,29 @@ public class OpAsQueryTest {
         Query[] r = { orig, got };
         return r;
     }
+    
+    public Query[] checkQueryParseable(String query, boolean expectEquals) {
+        Query[] r = checkQuery(query);
+        
+        //Strip namespaces and Base URI from each so comparison is not affected by those
+        stripNamespacesAndBase(r[0]);
+        stripNamespacesAndBase(r[1]);
+        
+        if (expectEquals) {
+            Assert.assertEquals(r[0], r[1]);
+        } else {
+            Assert.assertNotEquals(r[0], r[1]);
+        }
+        String query2 = r[1].toString();
+        Query q = QueryFactory.create(query2);
+        return r;
+    }
+    
+    protected void stripNamespacesAndBase(Query q) {
+        Map<String, String> prefixes = q.getPrefixMapping().getNsPrefixMap();
+        for (String prefix : prefixes.keySet()) {
+            q.getPrefixMapping().removeNsPrefix(prefix);
+        }
+        q.setBaseURI((String)null);
+    }
 }