James, all,

thanks for your feedback. As I understand your response, you would agree with 
my assessment of the expected query results — because in all cases at least one 
of the variables is not bound in the respective scope, so all queries return 
the empty result. 

When it comes to the FILTER queries, there’s broad "agreement" amongst the 
engines I tested. However, for queries 2a. and 2b. one can observe that many 
(most) engines, amongst them Sesame and Jena, actually do deliver answers. The 
same is true for a slight variant of 2b, which pushes the variable bindings 
into a surrounding VALUES clause:

SELECT ?s ?type WHERE {
  {
    BIND(URI(CONCAT(?typeBase,"Person")) AS ?type)
    ?s a ?o
    FILTER(?o=?type)
  }
  UNION
  {
    BIND(URI(CONCAT(?typeBase,"Animal")) AS ?type)
    ?s a ?o
    FILTER(?o=?type)
  }
} VALUES (?typeBase) { ("http://example.com/";) }

According to the specs, this is translated as P := Join(P, ToMultiSet(data)), 
where P is the algebra translation of the query and “data is a solution set 
formed from the VALUES clause”. Since the arguments of the join are evaluated 
independently, there’s no way for ?typeBase to be bound in the query’s body. 

Note that this effectively limits the usage of an outer VALUES clause to inject 
bindings for variables that are reused in triple patterns only, it never works 
for variables that are (exclusively) used in FILTERs or BIND constructs. Things 
are the way they are, but we repeatedly observed that this can be quite 
confusing for query authors — and it is inconvenient: as indicated by the 
example above, it prevents you from injecting bindings into UNIONs whenever the 
UNION does not explicitly “re-bind" these variables in triple patterns.

Just as a suggestion to the W3C group: it would be great to have some more test 
case coverage for such cases, with the exception of the FILTER cases (1a, 1b) I 
couldn’t find any related test cases. 

Best,
Michael

