This is completely unrelated to any recent questions about the rule
engine and builtins. :)  I've got this data:


@prefix : <http://example.org/> .
:a :atIndex 0 .
:b :atIndex 1 .
:c :atIndex 2 .
:d :atIndex 3 .


Here's a query that finds an ?element at an ?index, binds ?index2 to
?index - 1, and optionally selects an ?element2 that is at ?index2.


prefix : <http://example.org/>
select ?element ?index ?element2 ?index2 where {
  ?element :atIndex ?index .
  BIND( ?index - 1 as ?index2 )
  OPTIONAL {
    ?element2 :atIndex ?index2 .
  }
}
order by ?index


The results are as expected:


$ arq --data data.n3 --query query.sparql
---------------------------------------
| element | index | element2 | index2 |
=======================================
| :a      | 0     |          | -1     |
| :b      | 1     | :a       | 0      |
| :c      | 2     | :b       | 1      |
| :d      | 3     | :c       | 2      |
---------------------------------------


Moving the BIND into the OPTIONAL, i.e.,


prefix : <http://example.org/>
select ?element ?index ?element2 ?index2 where {
  ?element :atIndex ?index .
  OPTIONAL {
    BIND( ?index - 1 as ?index2 )
    ?element2 :atIndex ?index2 .
  }
}
order by ?index


produces lots more results;  it seems that there's no constraint on
the ?index within the OPTIONAL, so ?index2 can range over everything.

$ arq --data data.n3 --query query.sparql
---------------------------------------
| element | index | element2 | index2 |
=======================================
| :a      | 0     | :a       | 0      |
| :a      | 0     | :b       | 1      |
| :a      | 0     | :c       | 2      |
| :a      | 0     | :d       | 3      |
| :b      | 1     | :a       | 0      |
| :b      | 1     | :b       | 1      |
| :b      | 1     | :c       | 2      |
| :b      | 1     | :d       | 3      |
| :c      | 2     | :a       | 0      |
| :c      | 2     | :b       | 1      |
| :c      | 2     | :c       | 2      |
| :c      | 2     | :d       | 3      |
| :d      | 3     | :a       | 0      |
| :d      | 3     | :b       | 1      |
| :d      | 3     | :c       | 2      |
| :d      | 3     | :d       | 3      |
---------------------------------------


Now, using a FILTER in the OPTIONAL:


prefix : <http://example.org/>

select ?element ?index ?element2 ?index2 where {
  ?element :atIndex ?index .
  OPTIONAL {
    FILTER( ?index - 1 = ?index2 )
    ?element2 :atIndex ?index2 .
  }
}
order by ?index


produces results that actually show that ?index2 is constrained, and
are almost the same the as the first query (except that the case where
?index2 is -1 doesn't occur):


$ arq --data data.n3 --query query.sparql
---------------------------------------
| element | index | element2 | index2 |
=======================================
| :a      | 0     |          |        |
| :b      | 1     | :a       | 0      |
| :c      | 2     | :b       | 1      |
| :d      | 3     | :c       | 2      |
---------------------------------------


Is this expected?  Why can't the BIND inside the optional reference
the outer binding of ?index?  In the spec, I do read about the
difference of scope between, e.g., FILTER NOT EXISTS { ?n ... } and
MINUS { ?n ... }, where in the former, ?n can refer to an outer
binding, but for the latter, it cannot.  I think that 18.2.1 Variable
Scope [1] is probably relevant here, but I'm not sure how to get an
answer from it.

Thanks in advance!
//JT

[1] http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#variableScope

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Reply via email to