Re: Visibility of variables in nested Group(OrUnion)GraphPatterns

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 <james@dydra.com> wrote:
> 
> good afternoon;
> 
>> On 2015-08-27, at 13:27, Michael Schmidt <ms@metaphacts.com <mailto:ms@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 | james@dydra.com <mailto:james@dydra.com> | http://dydra.com <http://dydra.com/>

Received on Monday, 31 August 2015 12:08:21 UTC