> On 30 Aug 2015, at 13:56, james anderson <ja...@dydra.com> wrote:
> 
> good afternoon;
> 
>> On 2015-08-27, at 13:27, Michael Schmidt <m...@metaphacts.com 
>> <mailto:m...@metaphacts.com>> wrote:
>> 
>> Dear community,
>> 
>> I’ve repeatedly observed inconsistent behaviour across SPARQL engines when 
>> it comes to the visibility of variables in nested groups (or in UNIONs). Let 
>> me illustrate the issues through a couple of queries, to be executed over a 
>> simple dataset consisting of the two triples:
>> 
>> <http://example.com/Alice <http://example.com/Alice>> a 
>> <http://example.com/Person <http://example.com/Person>> .
>> <http://example.com/Flipper <http://example.com/Flipper>> a 
>> <http://example.com/Animal <http://example.com/Animal>> .
>> 
>> 
> the most transparent bases for interpretation are the algebra expressions.
> sparql.org <http://sparql.org/>’s are included below.
> 
> 
>> 1a.) Visibility of FILTERs
>> 
>> SELECT ?s ?type WHERE { 
>>  BIND(<http://example.com/Person <http://example.com/Person>> AS ?type)
>>  { ?s ?p ?o FILTER(?o=?type) }
>> }
> 
>  1 (base <http://example/base/ <http://example/base/>>
>  2   (project (?s ?type)
>  3     (join
>  4       (extend ((?type <http://example.com/Person 
> <http://example.com/Person>>))
>  5         (table unit))
>  6       (filter (= ?o ?type)
>  7         (bgp (triple ?s ?p ?o))))))
> 
> ?type’s scope includes the join and it’s dominant forms, but does not not 
> include the filter.
> 
>> 
>> As far as I understand the spec, the variable ?type is not visible in the 
>> inner subgroup, so it is unbound when evaluating the FILTER. As a 
>> consequence, this query should return the empty result. Is this correct?
>> 
>> 
>> 1b.) A slight variant of this example is where we do not consider a 
>> GroupGraphPattern but a GroupOrUnionGraphPattern:
>> 
>> SELECT ?s ?type WHERE { 
>>  BIND(<http://example.com/Person <http://example.com/Person>> AS ?type)
>>  { ?s ?p ?o FILTER(?o=?type) }
>> UNION
>> { ?s ?p ?o FILTER(?o!=?type) }
>> }
> 
>  1 (base <http://example/base/ <http://example/base/>>
>  2   (project (?s ?type)
>  3     (join
>  4       (extend ((?type <http://example.com/Person 
> <http://example.com/Person>>))
>  5         (table unit))
>  6       (union
>  7         (filter (= ?o ?type)
>  8           (bgp (triple ?s ?p ?o)))
>  9         (filter (!= ?o ?type)
> 10           (bgp (triple ?s ?p ?o)))))))
> 
> the same is true for this expression.
> 
>> 
>> Again, variable ?type should not be visible in any part of the UNION, so 
>> both filters evaluate to error and the result is empty again. Is this 
>> correct?
>> 
>> 
>> 2a.) Let’s now consider examples where we reuse variables from outside in 
>> BIND expressions rather than FILTERs:
>> 
>> SELECT ?s ?type WHERE { 
>>  BIND("http://example.com/"; AS ?typeBase)
>>  {
>>    BIND(URI(CONCAT(?typeBase,"Person")) AS ?type)
>>   ?s ?p ?o
>>   FILTER(?o=?type)
>>  }
>> }
> 
>  1 (base <http://example/base/ <http://example/base/>>
>  2   (project (?s ?type)
>  3     (join
>  4       (extend ((?typeBase "http://example.com/ <http://example.com/>"))
>  5         (table unit))
>  6       (filter (= ?o ?type)
>  7         (join
>  8           (extend ((?type (uri (concat ?typeBase "Person"))))
>  9             (table unit))
> 10           (bgp (triple ?s ?p ?o)))))))
> 
> in this case, the second filter in within the scope of the ?type binding, but 
> that binding's contributing ?typeBase reference is outside of the scope of 
> the respective binding
> 
>> 
>> The query tries to bind variable ?type in the nested group based on variable 
>> ?typeBase, which is defined outside. In my understanding, this outer 
>> variable (?typeBase) should not be visible when executing the inner BIND, so 
>> this query would return the empty result?
>> 
>> 
>> 2b.) A slight variant of the previous one with a GroupOrUnionGraphPattern:
>> 
>> 
>> SELECT ?s ?type WHERE { 
>>  BIND("http://example.com/"; AS ?typeBase)
>>  {
>>    BIND(URI(CONCAT(?typeBase,"Person")) AS ?type)
>>    ?s ?p ?o
>>    FILTER(?o=?type)
>>  }
>>  UNION
>>  {
>>    BIND(URI(CONCAT(?typeBase,"Animal")) AS ?type)
>>    ?s ?p ?o
>>    FILTER(?o=?type)
>>  }
>> }
>> 
> 
>  1 (base <http://example/base/ <http://example/base/>>
>  2   (project (?s ?type)
>  3     (join
>  4       (extend ((?typeBase "http://example.com/ <http://example.com/>"))
>  5         (table unit))
>  6       (union
>  7         (filter (= ?o ?type)
>  8           (join
>  9             (extend ((?type (uri (concat ?typeBase "Person"))))
> 10               (table unit))
> 11             (bgp (triple ?s ?p ?o))))
> 12         (filter (= ?o ?type)
> 13           (join
> 14             (extend ((?type (uri (concat ?typeBase "Animal"))))
> 15               (table unit))
> 16             (bgp (triple ?s ?p ?o))))))))
> 
>> Also here I’d expect the empty result.
> 
> as would appear correct from the algebra expression.
> 
> best regards, from berlin,
> ---
> james anderson | ja...@dydra.com <mailto:ja...@dydra.com> | http://dydra.com 
> <http://dydra.com/>

Reply via email to