Skip to content

Commit fa12c08

Browse files
committed
More descriptive text
Clarify the semantics of Scalar Subqueries. Specify the reason for having SingleValuePatternQuery, i.e. it being the future of Pattern Comprehension.
1 parent 61cc42b commit fa12c08

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

cip/1.accepted/CIP2017-03-29-Single-Value-Subqueries.adoc

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,73 @@ Filter = [Order], [Skip], [Limit] ;
4545

4646
=== Scalar Subqueries
4747

48+
Scalar Subqueries are read-only subqueries that produce a single value in a single row.
49+
The result of a Scalar Subquery is the single value (in the single row) produced by the subquery.
50+
51+
If the subquery of a Scalar Subquery produces more than a single row an error value (or `NULL`) is produced as the result of the subquery.
52+
53+
If the subquery of a Scalar Subquery produces no rows, an error value (or `NULL`) is produced as the result of the subquery.
54+
55+
Note that this makes it difficult to distinguish between the cases of:
56+
57+
* The Scalar Subquery produced more than a single row
58+
* The Scalar Subquery produced zero rows
59+
* The Scalar Subquery produced a single row, but the value of that row is an error value (or `NULL`)
60+
61+
In order to allow the user to explicitly distinguish between these cases, we allow ways of asserting that there is exactly one row.
62+
63+
* For ensuring that the Scalar Subquery produces at least a single row, the `MANDATORY` query modifies can be used, either by specifying the whole Scalar Subquery as a mandatory subquery, or if the subquery is a single `MATCH` subquery `MANDATORY MATCH` can be used.
64+
* For ensuring that the Scalar Subquery produces at most single rows, an asserting aggregation function called `single` is proposed.
65+
This aggregation raises an error from the query if more than a single row is aggregated.
66+
67+
4868
=== List Subqueries
4969

70+
List Subqueries are read-only subqueries that produce a single value per row, and zero or more rows.
71+
The result of a List Subquery is the list formed by collecting all of the values of all rows produced by the subquery.
72+
If the subquery of the List Subquery produces no rows, the result of the List Subquery is an empty list.
73+
74+
A Scalar Subquery is equivalent to the corresponding Scalar Subquery where the projected value is collected into a list.
75+
As an example, the following query:
76+
77+
[source, cypher]
78+
----
79+
MATCH (p:Person)
80+
RETURN p.name AS person, [
81+
MATCH (p)-[:KNOWS]-(f)
82+
RETURN f.name
83+
] AS friends
84+
----
85+
86+
is equivalent to:
87+
88+
[source, cypher]
89+
----
90+
MATCH (p:Person)
91+
RETURN p.name AS person, SCALAR (
92+
MATCH (p)-[:KNOWS]-(f)
93+
RETURN collect(f.name)
94+
) AS friends
95+
----
96+
97+
=== Single Pattern Based Subqueries
98+
99+
The subquery syntax defined by the `SingleValuePatternQuery` non-terminal is intended to replace the syntax that has been known as "Pattern Comprehension" and recast it as a kind of subquery.
100+
It is semantically equivalent to a `SingleValueQuery` with a `Match` preceding the single `PatternPart`, including the optional `Where`.
101+
102+
It differs from `SingleValueQuery` in that:
103+
104+
* it only allows a single `Match` with a single `PatternPart`.
105+
* it does not allow `Unwind`, `Call`, or `With`.
106+
107+
It differs from "Pattern Comprehension" in that:
108+
109+
* it uses `RETURN` for defining the projected value instead of `|`.
110+
111+
A `SingleValuePatternQuery`, `α [WHERE ρ] RETURN σ` is canonicalized to a `SingleValueQuery` as `MATCH α [WHERE ρ] RETURN σ`.
112+
For example `[(kevin)-[:KNOWS]\->(friend) RETURN friend.name]` is canonicalized to `[MATCH (kevin)-[:KNOWS]\->(friend) RETURN friend.name]`.
113+
114+
50115
=== Examples
51116

52117
[source, cypher]
@@ -132,14 +197,14 @@ RETURN who.name, SCALAR (
132197
MATCH (who)-[filing:FILED]->(receipt)
133198
WHERE date.truncate('month', date() - duration('P1M'))
134199
<= filing.date <
135-
date.truncate('month', date() - duration('P1M'))
200+
date.truncate('month', date() + duration('P1M'))
136201
RETURN sum(receipt.amount)
137202
) AS total_expenses
138203
----
139204

140205

141206
[source, cypher]
142-
.Something
207+
.Using the `SingleValueCallQuery` form to avoid redundant projection
143208
----
144209
RETURN [
145210
CALL my.cool.Procedure() YIELD theValue

0 commit comments

Comments
 (0)