Return-Path: X-Original-To: apmail-incubator-jena-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-jena-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9D34A9EA8 for ; Wed, 28 Dec 2011 18:46:58 +0000 (UTC) Received: (qmail 87981 invoked by uid 500); 28 Dec 2011 18:46:58 -0000 Delivered-To: apmail-incubator-jena-commits-archive@incubator.apache.org Received: (qmail 87956 invoked by uid 500); 28 Dec 2011 18:46:58 -0000 Mailing-List: contact jena-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jena-dev@incubator.apache.org Delivered-To: mailing list jena-commits@incubator.apache.org Received: (qmail 87949 invoked by uid 99); 28 Dec 2011 18:46:58 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Dec 2011 18:46:58 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Dec 2011 18:46:54 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id AA14323888E7; Wed, 28 Dec 2011 18:46:32 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1225272 - in /incubator/jena/Jena2/ARQ/trunk: ./ src/main/java/com/hp/hpl/jena/sparql/lang/ src/main/java/com/hp/hpl/jena/sparql/syntax/ src/main/java/com/hp/hpl/jena/sparql/util/ src/test/java/com/hp/hpl/jena/sparql/lang/ Date: Wed, 28 Dec 2011 18:46:32 -0000 To: jena-commits@incubator.apache.org From: andy@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111228184632.AA14323888E7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: andy Date: Wed Dec 28 18:46:31 2011 New Revision: 1225272 URL: http://svn.apache.org/viewvc?rev=1225272&view=rev Log: JENA-142 Scope tracking of variables. Modified: incubator/jena/Jena2/ARQ/trunk/ChangeLog.txt incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/SyntaxVarScope.java incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/ElementWalker.java incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/PatternVarsVisitor.java incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/RecursiveElementVisitor.java incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/util/VarUtils.java incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/lang/TestVarScope.java Modified: incubator/jena/Jena2/ARQ/trunk/ChangeLog.txt URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/ChangeLog.txt?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/ChangeLog.txt (original) +++ incubator/jena/Jena2/ARQ/trunk/ChangeLog.txt Wed Dec 28 18:46:31 2011 @@ -3,11 +3,16 @@ ChangeLog for ARQ ==== ARQ 2.9.1 ++ SPARQL 1.1: Complete scope tracking of variables (JENA-142) ++ Faster writing of XML and JSON results formats (JENA-178) + + ==== ARQ 2.8.9 / 2.9.0 ** Java 6 is now required for running ARQ. -+ ARQ: Provides \-escapes for characters ~.-!$&'()*+,;=:/?#@% in local part of prefix names -+ ARQ: Allow %xx in the local part of prefix names ++ SPARQL 1.1: Provides \-escapes for characters ~.-!$&'()*+,;=:/?#@% + in local part of prefix names ++ SPARQl 1.1: Allow %xx in the local part of prefix names + SPARQL 1.1 / RDF 1.1 : DATATYPE(literal-with-lang) is now rdf:langString, not an error. + DatasetFactory: perferred methods for an in-memory dataset are: create() -- will automatically add in-memory named graphs Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/SyntaxVarScope.java URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/SyntaxVarScope.java?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/SyntaxVarScope.java (original) +++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/SyntaxVarScope.java Wed Dec 28 18:46:31 2011 @@ -56,6 +56,8 @@ public class SyntaxVarScope * SubQuery done as a separate pass. * Combine finalization with findAndAddNamedVars/setResultVars */ + + // Weakness : EXISTS inside FILTERs? public static void check(Query query) { @@ -76,12 +78,8 @@ public class SyntaxVarScope // Check BIND by accumulating variables and making sure BIND does not attempt to reuse one private static void checkBind(Query query) { - LinkedHashSet queryVars = new LinkedHashSet() ; - BindScopeChecker visitor = new BindScopeChecker(queryVars) ; - //PatternVars.vars(query.getQueryPattern(), visitor) ; - - ElementWalker.Walker walker = new ScopeWalker(visitor) ; - ElementWalker.walk(query.getQueryPattern(), walker) ; + HashSet queryVars = new HashSet() ; + scopeVars(queryVars, query.getQueryPattern()) ; } // Check subquery by finding subquries and recurisively checking. @@ -239,26 +237,16 @@ public class SyntaxVarScope } } - /** Accumulate pattern variables but include some checking (BIND) as well */ - private static class BindScopeChecker extends PatternVarsVisitor + // Special version of walker for scoping rules. + + private static void scopeVars(Collection acc, Element e) { - public BindScopeChecker(Set s) - { - super(s) ; - } - - @Override - public void visit(ElementBind el) - { - Var var = el.getVar() ; - - if ( acc.contains(var) ) - throw new QueryParseException("BIND: Variable used when already in-scope: "+var+" in "+el, -1 , -1) ; - checkAssignment(acc, el.getExpr(), var) ; - } + PatternVarsVisitor pvv = new PatternVarsVisitor(acc) ; + ScopeWalker sw = new ScopeWalker(pvv) ; + e.visit(sw) ; } - - // Special version of walker for scoping rules. + + // Applies scope rules and does the structure walk. public static class ScopeWalker extends ElementWalker.Walker { @@ -274,21 +262,16 @@ public class SyntaxVarScope public void visit(ElementMinus el) { // Don't go down the RHS of MINUS - //if ( el.getMinusElement() != null ) - // el.getMinusElement().visit(this) ; proc.visit(el) ; } - // It is a top-down walk, so on enter an element of group or UNION, - // then the entry set is - // Isolate elements of UNION @Override public void visit(ElementUnion el) { - Set accState = new HashSet(pvVisitor.acc) ; - doMultipleIndependent(accState, el.getElements()) ; - pvVisitor.acc = accState ; + Collection accGroup = pvVisitor.acc ; + for ( Element e : el.getElements() ) + nestedScope(accGroup, e) ; proc.visit(el) ; } @@ -300,28 +283,66 @@ public class SyntaxVarScope // FILTER end of group // All other elements (SERVICE?) outcome is only to the overall results. -// @Override -// public void visit(ElementGroup el) -// { -// // But BIND needs to be does over end of group. -// // Ditto FILTER tests. -// Set accState = new HashSet(pvVisitor.acc) ; -// doMultipleIndependent(accState, el.getElements()) ; -// pvVisitor.acc = accState ; -// proc.visit(el) ; -// } + @Override + public void visit(ElementGroup el) + { + // Ther are two kinds of elements: ones that accumulate variables + // across the group and ones that isolate a subexpression to be joined + // with other and the group itself. + // Scoped: UNION, Group, OPTIONAL, (MINUS), SERVICE, SubSELECT + // Acumulating: BGPs, paths, BIND, LET + + Collection accGroup = pvVisitor.acc ; // Accumulate as we go. + + for ( Element e : el.getElements() ) + { + if ( scoped(e) ) + nestedScope(accGroup, e) ; + else + scopeVars(accGroup, e) ; + } + proc.visit(el) ; + } + private void nestedScope(Collection accGroup , Element e ) + { + // New scope accumulator. + Collection x = new HashSet() ; + scopeVars(x, e) ; + accGroup.addAll(x) ; + } - private void doMultipleIndependent(Set agg, List elements) + private static boolean scoped(Element e) + { + return e instanceof ElementGroup || + e instanceof ElementUnion || + e instanceof ElementOptional || + e instanceof ElementService || + e instanceof ElementSubQuery ; + } + + // Inside filters. + + @Override + public void visit(ElementBind el) + { + Var var = el.getVar() ; + + if ( pvVisitor.acc.contains(var) ) + throw new QueryParseException("BIND: Variable used when already in-scope: "+var+" in "+el, -1 , -1) ; + checkAssignment(pvVisitor.acc, el.getExpr(), var) ; + } + + + + @Override + public void visit(ElementService el) { - // agg is empty? - for ( Element e : elements ) + if ( el.getServiceNode().isVariable() ) { - pvVisitor.acc.clear() ; - // Do subelement. - e.visit(this) ; - // Accumulate for final result. - agg.addAll(pvVisitor.acc) ; + Var var = Var.alloc(el.getServiceNode()) ; + if ( ! pvVisitor.acc.contains(var) ) + throw new QueryParseException("SERVICE: Variable not already in-scope: "+var+" in "+el, -1 , -1) ; } } Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/ElementWalker.java URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/ElementWalker.java?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/ElementWalker.java (original) +++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/ElementWalker.java Wed Dec 28 18:46:31 2011 @@ -19,12 +19,12 @@ package com.hp.hpl.jena.sparql.syntax; - /** An element visitor that walks the graph pattern tree, * applying a visitor at each Element traversed. - * Only walks one level of the query (not subqueries -- sub SELECT, (NOT)EXISTS - * these will need to call down themselves if it is meaningful for the visitor. - * Bottom-up walk - apply to subelements before applying to current element. */ + * Does not (NOT)EXISTS in filters. + * These will need to call down themselves if it is meaningful for the visitor. + * Bottom-up walk - apply to subelements before applying to current element. + */ public class ElementWalker { @@ -49,7 +49,10 @@ public class ElementWalker static public class Walker implements ElementVisitor { protected ElementVisitor proc ; - protected Walker(ElementVisitor visitor) { proc = visitor ; } + protected Walker(ElementVisitor visitor) + { + proc = visitor ; + } @Override public void visit(ElementTriplesBlock el) @@ -129,22 +132,17 @@ public class ElementWalker proc.visit(el) ; } - // EXISTs, NOT EXISTs are really subqueries so don't automatically walk down them. - // NB They also occur in FILTERs via expressions. + // EXISTs, NOT EXISTs also occur in FILTERs via expressions. @Override public void visit(ElementExists el) { -// if ( el.getElement() != null ) -// el.getElement().visit(this) ; proc.visit(el) ; } @Override public void visit(ElementNotExists el) { -// if ( el.getElement() != null ) -// el.getElement().visit(this) ; proc.visit(el) ; } @@ -159,10 +157,6 @@ public class ElementWalker @Override public void visit(ElementSubQuery el) { - // Only walk this level. -// Element el2 = el.getQuery().getQueryPattern() ; -// if ( el2 != null ) -// el2.visit(this) ; proc.visit(el) ; } Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/PatternVarsVisitor.java URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/PatternVarsVisitor.java?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/PatternVarsVisitor.java (original) +++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/PatternVarsVisitor.java Wed Dec 28 18:46:31 2011 @@ -18,8 +18,8 @@ package com.hp.hpl.jena.sparql.syntax; +import java.util.Collection ; import java.util.Iterator ; -import java.util.Set ; import com.hp.hpl.jena.graph.Triple ; import com.hp.hpl.jena.sparql.core.TriplePath ; @@ -29,8 +29,8 @@ import com.hp.hpl.jena.sparql.util.VarUt public class PatternVarsVisitor extends ElementVisitorBase { - public Set acc ; - public PatternVarsVisitor(Set s) { acc = s ; } + public Collection acc ; + public PatternVarsVisitor(Collection s) { acc = s ; } @Override public void visit(ElementTriplesBlock el) Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/RecursiveElementVisitor.java URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/RecursiveElementVisitor.java?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/RecursiveElementVisitor.java (original) +++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/syntax/RecursiveElementVisitor.java Wed Dec 28 18:46:31 2011 @@ -26,9 +26,9 @@ package com.hp.hpl.jena.sparql.syntax; * calling points: *
    *
  • start of element
  • - *
  • end of element
  • *
  • start each sub element
  • *
  • end of each sub element
  • + *
  • end of element
  • *
