- From: Andy Seaborne <andy@apache.org>
- Date: Thu, 17 Nov 2016 13:40:14 +0000
- To: public-sparql-exists@w3.org
Here is a attempt to define the replacement process for proposal B (deep
binding injection). This message is the descriptive version, the next
message is a more formal description.
Suggestions for improving the definitions very welcome! (I am a little
out of practice writing definitions...)
This definition applies to algebra expressions in EXISTS for legal
SPARQL queries. The rules for a SPARQL query preclude certain algebra
expressions like "extend" (i.e BIND) of a variable which is also in a
BGP that "extend" applies to.
The approach is to alter the places where variables get bound by joining
the bindings for the solution mapping being filtered (the "current
row"). This restricts the range of values a variable can take to just
the value in the solution mapping being filtered. (FILTER sameTerm
would do the same thing.)
Assignment (an "AS") to a variable which is in-scope for the FILTER is
not allowed. Any potential variables in a "current row", are considered
in-scope for the EXIST expression.
18.2.1 Variable Scope
https://www.w3.org/TR/sparql11-query/#variableScope
Putting all the variables of the current row into the replacement, not
just the ones in a replaced BGP makes FILTERS with variables from the
current row work:
{
?x :predicate ?y
FILTER EXISTS { ?x :predicate ?v . FILTER ( ?v < ?y ) }
}
then if the current row is: ?x=<http://example/resource>, ?y=123
EXISTS {
{ ?x :predicate ?v .
VALUES(?x ?y) { (<http://example/resource> 123) }
}
FILTER ( ?v < ?y )
}
except this is done on the algebra not the syntax.
This process works for compound forms:
{
?x :predicate ?y
FILTER EXISTS {
GRAPH <http://example/graph> {
?x :predicate ?v .
FILTER ( ?v < ?y ) }
}
}
{
?x :pred ?y
FILTER EXISTS {
{
?x :predicate1 ?v .
FILTER ( ?v < ?y ) }
} UNION {
?x :predicate2 ?v .
FILTER ( ?v < ?y ) }
}
}
It must deal with uses of the same variable name inside sub-SELECT. A
sub-SELECT introduces projection so it can hide variables. The name of
such variables inside the projection does not matter - systematic
renaming of any non-projected variable does not change the results.
SELECT * {
?x :predicate ?y
{ SELECT ?x
{ ?x :predicate ?v .
FILTER(?v < 123)
} }
}
the "?v" is not part of the results, nor can be joined with a variable
outside the sub-select because only "?x" is in the projection.
This has the same results:
SELECT * {
?x :predicate ?y
{ SELECT ?x
{ ?x :predicate ?Z .
FILTER(?Z < 123)
} }
}
The proposal is to rename these hidden variables so they use different
names to the current row being filtered.
NB This has a consequence that if a query wishes to filter on a variable
from the current row, it must be in the projection.
This could be changed by modifying the definition of renaming in the
other message.
Then replace any form "x" which is a BGP, path or "GRAPH ?g" with
join(x, current row)
"AS ?var" where ?var comes from any current row (the set of varables
in-scope by the current scope rules at the FILTER) is not allowed.
Blank nodes are treated as constants. This is in the algebra where blank
nodes in solution mappings are not acting as variables.
Current unclear:
(this is an example from SHACL, not that it will necessarily remain this
query and is required to be defined in SPARQL):
4.3.2 sh:maxCount
SELECT $this
WHERE {
$this $PATH ?value .
}
GROUP BY $this
HAVING (COUNT(DISTINCT ?value) > $maxCount)
so for an EXISTS filter:
EXISTS {
SELECT $this {
$this $PATH ?value .
}
GROUP BY $this
HAVING (COUNT(DISTINCT ?value) > $maxCount)
(Peter - in proposal A, the initial(t) is outside the HAVING)
There is no place currently to inject the $maxCount.
Pretending there is empty BGP at the start works in this similar form:
SELECT $this {
BIND(1 AS $dummy)
{ SELECT $this (COUNT(DISTINCT ?value) AS ?X) {
$this $PATH ?value .
}
GROUP BY $this
}
FILTER(?X > $maxCount)
}
Andy
Received on Thursday, 17 November 2016 13:40:49 UTC