Skip to content

Commit

Permalink
Fixed some BIND scoping issues
Browse files Browse the repository at this point in the history
Made Extend eval only forget vars not bound outside.
Made Extend only collect vars not in "expr"

This fixes #580
  • Loading branch information
gromgull committed Jan 18, 2017
1 parent 87414fd commit c1b29ae
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 12 deletions.
23 changes: 14 additions & 9 deletions rdflib/plugins/sparql/algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,16 +435,21 @@ def _addVars(x, children):
if isinstance(x, Variable):
return set([x])
elif isinstance(x, CompValue):
x["_vars"] = set(reduce(operator.or_, children, set()))
if x.name == "Bind":
return set([x.var])
elif x.name == 'SubSelect':
if x.projection:
s = set(v.var or v.evar for v in x.projection)
else:
s = set()
if x.name == "Extend":
# vars only used in the expr for a bind should not be included
x["_vars"] = reduce(operator.or_, [ child for child,part in zip(children,x) if part!='expr' ], set())

return set([x.var]) # perhaps this should expose all vars here too?
else:
x["_vars"] = set(reduce(operator.or_, children, set()))

if x.name == 'SubSelect':
if x.projection:
s = set(v.var or v.evar for v in x.projection)
else:
s = set()

return s
return s
return reduce(operator.or_, children, set())


Expand Down
2 changes: 1 addition & 1 deletion rdflib/plugins/sparql/evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def evalExtend(ctx, extend):

for c in evalPart(ctx, extend.p):
try:
e = _eval(extend.expr, c.forget(ctx))
e = _eval(extend.expr, c.forget(ctx, _except=extend._vars))
if isinstance(e, SPARQLError):
raise e

Expand Down
5 changes: 3 additions & 2 deletions rdflib/plugins/sparql/sparql.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,14 @@ def _prologue(self):
bnodes = property(_bnodes)
now = property(_now)

def forget(self, before):
def forget(self, before, _except=None):
"""
return a frozen dict only of bindings made in self
since before
"""
if not _except : _except = []

return FrozenBindings(self.ctx, (x for x in self.iteritems() if before[x[0]] is None))
return FrozenBindings(self.ctx, (x for x in self.iteritems() if x[0] in _except or before[x[0]] is None))

def remember(self, these):
"""
Expand Down
6 changes: 6 additions & 0 deletions test/DAWG/rdflib/bindscope.rq
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
PREFIX s: <http://schema.org/>

SELECT ?s ?o ?x WHERE {
?x s:knows ?o .
{ ?x a s:Person. BIND(?x as ?s) }
}
22 changes: 22 additions & 0 deletions test/DAWG/rdflib/bindscope.srx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="s"/>
<variable name="o"/>
<variable name="x"/>
</head>
<results>
<result>
<binding name="s">
<uri>http://example.org/jane</uri>
</binding>
<binding name="o">
<uri>http://example.org/john</uri>
</binding>
<binding name="x">
<uri>http://example.org/jane</uri>
</binding>

</result>
</results>
</sparql>
6 changes: 6 additions & 0 deletions test/DAWG/rdflib/bindscope.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@prefix s: <http://schema.org/> .
@prefix x: <http://example.org/> .

x:john a s:Person ; s:name "John" .
x:jane a s:Person ; s:name "Jane" ; s:knows x:john.
x:ecorp a s:Organization ; s:name "Evil Corp" ; s:employee x:jane .
9 changes: 9 additions & 0 deletions test/DAWG/rdflib/bindscope2.rq
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
PREFIX s: <http://schema.org/>
PREFIX x: <http://example.org/>

SELECT ?s ?p ?o ?x
WHERE {
?x a s:Person .
{ ?x ?p ?o . BIND (?x as ?s) } UNION
{ ?s ?p ?x . BIND (?x as ?o) }
}
8 changes: 8 additions & 0 deletions test/DAWG/rdflib/bindscope2.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
?s ?p ?o ?x
<http://example.org/john> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person> <http://example.org/john>
<http://example.org/john> <http://schema.org/name> "John" <http://example.org/john>
<http://example.org/jane> <http://schema.org/knows> <http://example.org/john> <http://example.org/john>
<http://example.org/jane> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person> <http://example.org/jane>
<http://example.org/jane> <http://schema.org/name> "Jane" <http://example.org/jane>
<http://example.org/jane> <http://schema.org/knows> <http://example.org/john> <http://example.org/jane>
<http://example.org/ecorp> <http://schema.org/employee> <http://example.org/jane> <http://example.org/jane>
30 changes: 30 additions & 0 deletions test/DAWG/rdflib/manifest.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
:whitespacedot
:minusfilter
:notexistsfilter
:bindscope
:bindscope2
) .


Expand Down Expand Up @@ -81,3 +83,31 @@ From https://github.com/RDFLib/rdflib/issues/615, contributed by https://github.
qt:data <minusfilter.ttl> ] ;
mf:result <notexistsfilter.srx>
.


:bindscope rdf:type mf:QueryEvaluationTest ;
mf:name "Scope of bind in groups";
rdfs:comment """
From https://github.com/RDFLib/rdflib/issues/580, contributed by https://github.com/pchampin
""";
dawgt:approval dawgt:Approved ;
dawgt:approvedBy <http://gromgull.net/me> ;
mf:action
[ qt:query <bindscope.rq> ;
qt:data <bindscope.ttl> ] ;
mf:result <bindscope.srx>
.


:bindscope2 rdf:type mf:QueryEvaluationTest ;
mf:name "Scope of bind in groups2";
rdfs:comment """
From https://github.com/RDFLib/rdflib/issues/580, contributed by https://github.com/pchampin
""";
dawgt:approval dawgt:Approved ;
dawgt:approvedBy <http://gromgull.net/me> ;
mf:action
[ qt:query <bindscope2.rq> ;
qt:data <bindscope.ttl> ] ;
mf:result <bindscope2.tsv>
.

0 comments on commit c1b29ae

Please sign in to comment.