- 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