Skip to content

Commit d3b1cef

Browse files
Clause composition: Write-read conflicts (#1328)
Extend clause composition docs to also include Write-Read conflicts instead of only Read-Write conflicts Co-authored-by: Richard Sill <[email protected]>
1 parent bd97e08 commit d3b1cef

File tree

1 file changed

+99
-3
lines changed

1 file changed

+99
-3
lines changed

modules/ROOT/pages/clauses/clause-composition.adoc

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ In a Cypher query, read and write clauses can take turns.
129129
The most important aspect of read-write queries is that the state of the graph also changes between clauses.
130130

131131
[IMPORTANT]
132-
A clause can never observe writes made by a later clause.
132+
A clause can never observe writes made by a later clause, and will observe all writes done by the previous clauses.
133133

134134
As of Cypher 25, read and write clauses can be combined in any order.
135135
That is, a write clause followed by a read clause no longer requires a separating xref:clauses/with.adoc[`WITH`] clause in order for the read clause to observe the changes made by a preceding write clause.
@@ -152,7 +152,7 @@ RETURN f.name AS friendName,
152152
.Table of intermediate results and state of the graph between read and write clauses
153153
======
154154
155-
Using the same example graph as above, this example shows the table of intermediate results and the state of the graph after each clause for the following query:
155+
Using the same example graph as above, this example shows the table of intermediate results and the state of the graph after each clause for a query with a read clause before a write clause:
156156
157157
[source,cypher, indent=0]
158158
----
@@ -163,7 +163,7 @@ The query finds all nodes where the `name` property starts with "J"
163163
and for each such node it creates another node with the `name` property set to "Jay-jay".
164164
165165
166-
.+The table of intermediate results and the state of the graph after each clause+
166+
.Read-write: The table of intermediate results and the state of the graph after each clause+
167167
[options="header", width="100%", cols="3a, 4a, 4a"]
168168
|===
169169
@@ -310,6 +310,102 @@ the graph made by the `CREATE`.
310310
311311
======
312312

313+
.Table of intermediate results and state of the graph between write and read clauses
314+
======
315+
On an empty graph, this example shows the table of intermediate results and the state of the graph after each clause for a query with a write clause before a read clause:
316+
317+
[source,cypher, indent=0]
318+
----
319+
UNWIND ["Max", "Lune"] AS dogName
320+
CREATE (n:Dog {name: dogName})
321+
WITH n
322+
MATCH (d:Dog)
323+
RETURN COUNT(*)
324+
----
325+
This query creates two `Dog` nodes and returns the value `4`.
326+
327+
.+Write-read: The table of intermediate results and the state of the graph after each clause+
328+
[options="header", width="100%", cols="3a, 4a, 4a"]
329+
|===
330+
331+
| Clause
332+
| Table of intermediate results after the clause
333+
| State of the graph after the clause, changes in red
334+
335+
| ----
336+
UNWIND ["Max", "Luna"] AS dogName
337+
----
338+
|
339+
[options="header",cols="1m"]
340+
!===
341+
! dogName
342+
! "Max"
343+
! "Luna"
344+
!===
345+
|
346+
347+
| ----
348+
CREATE (n:Dog {name: dogName})
349+
----
350+
|
351+
[options="header",cols="1m, 1m"]
352+
!===
353+
! dogName ! n
354+
! "Max" ! (:Dog {name: 'Max'})
355+
! "Luna" ! (:Dog {name: 'Luna'})
356+
!===
357+
|
358+
359+
[graphviz]
360+
----
361+
digraph L { node [shape=record style=rounded];
362+
N5 [
363+
color = "red"
364+
fontcolor = "red"
365+
label = "{Dog\|name = \'Max\'\l}"
366+
]
367+
N6 [
368+
color = "red"
369+
fontcolor = "red"
370+
label = "{Dog\|name = \'Luna\'\l}"
371+
]
372+
}
373+
----
374+
375+
| ----
376+
MATCH (d:Dog)
377+
----
378+
|
379+
[options="header",cols="1m, 1m, 1m"]
380+
!===
381+
! dogName ! n ! d
382+
! "Max" ! (:Dog {name: 'Max'}) ! (:Dog {name: 'Max'})
383+
! "Max" ! (:Dog {name: 'Max'}) ! (:Dog {name: 'Luna'})
384+
! "Luna" ! (:Dog {name: 'Luna'}) ! (:Dog {name: 'Max'})
385+
! "Luna" ! (:Dog {name: 'Luna'}) ! (:Dog {name: 'Luna'})
386+
!===
387+
|
388+
389+
[graphviz]
390+
----
391+
digraph L { node [shape=record style=rounded];
392+
N5 [
393+
label = "{Dog\|name = \'Max\'\l}"
394+
]
395+
N6 [
396+
label = "{Dog\|name = \'Luna\'\l}"
397+
]
398+
}
399+
----
400+
|===
401+
402+
It is important to note that the `MATCH` clause reads all the `Dog` nodes that are created by the `CREATE` clause.
403+
This is because the `CREATE` clause comes before the `MATCH` clause and thus the `MATCH` observes all changes to
404+
the graph made by the `CREATE`.
405+
The `MATCH` clause is performed for every intermediate result, this leads to finding two nodes for both intermediate results.
406+
407+
======
408+
313409
[[cypher-clause-composition-union-queries]]
314410
== Queries with `UNION`
315411

0 commit comments

Comments
 (0)