Skip to content

Commit cdbd2a8

Browse files
committed
WIP: Sketch correlated EXISTS
1 parent fd7b58f commit cdbd2a8

File tree

1 file changed

+125
-208
lines changed

1 file changed

+125
-208
lines changed

spec/index.html

Lines changed: 125 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -8871,6 +8871,7 @@ <h5>Expand Syntax Forms</h5>
88718871
<p>Expand abbreviations for IRIs and triple patterns given in
88728872
Section&nbsp;<a href="#sparqlSyntax" class="sectionRef"></a>.</p>
88738873
</section>
8874+
88748875
<section id="sparqlCollectFilters">
88758876
<h5>Collect <code>FILTER</code> Elements</h5>
88768877
<p><code>FILTER</code> expressions apply to the whole group graph pattern in which they
@@ -8886,13 +8887,120 @@ <h5>Collect <code>FILTER</code> Elements</h5>
88868887
Let FS := empty set
88878888
For each form FILTER(expr) in the group graph pattern
88888889
In expr, replace NOT EXISTS{P} with fn:not(<a href="#defn_evalExists">exists(translate(P)))</a>
8889-
In expr, replace EXISTS{P} with <a href="#defn_evalExists">exists(translate(P))</a>
8890+
In expr, replace EXISTS{P} with prepare(EXISTS{P})
88908891
FS := FS ∪ {expr}
88918892
End
88928893
</pre>
88938894
<p>The set of filter expressions <code>FS</code> is <a href="#sparqlAddFilters">used
88948895
later</a>.</p>
8896+
8897+
<div>
8898+
<i>Prepare EXISTS and NOT EXISTS</i>
8899+
<p><b>prepare(EXISTS{P})</b></p>
8900+
8901+
<div class="ednote">
8902+
<p>@@ Scoping rule already done (grammar note).<br/>
8903+
Prepare FILTER for exists.
8904+
</p>
8905+
<ul>
8906+
<li>A1 = translate(P) without applying simplification</li>
8907+
<li>A2 = A1 rewritten to include access current binding</li>
8908+
<li>A3 = A2 Remapped hidden-scope variables (if we do that)</li>
8909+
</ul>
8910+
8911+
<div class="defn">
8912+
<div>
8913+
<b>Definition: Access to the current binding</b>
8914+
<p>
8915+
During <a href="#sparqlQuery">translation to the SPARQL algebra</a>
8916+
</p>
8917+
<pre>
8918+
Replace each occurence of `Y` in X where `Y` is one of
8919+
<a href="#sparqlTranslateBasicGraphPatterns">Basic Graph Pattern</a>,
8920+
<a href="#sparqlTranslatePathExpressions">Property Path Expression</a>,
8921+
<a href="#sparqlTranslateGraphPatterns">`Graph(Var, pattern)`</a>,
8922+
<a href="#https://www.w3.org/TR/sparql12-query/#sparqlTranslateGraphPatterns">Inline Data</a>
8923+
with `join(Y, BindingInScope())`.</pre>
8924+
</div>
8925+
<div class="note">
8926+
c.f. section <a href="#sparqlTranslateGraphPatterns">Translate Graph Patterns</a>
8927+
where an empty basic graph pattern start any
8928+
<a href="#rGroupGraphPattern">GroupGraphPattern</a>.
8929+
It happens before the <a href="#sparqlSimplification">simplification step</a>.
8930+
</div>
8931+
</div>
8932+
8933+
<div class="ednote" id="note-BindingInScope">
8934+
<p>
8935+
One way to provide `BindingInScope` is to change `eval` to also have the current row
8936+
as an argument or a "null" token. . Normally this the "null" token. This would be set in
8937+
eval-filter.
8938+
</p>
8939+
<p>
8940+
Another way is to have a global (to the execution) variable. In eval-exists, the
8941+
old value is recorded, the global set to the new value, and reset on exit - this forms a
8942+
stack for nested EXISTS.
8943+
</p>
8944+
<p>
8945+
Modifing `eval` is better prepartion for other correlted operations.<br/>
8946+
A current-row stack in EXISTS isless intrusive.
8947+
</p>
8948+
</div>
8949+
8950+
<div class="defn">
8951+
<b>Definition: <span id="defn_projmap">Projection Expression Variable Remapping</span></b>
8952+
<p>
8953+
For a projection algebra operation #sparqlProjection `Project(A, PV)` acting on algreg express `A` and with set of variables `PV`, define
8954+
a partial mapping `F` from
8955+
`<a href="#sparqlQueryVariables">V</a>`,
8956+
the set of all variables, to `V` where:
8957+
</p>
8958+
<pre>F(v) = v1 if v is in PV, where v1 is a fresh variable
8959+
F(v) = v if v is not in PV</pre>
8960+
<p>
8961+
Define the Projection Expression Variable Remapping `ProjectMap(P, PV)`
8962+
</p>
8963+
<pre>ProjectMap(Project(A, PV)) = Project(A1, PV)
8964+
where A1 is the result of applying F
8965+
to every variable mentioned in A.</pre>
8966+
<p>
8967+
The Projection Expression Variable Remapping yields an algrebra expression that
8968+
evaluates to the same results as the Project argument. No variable of `ProjectMap(Project(A, PV))`
8969+
that is not in `PV` is mentioned anywhere else in the algebra expression for the query.
8970+
</p>
8971+
</div>
8972+
<p>This process is applied throughout the graph pattern of <code>EXISTS</code>:</p>
8973+
<div class="defn">
8974+
<b>Definition: <span id="defn_varrename">Variable Remapping</span></b>
8975+
<p>
8976+
For any algebra expression `X`, define the Variable Remapping `PrjMap(X)`
8977+
of algebra expression `X`:
8978+
</p>
8979+
<pre>PrjMap(X) = replace all project operations Project(P, PV)
8980+
with ProjectMap(P, PV) for each projection in X.</pre>
8981+
</div>
8982+
<p>
8983+
The outcome of `PrjMap` is independent of the order of replacement
8984+
(e.g. bottom-up or top-down).
8985+
Replacements may happen several times, depending on recursive order
8986+
but each time a replacement is made, the variable not used anywhere else.
8987+
</p>
8988+
8989+
<div class="note">
8990+
<p>
8991+
A variable inside a project expression that is not in the variables projected
8992+
is not affected by the values insertion operation because it is renamed apart.
8993+
</p>
8994+
<p>
8995+
This operation is as part of the <a href="#sparqlQuery">translation to the SPARQL
8996+
algebra</a>.
8997+
</p>
8998+
</div>
8999+
</div>
9000+
</div>
88959001
</section>
9002+
9003+
88969004
<section id="sparqlTranslatePathExpressions">
88979005
<h5>Translate Property Path Expressions</h5>
88989006
<p>The following table gives the translation
@@ -9149,14 +9257,17 @@ <h5>Filters of Group</h5>
91499257
</section>
91509258
<section id="sparqlSimplification">
91519259
<h5>Simplification step</h5>
9152-
<p>Some groups of one graph pattern become <a href="#defn_absJoin"
9153-
class="absOp">Join</a>(|Z|, |A|), where |Z| is the empty basic graph
9260+
<p class="ednote">
9261+
@@ Move out of the general `translate()` process and
9262+
perform once after top level translation only
9263+
</p>
9264+
<p>Some groups of one graph pattern become
9265+
<a href="#defn_absJoin" class="absOp">Join</a>(|Z|, |A|), where |Z| is the empty basic graph
91549266
pattern (which is the empty set). These are replaced by |A|. The empty
91559267
graph pattern |Z| is the identity for join:</p>
91569268
<pre class="code nohighlight">
91579269
Replace <a href="#defn_absJoin" class="absOp">Join</a>(<var>Z</var>, <var>A</var>) by <var>A</var>
9158-
Replace <a href="#defn_absJoin" class="absOp">Join</a>(<var>A</var>, <var>Z</var>) by <var>A</var>
9159-
</pre>
9270+
Replace <a href="#defn_absJoin" class="absOp">Join</a>(<var>A</var>, <var>Z</var>) by <var>A</var></pre>
91609271
</section>
91619272
</section>
91629273
<section id="sparqlAlgebraExamples">
@@ -10464,6 +10575,12 @@ <h3>Evaluation Semantics</h3>
1046410575
</div>
1046510576
<div class="defn">
1046610577
<p><b>Definition: <span id="defn_evalFilter">Evaluation of Filter</span></b></p>
10578+
10579+
<p class="ednote">@@ Make current μ available. Or use current language in Exist.
10580+
Long term: change eval() to be arity three - 3rd argument is "current row".
10581+
<a href="="note-BindingInScope">editors note</a>.
10582+
</p>
10583+
1046710584
<p><a href="#defn_eval" class="evalFct">eval</a>( |D|(|G|), <a href="#defn_absFilter" class="absOp">Filter</a>(|F|, |P|) ) = <a href="#defn_algFilter" class="algFct">Filter</a>( |F|, <a href="#defn_eval" class="evalFct">eval</a>(|D|(|G|), |P|), |D|(|G|) )</p>
1046810585
</div>
1046910586
<p>'substitute' is a filter function in support of the evaluation of
@@ -10479,6 +10596,9 @@ <h3>Evaluation Semantics</h3>
1047910596
</div>
1048010597
<div class="defn">
1048110598
<p><b>Definition: <span id="defn_evalExists">Evaluation of Exists</span></b></p>
10599+
10600+
<p class="ednote">@@ Update</p>
10601+
1048210602
<p>Let <var>μ</var> be the current solution mapping for a filter and |P| a graph pattern:</p>
1048310603
<blockquote>
1048410604
The value exists(|P|), given |D|(|G|) is true if and only if <a href="#defn_eval" class="evalFct">eval</a>( |D|(|G|), substitute(|P|, <var>μ</var>)) is
@@ -10602,209 +10722,6 @@ <h3>Evaluation Semantics</h3>
1060210722
<a href="#defn_eval" class="evalFct">eval</a>( |D|(|G|), <a href="#defn_absSlice" class="absOp">Slice</a>(|L|, |start|, |length|) ) = <a href="#defn_algSlice" class="algFct">Slice</a>( <a href="#defn_eval" class="evalFct">eval</a>(|D|(|G|), |L|), |start|, |length| )
1060310723
</p>
1060410724
</div>
10605-
10606-
<!-- ValuesInsertion -->
10607-
<section>
10608-
<h3>Values Insertion and `EXISTS`</h3>
10609-
<div class="ednote">
10610-
<p>The following subsections contain draft material for a revised
10611-
"`exists`" operation.
10612-
</p>
10613-
<p>
10614-
Background: <a href="https://github.com/w3c/sparql-dev/blob/main/SEP/SEP-0007/sep-0007.md">SPARQL CG SEP-0007</a>
10615-
</p>
10616-
</div>
10617-
<section>
10618-
<h4>Syntax Restriction</h4>
10619-
<p><i>Additional [[[#sparqlGrammar]]] note:</i></p>
10620-
<blockquote>
10621-
Any variable that is assigned to in the graph pattern of `EXISTS`/`NOT EXISTS` must not be in-scope.
10622-
This applies to `BIND`, variables introduced by `AS` in a `SELECT` clause, variables in a `VALUES`
10623-
clause, and variables introduced by `AS` in `GROUP BY`.
10624-
</blockquote>
10625-
<p>
10626-
Extend the "in-scope" rules to include the possible
10627-
variables that are in-scope for the current row:
10628-
</p>
10629-
<table style="border-collapse: collapse; border-color: #000000; border-spacing:5px; border-width: 1px">
10630-
<tbody>
10631-
<tr>
10632-
<th>Syntax Form</th>
10633-
<th>In-scope variables</th>
10634-
</tr>
10635-
<tr>
10636-
<td>`EXISTS` and `NOT EXISTS` filters </td>
10637-
<td><code>v</code> is in-scope if it is in-scope for the pattern to which the `FILTER` is applied.
10638-
</td>
10639-
</tr>
10640-
</tbody>
10641-
</table>
10642-
<div class="note">
10643-
<p>
10644-
This restriction means that inserted values
10645-
do not conflict with values assigned to variables within the pattern.
10646-
</p>
10647-
<p>
10648-
This operation is performed as part of query parsing.
10649-
</p>
10650-
</div>
10651-
</section>
10652-
<section>
10653-
<h4>Remapping</h4>
10654-
<p>
10655-
Remapping ensures that a variable name used inside a project expression,
10656-
but which is not part of the results of the evaluation of the project expression,
10657-
does not coincide with a variable mentioned anywhere else in the
10658-
algebra expression of a query.
10659-
</p>
10660-
<p>
10661-
Renaming these variables does not change the results of evaluating
10662-
the project expresssion.
10663-
</p>
10664-
<div class="defn">
10665-
<b>Definition: <span id="defn_projmap">Projection Expression Variable Remapping</span></b>
10666-
<p>
10667-
For a <a href="#sparqlProjection">projection algebra operation</a>
10668-
`Project(A, PV)` acting on algebra expression `A` and with set of variables `PV`,
10669-
define a mapping `F` from `V`,
10670-
<a href="#sparqlQueryVariables">the set of all variables</a>,
10671-
to `V` where:
10672-
</p>
10673-
<pre>F(v) = v1 if v is not in PV, where v1 is a fresh variable
10674-
F(v) = v if v is in PV</pre>
10675-
<p>
10676-
Define the Projection Expression Variable Remapping `ProjectMap(P, PV)`
10677-
</p>
10678-
<pre>ProjectMap(Project(A, PV)) = Project(A1, PV)
10679-
where A1 is the result of applying F
10680-
to every variable mentioned in A.
10681-
</pre>
10682-
<p>
10683-
The Projection Expression Variable Remapping yields an algrebra expression that
10684-
evaluates to the same results as the Project argument. No variable of `ProjectMap(Project(A, PV))`
10685-
that is not in `PV` is mentioned anywhere else in the algebra expression for the query.
10686-
</p>
10687-
</div>
10688-
<p>This process is applied throughout the graph pattern of <code>EXISTS</code>:</p>
10689-
<div class="defn">
10690-
<b>Definition: <span id="defn_varrename">Variable Remapping</span></b>
10691-
<p>
10692-
For any algebra expression `X`, define the Variable Remapping `PrjMap(X)`
10693-
of algebra expression `X`:
10694-
</p>
10695-
<pre>PrjMap(X) = replace all project operations Project(P, PV)
10696-
with ProjectMap(Project(A, PV), PV) for each projection in X.</pre>
10697-
</div>
10698-
<p>
10699-
The outcome of `PrjMap` is independent of the order of replacement
10700-
(whether "bottom-up" or "top-down") order.
10701-
Replacements may happen several times, depending on recursive order
10702-
but each time a replacement is made, the variable not used anywhere else.
10703-
</p>
10704-
10705-
<div class="note">
10706-
<p>
10707-
A variable inside a project expression that is not in the variables projected
10708-
is not affected by the values insertion operation because it is renamed apart.
10709-
</p>
10710-
<p>
10711-
This operation is as part of the <a href="#sparqlQuery">translation to the SPARQL
10712-
algebra</a>.
10713-
</p>
10714-
</div>
10715-
</section>
10716-
<section>
10717-
<h4>Values Insertion</h4>
10718-
<p>
10719-
Alternative 1: rewrite the algebra during
10720-
<a href="#sparqlQuery">translation to the SPARQL algebra</a>
10721-
to include a function that evaluates to the current row.
10722-
</p>
10723-
10724-
<div class="defn">
10725-
<div>
10726-
<b>Definition: <span id="defn_correlate">Values In Scope</span></b>
10727-
<p>
10728-
Define the function `BindingInScope()`.
10729-
Evaluation of `BindingInScope()` results in a table of one row,
10730-
being the current binding of the enclosing filter.
10731-
</p>
10732-
</div>
10733-
<p class="ednote">Need to define `BindingInScope`</p>
10734-
</div>
10735-
10736-
<div class="defn">
10737-
<div>
10738-
<b>Definition: Access to the current binding</b>
10739-
<p>
10740-
During <a href="#sparqlQuery">translation to the SPARQL algebra</a>
10741-
</p>
10742-
<p class="ednote">Define putting in the `BindingInScope` operator</p>
10743-
<pre>
10744-
Replace each occurence of Y where Y is one of
10745-
<a href="#sparqlTranslateBasicGraphPatterns">Basic Graph Pattern</a>,
10746-
<a href="#sparqlTranslatePathPatterns">Property Path Patterns</a>,
10747-
<a href="#sparqlTranslateGraphPatterns">Graph(Var, pattern)</a>,
10748-
<a href="#https://www.w3.org/TR/sparql12-query/#sparqlTranslateGraphPatterns">Inline Data</a>
10749-
with join(Y, BindingInScope()).</pre>
10750-
</div>
10751-
<div class="note">
10752-
c.f. section <a href="#sparqlTranslateGraphPatterns">Translate Graph Patterns</a>
10753-
where an empty basic graph pattern start any
10754-
<a href="#rGroupGraphPattern">GroupGraphPattern</a>.
10755-
It happens before the <a href="#sparqlSimplification">simplification step</a>.
10756-
</div>
10757-
</div>
10758-
10759-
<div class="example">
10760-
<p>
10761-
Examples
10762-
</p>
10763-
</div>
10764-
10765-
<p>
10766-
Alternative 2: rewrite the algebra during execution. This corresponds to the
10767-
<a href="https://github.com/w3c/sparql-dev/blob/main/SEP/SEP-0007/sep-0007.md">original SEP-0007 proposal</a>.
10768-
</p>
10769-
<div class="defn">
10770-
<div>
10771-
<b>Definition: <span id="defn_insertvalues">Insert Values</span></b>
10772-
<p>
10773-
Define the function `InsertValues(X, μ)`
10774-
</p>
10775-
<pre>Let Table(μ) = { μ } and multiplicity( μ | Table(μ) = { μ } ) = 1
10776-
10777-
Replace each occurence of Y in X where Y is one of
10778-
<a href="#sparqlTranslateBasicGraphPatterns">Basic Graph Pattern</a>,
10779-
<a href="#sparqlTranslatePathPatterns">Property Path Patterns</a>,
10780-
<a href="#sparqlTranslateGraphPatterns">Graph(Var, pattern)</a>,
10781-
<a href="#https://www.w3.org/TR/sparql12-query/#sparqlTranslateGraphPatterns">Inline Data</a>
10782-
with join(Y, Table(μ)).</pre>
10783-
10784-
</div>
10785-
</div>
10786-
</section>
10787-
10788-
<section>
10789-
<h4>Evaluation of EXISTS</h4>
10790-
<div class="defn">
10791-
<b>Definition: <span id="x-defn_evalExists">Evaluation of Exists</span></b>
10792-
<p>
10793-
Let `μ` be the current solution mapping for a filter, and `X` a graph pattern,
10794-
define the Evaluation of Exists `exists(X)`
10795-
</p>
10796-
<p class="ednote">
10797-
@@ Set up the current row for `BindingdInScope`.
10798-
</p>
10799-
<pre>exists(X) = true
10800-
if eval( D(G), μ)
10801-
is a non-empty solution sequence.
10802-
exists(X) = false otherwise</pre>
10803-
</div>
10804-
</section>
10805-
</section>
10806-
<!-- ValuesInsertion -->
10807-
1080810725
</section>
1080910726

1081010727
<section id="sparqlBGPExtend">

0 commit comments

Comments
 (0)