*

* Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/util/VarUtils.java URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/util/VarUtils.java?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/util/VarUtils.java (original) +++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/util/VarUtils.java Wed Dec 28 18:46:31 2011 @@ -18,6 +18,7 @@ package com.hp.hpl.jena.sparql.util; +import java.util.Collection ; import java.util.HashSet ; import java.util.Set ; @@ -35,20 +36,20 @@ public class VarUtils return x ; } - public static void addVarsFromTriple(Set acc, Triple t) + public static void addVarsFromTriple(Collection acc, Triple t) { addVar(acc, t.getSubject()) ; addVar(acc, t.getPredicate()) ; addVar(acc, t.getObject()) ; } - public static void addVarsFromTriplePath(Set acc, TriplePath tpath) + public static void addVarsFromTriplePath(Collection acc, TriplePath tpath) { addVar(acc, tpath.getSubject()) ; addVar(acc, tpath.getObject()) ; } - public static void addVar(Set acc, Node n) + public static void addVar(Collection acc, Node n) { if ( n == null ) return ; Modified: incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/lang/TestVarScope.java URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/lang/TestVarScope.java?rev=1225272&r1=1225271&r2=1225272&view=diff ============================================================================== --- incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/lang/TestVarScope.java (original) +++ incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/lang/TestVarScope.java Wed Dec 28 18:46:31 2011 @@ -22,16 +22,14 @@ import org.junit.Test ; import org.openjena.atlas.junit.BaseTest ; import com.hp.hpl.jena.query.Query ; -import com.hp.hpl.jena.query.QueryFactory ; import com.hp.hpl.jena.query.QueryException ; -import com.hp.hpl.jena.sparql.lang.SyntaxVarScope ; +import com.hp.hpl.jena.query.QueryFactory ; public class TestVarScope extends BaseTest { private static void scope(String queryStr) { Query query = QueryFactory.create(queryStr) ; - SyntaxVarScope.check(query) ; } @Test public void scope_01() { scope("SELECT ?x { ?s ?p ?o }") ; } @@ -62,25 +60,37 @@ public class TestVarScope extends BaseTe @Test (expected=QueryException.class) public void scope_21() { scope("SELECT ?o { ?x ?p ?o } GROUP BY ?x") ; } + + @Test(expected=QueryException.class) + public void scope_22() { scope("SELECT * { ?s ?p ?o BIND(5 AS ?o) }") ; } - @Test public void scope_22() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(?o2+5 AS ?z) }") ; } + @Test public void scope_23() { scope("SELECT * { ?s ?p ?o { BIND(5 AS ?o) } }") ; } + + @Test(expected=QueryException.class) + public void scope_24() { scope("SELECT * { { ?s ?p ?o } BIND(5 AS ?o) }") ; } + + @Test public void scope_25() { scope("SELECT * { { ?s ?p ?o } { BIND(5 AS ?o) } }") ; } + + @Test public void scope_26() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(?o2+5 AS ?z) }") ; } @Test(expected=QueryException.class) - public void scope_23() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(5 AS ?o2) }") ; } + public void scope_27() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(5 AS ?o2) }") ; } @Test(expected=QueryException.class) - public void scope_24() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(?o+5 AS ?o2) }") ; } + public void scope_28() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(?o+5 AS ?o2) }") ; } @Test(expected=QueryException.class) - public void scope_25() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(5 AS ?o) }") ; } + public void scope_29() { scope("SELECT * { ?s ?p ?o OPTIONAL{?s ?p2 ?o2} BIND(5 AS ?o) }") ; } + @Test(expected=QueryException.class) + public void scope_31() { scope("SELECT * { { ?s ?p ?o } UNION {?s ?p2 ?o2} BIND(5 AS ?o) }") ; } // Subqueries @Test(expected=QueryException.class) - public void scope_30() { scope("SELECT * { SELECT (?o+1 AS ?o) { ?s ?p ?o }}") ; } + public void scope_50() { scope("SELECT * { SELECT (?o+1 AS ?o) { ?s ?p ?o }}") ; } @Test - public void scope_31() + public void scope_51() { scope("SELECT ?y { " + "{ { SELECT (?x AS ?y) { ?s ?p ?x } } } UNION { { SELECT (?x AS ?y) { ?s ?p ?x } } }" + @@ -88,7 +98,7 @@ public class TestVarScope extends BaseTe } @Test(expected=QueryException.class) - public void scope_32() + public void scope_52() { scope("SELECT ?y { " + "{ { SELECT (?o+1 AS ?x) (?o+1 AS ?x) { ?s ?p ?o } } UNION { ?s ?p ?x } }" +