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/03/25 21:33:10 UTC
svn commit: r1460878 - in /jena/trunk:
jena-arq/src/main/java/com/hp/hpl/jena/sparql/algebra/OpAsQuery.java
jena-arq/src/test/java/com/hp/hpl/jena/sparql/algebra/OpAsQueryTest.java
jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java
Author: rvesse
Date: Mon Mar 25 20:33:10 2013
New Revision: 1460878
URL: http://svn.apache.org/r1460878
Log:
Fixes and tests for JENA-422
Allows for top level BIND to round trip (albeit as a project expression but it's semantically equivalent)
Fixes the reported issue of BIND inside a SERVICE clause not being carried to the remote service
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
jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.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=1460878&r1=1460877&r2=1460878&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 Mon Mar 25 20:33:10 2013
@@ -51,11 +51,16 @@ public class OpAsQuery
//OpWalker.walk(op, v) ;
op.visit(v) ;
- List<Var> vars = v.projectVars;
+ Set<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();
+
+ // Depending on where the variable comes from we may already
+ // have added this as a result variable
+ if (query.getResultVars().contains(var)) continue;
+
if (v.varExpression.containsKey(var))
query.addResultVar(var, v.varExpression.get(var));
else
@@ -76,7 +81,7 @@ public class OpAsQuery
private Element element = null ;
private ElementGroup currentGroup = null ;
private Deque<ElementGroup> stack = new ArrayDeque<ElementGroup>() ;
- private List<Var> projectVars = Collections.emptyList() ;
+ private Set<Var> projectVars = Collections.emptySet();
private Map<Var, Expr> varExpression = new HashMap<Var, Expr>() ;
public Converter(Query query)
@@ -419,7 +424,7 @@ public class OpAsQuery
@Override
public void visit(OpAssign opAssign)
{
- opAssign.getSubOp().visit(this) ;
+ opAssign.getSubOp().visit(this) ;
// Go through each var and get the assigned expression
for ( Var v : opAssign.getVarExprList().getVars() )
@@ -432,8 +437,15 @@ public class OpAsQuery
// If in top level we defer assignment to SELECT section
// This also covers the GROUP recombine
- // NOTE: this means we can't round trip top-level BINDs
if (inTopLevel()) {
+ if (!inGroupRecombine(opAssign)) {
+ // If not wrapped over a Group then we need to ensure we add the variable
+ // to the list or otherwise the BIND will not round trip
+ // Note - This does mean top level BIND will manifest as a project expression
+ // rather than a BIND but this is semantically equivalent so is not an issue
+ if (projectVars.isEmpty()) projectVars = new HashSet<Var>();
+ projectVars.add(v);
+ }
varExpression.put(v, tr);
} else {
Element elt = new ElementAssign(v, e) ;
@@ -458,8 +470,15 @@ public class OpAsQuery
// If in top level we defer assignment to SELECT section
// This also covers the GROUP recombine
- // NOTE: this means we can't round trip top-level BINDs
if (inTopLevel()) {
+ if (!inGroupRecombine(opExtend)) {
+ // If not wrapped over a Group then we need to ensure we add the variable
+ // to the list or otherwise the BIND will not round trip
+ // Note - This does mean top level BIND will manifest as a project expression
+ // rather than a BIND but this is semantically equivalent so is not an issue
+ if (projectVars.isEmpty()) projectVars = new HashSet<Var>();
+ projectVars.add(v);
+ }
varExpression.put(v, tr);
} else {
Element elt = new ElementBind(v, tr) ;
@@ -488,7 +507,7 @@ public class OpAsQuery
{
// Defer adding result vars until the end.
// OpGroup generates dupes otherwise
- this.projectVars = opProject.getVars();
+ this.projectVars = new HashSet<Var>(opProject.getVars());
opProject.getSubOp().visit(this) ;
}
@@ -596,6 +615,32 @@ public class OpAsQuery
private ElementGroup pop() { return stack.pop(); }
private void push(ElementGroup el) { stack.push(el); }
private boolean inTopLevel() { return stack.size() == 0; }
+
+ private boolean inGroupRecombine(OpExtend op) {
+ Op subOp = op.getSubOp();
+ if (subOp instanceof OpExtend) {
+ return inGroupRecombine((OpExtend)subOp);
+ } else if (subOp instanceof OpAssign) {
+ return inGroupRecombine((OpAssign)subOp);
+ } else if (subOp instanceof OpGroup) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean inGroupRecombine(OpAssign op) {
+ Op subOp = op.getSubOp();
+ if (subOp instanceof OpExtend) {
+ return inGroupRecombine((OpExtend)subOp);
+ } else if (subOp instanceof OpAssign) {
+ return inGroupRecombine((OpAssign)subOp);
+ } else if (subOp instanceof OpGroup) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
/**
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=1460878&r1=1460877&r2=1460878&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 Mon Mar 25 20:33:10 2013
@@ -52,8 +52,10 @@ public class OpAsQueryTest {
@Test
public void testDoubleCount() {
- Object[] result = checkQuery("select (count(?s) as ?sc) (count(?p) as ?pc) { ?s ?p ?o }");
- assertEquals(result[0], result[1]);
+ Query[] result = checkQuery("select (count(?s) as ?sc) (count(?p) as ?pc) { ?s ?p ?o }");
+ assertEquals(2, result[1].getResultVars().size());
+ assertTrue(result[1].getResultVars().contains("sc"));
+ assertTrue(result[1].getResultVars().contains("pc"));
}
/* JENA-166 */
@@ -63,18 +65,18 @@ public class OpAsQueryTest {
assertEquals(result[0], result[1]);
}
- // The next two tests represent an loss of information
- // I suspect the best solution is to let this pass and the other fail
@Test
- public void testProject() {
+ public void testProject1() {
Object[] result = checkQuery("SELECT (?x + 1 AS ?c) {}");
assertEquals(result[0], result[1]);
}
- // Ambiguous, don't bother
- public void testBind() {
- Object[] result = checkQuery("SELECT ?c { BIND(?x + 1 AS ?c) }");
- assertEquals(result[0], result[1]);
+ @Test
+ public void testProject2() {
+ Query[] result = checkQuery("SELECT (?x + 1 AS ?c) ?d {}");
+ assertEquals(2, result[1].getResultVars().size());
+ assertTrue(result[1].getResultVars().contains("c"));
+ assertTrue(result[1].getResultVars().contains("d"));
}
// This BIND is distinguisable, however
@@ -140,11 +142,34 @@ public class OpAsQueryTest {
assertEquals(result[0], result[1]);
}
- public Object[] checkQuery(String query) {
+ @Test
+ public void testExtend1() {
+ //Top Level BIND should now be round trippable
+ Query[] result = checkQuery("SELECT * WHERE { ?s ?p ?o . BIND(?o AS ?x) }");
+ assertNotEquals(result[0], result[1]);
+ assertTrue(result[1].getResultVars().contains("x"));
+ }
+
+ @Test
+ public void testExtend2() {
+ //Nested BIND should always have been round trippable
+ Query[] result = checkQuery("SELECT * WHERE { GRAPH ?g { ?s ?p ?o . BIND(?o AS ?x) } }");
+ assertEquals(result[0], result[1]);
+ }
+
+ @Test
+ public void testExtendInService() {
+ //Original test case from JENA-422
+ Query[] result = checkQuery("SELECT * WHERE { SERVICE <http://example/endpoint> { ?s ?p ?o . BIND(?o AS ?x) } }");
+ assertEquals(result[0], result[1]);
+ assertTrue(result[1].toString().contains("BIND"));
+ }
+
+ public Query[] checkQuery(String query) {
Query orig = QueryFactory.create(query, Syntax.syntaxSPARQL_11);
Op toReconstruct = Algebra.compile(orig);
Query got = OpAsQuery.asQuery(toReconstruct);
- Object[] r = { orig, got };
+ Query[] r = { orig, got };
return r;
}
@@ -153,7 +178,7 @@ public class OpAsQueryTest {
Op toReconstruct = Algebra.compile(orig);
toReconstruct = Algebra.toQuadForm(toReconstruct);
Query got = OpAsQuery.asQuery(toReconstruct);
- Object[] r = { orig, got };
+ Query[] r = { orig, got };
return r;
}
}
Modified: jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java?rev=1460878&r1=1460877&r2=1460878&view=diff
==============================================================================
--- jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java (original)
+++ jena/trunk/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java Mon Mar 25 20:33:10 2013
@@ -30,6 +30,8 @@ import org.junit.Test ;
import com.hp.hpl.jena.query.DatasetAccessor ;
import com.hp.hpl.jena.query.DatasetAccessorFactory ;
import com.hp.hpl.jena.query.* ;
+import com.hp.hpl.jena.sparql.core.Var;
+import com.hp.hpl.jena.sparql.engine.binding.Binding;
import com.hp.hpl.jena.sparql.resultset.ResultSetCompare ;
import com.hp.hpl.jena.sparql.sse.Item ;
import com.hp.hpl.jena.sparql.sse.SSE ;
@@ -66,6 +68,20 @@ public class TestQuery extends BaseServe
execQuery("SELECT * {?s ?p ?o}", 1) ;
}
+ @Test public void query_recursive_01()
+ {
+ String query = "SELECT * WHERE { SERVICE <" + serviceQuery + "> { ?s ?p ?o . BIND(?o AS ?x) } }";
+ QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, query);
+ ResultSet rs = qExec.execSelect();
+
+ Var x = Var.alloc("x");
+ while (rs.hasNext()) {
+ Binding b = rs.nextBinding();
+ Assert.assertNotNull(b.get(x));
+ }
+ qExec.close();
+ }
+
@Test public void request_id_header_01() throws IOException
{
String qs = Convert.encWWWForm("ASK{}") ;