- From: Peter F. Patel-Schneider <pfpschneider@gmail.com>
- Date: Fri, 21 Apr 2017 16:22:19 -0700
- To: Andy Seaborne <andy@apache.org>, public-sparql-exists@w3.org
My understanding of the translation to the SPARQL algebra of SELECT ?this WHERE { ?this a ex:good . FILTER EXISTS { { SELECT * WHERE { } } BIND ( ?this AS ?that ) ?that a ex:bad } } is as follows. This is a SELECT expression, so look at 18.2.4.4 which (implicitly) says to first translate the pattern. So translate { ?this a ex:good . FILTER EXISTS { { SELECT * WHERE { } } BIND ( ?this AS ?that ) ?that a ex:bad } } This is a group graph pattern with a triple pattern and a filter. From 18.2.2.2 the filter is extracted and translated, with the EXISTS construct inside the filter translated. So translate { { SELECT * WHERE { } } BIND ( ?this AS ?that ) ?that a ex:bad } } This is a group graph pattern with a group graph pattern, a bind, and a triple pattern. From the part of 18.2.2.6 on group graph patterns the translation proceeds by first setting G = Z Then the group graph pattern is "any other form" so translate it. Translate { SELECT * WHERE { } } This gets to the part of 18.2.2.6 on group graph patterns, setting G = Z Then translate SELECT * WHERE { } ends up as Project(Z,{})) and then ToMultiset(Project(Z,{})) So G = Join(Z,ToMultiset(Project(Z,{}))) Now 18.2.2.8 simplifies this to G = ToMultiset(Project(Z,{})) Then the BIND is processed resulting in G = Extend(ToMultiset(Project(Z,{})),that,?this) Then the triple pattern is processed. From 18.2.2.5 the triple pattern is translated into a BGP, becoming something like BGP ( ?that rdf:type ex:bad . ) which is then added, resulting in G = Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .)) [Maybe simplification happens now but the result is the same.] So the filter becomes exists(Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .))) and is remembered for later. Then the group graph pattern portion of 18.2.2.6 proceeds by first setting G = Z Then the triple pattern is procesed, first from 18.2.2.5 being is translated into a BGP, becoming something like BGP( ?this rdf:type ex:good . ) and then G = Join(Z,BGP( ?this rdf:type ex:good . )) Filter addition from 18.2.2.7 results in Filter( exists(Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .))), Join(Z,BGP( ?this rdf:type ex:good . )) ) Simplification from 18.2.28 results in Filter( exists(Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .))) BGP( ?this rdf:type ex:good . ) ) Finally back to 18.2.4.4 for the outer SELECT to get PV = { this } Then on to 18.2.5 and 18.2.5.2 to get the final result of translation Project( ToList( Filter( exists(Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .))) , BGP( ?this rdf:type ex:good . ) ) ), {this} ) This is then evaluated. The evaluation of the exists does a Replace(PrjMap( Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .))), { (this, ex:i) } ) which becomes Replace(Join(Extend(ToMultiset(Project(Z,{})),that,?this),BGP(?that rdf:type ex:bad .)), { (this, ex:i) } ) and then Join(Extend(ToMultiset(Project(Join(Z,{{(this,ex:i)}},{}))),that,?this), Join(BGP(?that rdf:type ex:bad .),{{(this,ex:i)}})) and then Join(Extend({{}},that,?this), Join(BGP(?that rdf:type ex:bad .),{{(this,ex:i)}})) and then Join(BGP(?that rdf:type ex:bad .),{{(this,ex:i)}})) so the connection between ?this and ?that is broken. So simplification happened in two places, removing a Join(Z,...) just outside of the ToMultiSet and another around the outer BGP. The latter simplification is benign for Proposal B as the outer BGP is still there. However, the former simplification ends up with the Extend not seeing any value for the variable this which is a problem. peter On 04/21/2017 12:55 PM, Andy Seaborne wrote: > > > On 18/04/17 19:24, Peter F. Patel-Schneider wrote: >> [Second half only.] >> >>>> SELECT ?this WHERE { >>>> ?this a ex:good . >>>> FILTER EXISTS { { SELECT * WHERE { } } >>>> BIND ( ?this AS ?that ) >>>> ?that a ex:bad } } >>>> >>>> peter >>>> >>> >>> Simplification applies after syntax parsing, before evaluation. >>> >>> Inner "SELECT * {}" is a project of no variables of the unit table which is >>> left as-is. So no simplification. >>> >>> 18.2.4.4 >>> "The set PV is used later for projection." >>> >>> 18.2.5.2 Projection >>> """ >>> The set of projection variables, PV, was calculated in the processing of >>> SELECT expressions. >>> >>> M := Project(M, PV) >>> """ >>> >>> There is something to account for in SELECT * but it's not simplification. >>> >>> Andy >> >> >> As far as I can tell the inner select is translated (see last example in >> 18.2.3) as >> ToMultiSet(Project(Z,{})) >> >> The argument to EXISTS is translated (19.2.2.6) as >> Join( Extend(Join(Z,ToMultiSet(Project(Z,{}))),?that,?this), >> BGP(?that rdf:type ex:bad ) >> >> Simplification (18.2.2.8) then results in >> Join( Extend(ToMultiSet(Project(Z,{})),?that,?this), >> BGP(?that rdf:type ex:bad) ) > > and the Z is not in a join. > >> >> So the EXISTS is translated to >> exists( >> Join( Extend(ToMultiSet(Project(Z,{})),?that,?this), >> BGP(?that rdf:type ex:bad) ) ) >> >> Evaluation of the EXISTS with ?this mapped to ex:i proceeds by first doing >> the replacement, which ends up with something like >> Join( Extend(ToMultiSet(Project(Join(Z,{{?this,ex:i}}),{})),?that,?this), > ^^^ > Simplification happened after the query was parsed, as the algebra was created > and does not apply again during evaluation. > > It should be that > > project -> {{?this,ex:i}} > > except for the issue noted about "SELECT *" > > then BIND ( ?this AS ?that ) happens. > then join with BGP(?that rdf:type ex:bad) > >> Join(BGP(?that rdf:type ex:bad),{{?this,ex:i}}) ) >> This is evaluated to >> Join( Extend({{}},?that,?this), >> Join(BGP(?that rdf:type ex:bad),{{?this,ex:i}}) ) >> and then to >> Join( {{}}, >> Join(BGP(?that rdf:type ex:bad),{{?this,ex:i}}) ) >> >> The BIND then ends up not having any effect because ?this doesn't have a >> binding when it is evaluated, due simplification removing the place where >> the FILTER variables might have been joined in. > > I don't see where such a simplification is happening. > It's the fact SELECT * is calculated without regard to the current row. > > When "SELECT *" includes ?this, the inner BGP has the current row added. > > "SELECT * {}" does not have a join. > >> >> peter >> > > (prefix ((: <http://example/>) > (rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>)) > (project (?this) > (filter (exists > (join > (extend ((?that ?this)) > (project {} > (table unit))) > (bgp (triple ?that rdf:type <::ex:bad>)))) > (bgp (triple ?this rdf:type <::ex:good>))))) > > for the EXISTS part: > > (join > (extend ((?that ?this)) > (project {} > (table unit)) > (bgp (triple ?that rdf:type <::ex:bad>)) > ) > > BIND extends the graph pattern (syntactically - it's gathered up in > syntax->algebra) before it.
Received on Friday, 21 April 2017 23:22:56 UTC