Skip to content

Commit 203391e

Browse files
committed
WIP: Sketch correlated EXISTS
1 parent 2364961 commit 203391e

File tree

1 file changed

+123
-208
lines changed

1 file changed

+123
-208
lines changed

spec/index.html

Lines changed: 123 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -8886,6 +8886,7 @@ <h5>Expand Syntax Forms</h5>
88868886
<p>Expand abbreviations for IRIs and triple patterns given in
88878887
Section&nbsp;<a href="#sparqlSyntax" class="sectionRef"></a>.</p>
88888888
</section>
8889+
88898890
<section id="sparqlCollectFilters">
88908891
<h5>Collect <code>FILTER</code> Elements</h5>
88918892
<p><code>FILTER</code> expressions apply to the whole group graph pattern in which they
@@ -8901,13 +8902,120 @@ <h5>Collect <code>FILTER</code> Elements</h5>
89018902
Let FS := empty set
89028903
For each form FILTER(expr) in the group graph pattern
89038904
In expr, replace NOT EXISTS{P} with fn:not(<a href="#defn_evalExists">exists(translate(P)))</a>
8904-
In expr, replace EXISTS{P} with <a href="#defn_evalExists">exists(translate(P))</a>
8905+
In expr, replace EXISTS{P} with prepare(EXISTS{P})
89058906
FS := FS ∪ {expr}
89068907
End
89078908
</pre>
89088909
<p>The set of filter expressions <code>FS</code> is <a href="#sparqlAddFilters">used
89098910
later</a>.</p>
8911+
8912+
<div>
8913+
<i>Prepare EXISTS and NOT EXISTS</i>
8914+
<p><b>prepare(EXISTS{P})</b></p>
8915+
8916+
<div class="ednote">
8917+
<p>@@ Scoping rule already done (grammar note).<br/>
8918+
Prepare FILTER for exists.
8919+
</p>
8920+
<ul>
8921+
<li>A1 = translate(P) without applying simplification</li>
8922+
<li>A2 = A1 rewritten to include access current binding</li>
8923+
<li>A3 = A2 Remapped hidden-scope variables (if we do that)</li>
8924+
</ul>
8925+
8926+
<div class="defn">
8927+
<div>
8928+
<b>Definition: Access to the current binding</b>
8929+
<p>
8930+
During <a href="#sparqlQuery">translation to the SPARQL algebra</a>
8931+
</p>
8932+
<pre>
8933+
Replace each occurence of `Y` in X where `Y` is one of
8934+
<a href="#sparqlTranslateBasicGraphPatterns">Basic Graph Pattern</a>,
8935+
<a href="#sparqlTranslatePathExpressions">Property Path Expression</a>,
8936+
<a href="#sparqlTranslateGraphPatterns">Graph(Var, pattern)</a>,
8937+
<a href="#rInlineData">Inline Data</a>
8938+
with join(Y, BindingInScope()) .</pre>
8939+
</div>
8940+
<div class="note">
8941+
c.f. section <a href="#sparqlTranslateGraphPatterns">Translate Graph Patterns</a>
8942+
where an empty basic graph pattern start any
8943+
<a href="#rGroupGraphPattern">GroupGraphPattern</a>.
8944+
It happens before the <a href="#sparqlSimplification">simplification step</a>.
8945+
</div>
8946+
</div>
8947+
8948+
<div class="ednote" id="note-BindingInScope">
8949+
<p>
8950+
One way to provide `BindingInScope` is to change `eval` to also have the current row
8951+
as an argument or a "null" token. . Normally this the "null" token. This would be set in
8952+
eval-filter.
8953+
</p>
8954+
<p>
8955+
Another way is to have a global (to the execution) variable. In eval-exists, the
8956+
old value is recorded, the global set to the new value, and reset on exit - this forms a
8957+
stack for nested EXISTS.
8958+
</p>
8959+
<p>
8960+
Modifing `eval` is better prepartion for other correlted operations.<br/>
8961+
A current-row stack in EXISTS isless intrusive.
8962+
</p>
8963+
</div>
8964+
8965+
<div class="defn">
8966+
<b>Definition: <span id="defn_projmap">Projection Expression Variable Remapping</span></b>
8967+
<p>
8968+
For a projection algebra operation #sparqlProjection `Project(A, PV)` acting on algreg express `A` and with set of variables `PV`, define
8969+
a partial mapping `F` from
8970+
`<a href="#sparqlQueryVariables">V</a>`,
8971+
the set of all variables, to `V` where:
8972+
</p>
8973+
<pre>F(v) = v1 if v is in PV, where v1 is a fresh variable
8974+
F(v) = v if v is not in PV</pre>
8975+
<p>
8976+
Define the Projection Expression Variable Remapping `ProjectMap(P, PV)`
8977+
</p>
8978+
<pre>ProjectMap(Project(A, PV)) = Project(A1, PV)
8979+
where A1 is the result of applying F
8980+
to every variable mentioned in A.</pre>
8981+
<p>
8982+
The Projection Expression Variable Remapping yields an algrebra expression that
8983+
evaluates to the same results as the Project argument. No variable of `ProjectMap(Project(A, PV))`
8984+
that is not in `PV` is mentioned anywhere else in the algebra expression for the query.
8985+
</p>
8986+
</div>
8987+
<p>This process is applied throughout the graph pattern of <code>EXISTS</code>:</p>
8988+
<div class="defn">
8989+
<b>Definition: <span id="defn_varrename">Variable Remapping</span></b>
8990+
<p>
8991+
For any algebra expression `X`, define the Variable Remapping `PrjMap(X)`
8992+
of algebra expression `X`:
8993+
</p>
8994+
<pre>PrjMap(X) = replace all project operations Project(P, PV)
8995+
with ProjectMap(P, PV) for each projection in X.</pre>
8996+
</div>
8997+
<p>
8998+
The outcome of `PrjMap` is independent of the order of replacement
8999+
(e.g. bottom-up or top-down).
9000+
Replacements may happen several times, depending on recursive order
9001+
but each time a replacement is made, the variable not used anywhere else.
9002+
</p>
9003+
9004+
<div class="note">
9005+
<p>
9006+
A variable inside a project expression that is not in the variables projected
9007+
is not affected by the values insertion operation because it is renamed apart.
9008+
</p>
9009+
<p>
9010+
This operation is as part of the <a href="#sparqlQuery">translation to the SPARQL
9011+
algebra</a>.
9012+
</p>
9013+
</div>
9014+
</div>
9015+
</div>
89109016
</section>
9017+
9018+
89119019
<section id="sparqlTranslatePathExpressions">
89129020
<h5>Translate Property Path Expressions</h5>
89139021
<p>The following table gives the translation
@@ -9164,14 +9272,17 @@ <h5>Filters of Group</h5>
91649272
</section>
91659273
<section id="sparqlSimplification">
91669274
<h5>Simplification step</h5>
9167-
<p>Some groups of one graph pattern become <a href="#defn_absJoin"
9168-
class="absOp">Join</a>(|Z|, |A|), where |Z| is the empty basic graph
9275+
<p class="ednote">
9276+
@@ Move out of the general `translate()` process and
9277+
perform once after top level translation only
9278+
</p>
9279+
<p>Some groups of one graph pattern become
9280+
<a href="#defn_absJoin" class="absOp">Join</a>(|Z|, |A|), where |Z| is the empty basic graph
91699281
pattern (which is the empty set). These are replaced by |A|. The empty
91709282
graph pattern |Z| is the identity for join:</p>
91719283
<pre class="code nohighlight">
91729284
Replace <a href="#defn_absJoin" class="absOp">Join</a>(<var>Z</var>, <var>A</var>) by <var>A</var>
9173-
Replace <a href="#defn_absJoin" class="absOp">Join</a>(<var>A</var>, <var>Z</var>) by <var>A</var>
9174-
</pre>
9285+
Replace <a href="#defn_absJoin" class="absOp">Join</a>(<var>A</var>, <var>Z</var>) by <var>A</var></pre>
91759286
</section>
91769287
</section>
91779288
<section id="sparqlAlgebraExamples">
@@ -10490,6 +10601,10 @@ <h3>Evaluation Semantics</h3>
1049010601
<div class="defn">
1049110602
<p><b>Definition: <span id="defn_evalFilter">Evaluation of Filter</span></b></p>
1049210603
<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>
10604+
<p class="ednote">@@ Make current μ available. Or use current language in Exist.
10605+
Long term: change eval() to be arity three - 3rd argument is "current row".
10606+
<a href="note-BindingInScope">editors note</a>.
10607+
</p>
1049310608
</div>
1049410609
<p>'substitute' is a filter function in support of the evaluation of
1049510610
<a href="#func-filter-exists"><code>EXISTS</code>
@@ -10504,6 +10619,9 @@ <h3>Evaluation Semantics</h3>
1050410619
</div>
1050510620
<div class="defn">
1050610621
<p><b>Definition: <span id="defn_evalExists">Evaluation of Exists</span></b></p>
10622+
10623+
<p class="ednote">@@ Update</p>
10624+
1050710625
<p>Let <var>μ</var> be the current solution mapping for a filter and |P| a graph pattern:</p>
1050810626
<blockquote>
1050910627
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
@@ -10627,209 +10745,6 @@ <h3>Evaluation Semantics</h3>
1062710745
<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| )
1062810746
</p>
1062910747
</div>
10630-
10631-
<!-- ValuesInsertion -->
10632-
<section>
10633-
<h3>Values Insertion and `EXISTS`</h3>
10634-
<div class="ednote">
10635-
<p>The following subsections contain draft material for a revised
10636-
"`exists`" operation.
10637-
</p>
10638-
<p>
10639-
Background: <a href="https://github.com/w3c/sparql-dev/blob/main/SEP/SEP-0007/sep-0007.md">SPARQL CG SEP-0007</a>
10640-
</p>
10641-
</div>
10642-
<section>
10643-
<h4>Syntax Restriction</h4>
10644-
<p><i>Additional [[[#sparqlGrammar]]] note:</i></p>
10645-
<blockquote>
10646-
Any variable that is assigned to in the graph pattern of `EXISTS`/`NOT EXISTS` must not be in-scope.
10647-
This applies to `BIND`, variables introduced by `AS` in a `SELECT` clause, variables in a `VALUES`
10648-
clause, and variables introduced by `AS` in `GROUP BY`.
10649-
</blockquote>
10650-
<p>
10651-
Extend the "in-scope" rules to include the possible
10652-
variables that are in-scope for the current row:
10653-
</p>
10654-
<table style="border-collapse: collapse; border-color: #000000; border-spacing:5px; border-width: 1px">
10655-
<tbody>
10656-
<tr>
10657-
<th>Syntax Form</th>
10658-
<th>In-scope variables</th>
10659-
</tr>
10660-
<tr>
10661-
<td>`EXISTS` and `NOT EXISTS` filters </td>
10662-
<td><code>v</code> is in-scope if it is in-scope for the pattern to which the `FILTER` is applied.
10663-
</td>
10664-
</tr>
10665-
</tbody>
10666-
</table>
10667-
<div class="note">
10668-
<p>
10669-
This restriction means that inserted values
10670-
do not conflict with values assigned to variables within the pattern.
10671-
</p>
10672-
<p>
10673-
This operation is performed as part of query parsing.
10674-
</p>
10675-
</div>
10676-
</section>
10677-
<section>
10678-
<h4>Remapping</h4>
10679-
<p>
10680-
Remapping ensures that a variable name used inside a project expression,
10681-
but which is not part of the results of the evaluation of the project expression,
10682-
does not coincide with a variable mentioned anywhere else in the
10683-
algebra expression of a query.
10684-
</p>
10685-
<p>
10686-
Renaming these variables does not change the results of evaluating
10687-
the project expresssion.
10688-
</p>
10689-
<div class="defn">
10690-
<b>Definition: <span id="defn_projmap">Projection Expression Variable Remapping</span></b>
10691-
<p>
10692-
For a <a href="#sparqlProjection">projection algebra operation</a>
10693-
`Project(A, PV)` acting on algebra expression `A` and with set of variables `PV`,
10694-
define a mapping `F` from `V`,
10695-
<a href="#sparqlQueryVariables">the set of all variables</a>,
10696-
to `V` where:
10697-
</p>
10698-
<pre>F(v) = v1 if v is not in PV, where v1 is a fresh variable
10699-
F(v) = v if v is in PV</pre>
10700-
<p>
10701-
Define the Projection Expression Variable Remapping `ProjectMap(P, PV)`
10702-
</p>
10703-
<pre>ProjectMap(Project(A, PV)) = Project(A1, PV)
10704-
where A1 is the result of applying F
10705-
to every variable mentioned in A.
10706-
</pre>
10707-
<p>
10708-
The Projection Expression Variable Remapping yields an algrebra expression that
10709-
evaluates to the same results as the Project argument. No variable of `ProjectMap(Project(A, PV))`
10710-
that is not in `PV` is mentioned anywhere else in the algebra expression for the query.
10711-
</p>
10712-
</div>
10713-
<p>This process is applied throughout the graph pattern of <code>EXISTS</code>:</p>
10714-
<div class="defn">
10715-
<b>Definition: <span id="defn_varrename">Variable Remapping</span></b>
10716-
<p>
10717-
For any algebra expression `X`, define the Variable Remapping `PrjMap(X)`
10718-
of algebra expression `X`:
10719-
</p>
10720-
<pre>PrjMap(X) = replace all project operations Project(P, PV)
10721-
with ProjectMap(Project(A, PV), PV) for each projection in X.</pre>
10722-
</div>
10723-
<p>
10724-
The outcome of `PrjMap` is independent of the order of replacement
10725-
(whether "bottom-up" or "top-down") order.
10726-
Replacements may happen several times, depending on recursive order
10727-
but each time a replacement is made, the variable not used anywhere else.
10728-
</p>
10729-
10730-
<div class="note">
10731-
<p>
10732-
A variable inside a project expression that is not in the variables projected
10733-
is not affected by the values insertion operation because it is renamed apart.
10734-
</p>
10735-
<p>
10736-
This operation is as part of the <a href="#sparqlQuery">translation to the SPARQL
10737-
algebra</a>.
10738-
</p>
10739-
</div>
10740-
</section>
10741-
<section>
10742-
<h4>Values Insertion</h4>
10743-
<p>
10744-
Alternative 1: rewrite the algebra during
10745-
<a href="#sparqlQuery">translation to the SPARQL algebra</a>
10746-
to include a function that evaluates to the current row.
10747-
</p>
10748-
10749-
<div class="defn">
10750-
<div>
10751-
<b>Definition: <span id="defn_correlate">Values In Scope</span></b>
10752-
<p>
10753-
Define the function `BindingInScope()`.
10754-
Evaluation of `BindingInScope()` results in a table of one row,
10755-
being the current binding of the enclosing filter.
10756-
</p>
10757-
</div>
10758-
<p class="ednote">Need to define `BindingInScope`</p>
10759-
</div>
10760-
10761-
<div class="defn">
10762-
<div>
10763-
<b>Definition: Access to the current binding</b>
10764-
<p>
10765-
During <a href="#sparqlQuery">translation to the SPARQL algebra</a>
10766-
</p>
10767-
<p class="ednote">Define putting in the `BindingInScope` operator</p>
10768-
<pre>
10769-
Replace each occurence of Y where Y is one of
10770-
<a href="#sparqlTranslateBasicGraphPatterns">Basic Graph Pattern</a>,
10771-
<a href="#sparqlTranslatePathPatterns">Property Path Patterns</a>,
10772-
<a href="#sparqlTranslateGraphPatterns">Graph(Var, pattern)</a>,
10773-
<a href="#https://www.w3.org/TR/sparql12-query/#sparqlTranslateGraphPatterns">Inline Data</a>
10774-
with join(Y, BindingInScope()).</pre>
10775-
</div>
10776-
<div class="note">
10777-
c.f. section <a href="#sparqlTranslateGraphPatterns">Translate Graph Patterns</a>
10778-
where an empty basic graph pattern start any
10779-
<a href="#rGroupGraphPattern">GroupGraphPattern</a>.
10780-
It happens before the <a href="#sparqlSimplification">simplification step</a>.
10781-
</div>
10782-
</div>
10783-
10784-
<div class="example">
10785-
<p>
10786-
Examples
10787-
</p>
10788-
</div>
10789-
10790-
<p>
10791-
Alternative 2: rewrite the algebra during execution. This corresponds to the
10792-
<a href="https://github.com/w3c/sparql-dev/blob/main/SEP/SEP-0007/sep-0007.md">original SEP-0007 proposal</a>.
10793-
</p>
10794-
<div class="defn">
10795-
<div>
10796-
<b>Definition: <span id="defn_insertvalues">Insert Values</span></b>
10797-
<p>
10798-
Define the function `InsertValues(X, μ)`
10799-
</p>
10800-
<pre>Let Table(μ) = { μ } and multiplicity( μ | Table(μ) = { μ } ) = 1
10801-
10802-
Replace each occurence of Y in X where Y is one of
10803-
<a href="#sparqlTranslateBasicGraphPatterns">Basic Graph Pattern</a>,
10804-
<a href="#sparqlTranslatePathPatterns">Property Path Patterns</a>,
10805-
<a href="#sparqlTranslateGraphPatterns">Graph(Var, pattern)</a>,
10806-
<a href="#https://www.w3.org/TR/sparql12-query/#sparqlTranslateGraphPatterns">Inline Data</a>
10807-
with join(Y, Table(μ)).</pre>
10808-
10809-
</div>
10810-
</div>
10811-
</section>
10812-
10813-
<section>
10814-
<h4>Evaluation of EXISTS</h4>
10815-
<div class="defn">
10816-
<b>Definition: <span id="x-defn_evalExists">Evaluation of Exists</span></b>
10817-
<p>
10818-
Let `μ` be the current solution mapping for a filter, and `X` a graph pattern,
10819-
define the Evaluation of Exists `exists(X)`
10820-
</p>
10821-
<p class="ednote">
10822-
@@ Set up the current row for `BindingdInScope`.
10823-
</p>
10824-
<pre>exists(X) = true
10825-
if eval( D(G), μ)
10826-
is a non-empty solution sequence.
10827-
exists(X) = false otherwise</pre>
10828-
</div>
10829-
</section>
10830-
</section>
10831-
<!-- ValuesInsertion -->
10832-
1083310748
</section>
1083410749

1083510750
<section id="sparqlBGPExtend">

0 commit comments

Comments
 (0)