Skip to content

Commit e0c40cd

Browse files
JPryce-AklundhsherfertHannesSandbergncordonHunterness
authored andcommitted
Merge 5.7 PRs to 5.x (#519)
Co-authored-by: Satia Herfert <[email protected]> Co-authored-by: Hannes Sandberg <[email protected]> Co-authored-by: Nacho Cordón <[email protected]> Co-authored-by: Therese Magnusson <[email protected]> Co-authored-by: Pontus Melke <[email protected]>
1 parent b2ccc14 commit e0c40cd

File tree

3 files changed

+249
-10
lines changed

3 files changed

+249
-10
lines changed

modules/ROOT/pages/administration/databases.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ ALTER DATABASE name [IF EXISTS]
9393
SET ACCESS {READ ONLY \| READ WRITE} \|
9494
SET TOPOLOGY n PRIMAR{Y\|IES} [m SECONDAR{Y\|IES}]
9595
}
96+
[WAIT [n [SEC[OND[S]]]]\|NOWAIT]
9697
----
9798

9899
| STOP DATABASE
@@ -1125,7 +1126,7 @@ To ensure the database to be dropped is standard and not composite, the user fir
11251126
[[administration-wait-nowait]]
11261127
== Wait options
11271128

1128-
Aside from `SHOW DATABASES` and `ALTER DATABASE`, all database management commands accept an optional `WAIT`/`NOWAIT` clause.
1129+
Aside from `SHOW DATABASES`, all database management commands accept an optional `WAIT`/`NOWAIT` clause.
11291130
The `WAIT`/`NOWAIT` clause allows you to specify a time limit in which the command must complete and return.
11301131

11311132
The options are:

modules/ROOT/pages/clauses/call-subquery.adoc

Lines changed: 247 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,11 @@ RETURN p.name, youngerPersonsCount
415415
Subqueries can be made to execute in separate, inner transactions, producing intermediate commits.
416416
This can come in handy when doing large write operations, like batch updates, imports, and deletes.
417417
To execute a subquery in separate transactions, you add the modifier `IN TRANSACTIONS` after the subquery.
418+
An outer transaction is opened to report back the accumulated statistics for the inner transactions
419+
(created and deleted nodes, relationships, etc) and it will succeed or fail depending on the results
420+
of those inner transactions.
421+
For more information, see <<txs_error_behaviour, error behaviour>>.
422+
Canceling that outer transaction will cancel the inner ones.
418423

419424
The following example uses a CSV file and the `LOAD CSV` clause to import more data to the example graph.
420425
It creates nodes in separate transactions using `+CALL { ... } IN TRANSACTIONS+`:
@@ -435,7 +440,7 @@ It creates nodes in separate transactions using `+CALL { ... } IN TRANSACTIONS+`
435440
LOAD CSV FROM 'file:///friends.csv' AS line
436441
CALL {
437442
WITH line
438-
CREATE (:PERSON {name: line[1], age: toInteger(line[2])})
443+
CREATE (:Person {name: line[1], age: toInteger(line[2])})
439444
} IN TRANSACTIONS
440445
----
441446

@@ -601,15 +606,20 @@ The batch size of `2 ROWS` is an example given the small data set used here.
601606
For larger data sets, you might want to use larger batch sizes, such as `10000 ROWS`.
602607
====
603608

609+
=== Error behaviour [[txs_error_behaviour]]
610+
Users can choose one of three different option flags to control the behaviour
611+
in case of an error occurring in any of the inner transactions of `+CALL { ... } IN TRANSACTIONS+`:
604612

605-
=== Errors
606-
607-
If an error occurs in `+CALL { ... } IN TRANSACTIONS+` the entire query fails and
608-
both the current inner transaction and the outer transaction are rolled back.
613+
* `ON ERROR CONTINUE` to ignore a recoverable error and continue the execution of subsequent inner transactions.
614+
The outer transaction succeeds.
615+
It will cause the expected variables from the failed inner query to be bound as null for that specific transaction.
616+
* `ON ERROR BREAK` to ignore a recoverable error and stop the execution of subsequent inner transactions. The outer transaction succeeds.
617+
It will cause expected variables from the failed inner query to be bound as null for all onward transactions (including the failed one).
618+
* `ON ERROR FAIL` to acknowledge a recoverable error and stop the execution of subsequent inner transactions. The outer transaction fails. This is the default behaviour if no flag is explicitly specified.
609619

610620
[IMPORTANT]
611621
====
612-
On error, any previously committed inner transactions remain committed, and are not rolled back.
622+
On error, any previously committed inner transactions remain committed, and are not rolled back. Any failed inner transactions are rolled back.
613623
====
614624

615625
In the following example, the last subquery execution in the second inner transaction fails
@@ -621,7 +631,7 @@ due to division by zero.
621631
UNWIND [4, 2, 1, 0] AS i
622632
CALL {
623633
WITH i
624-
CREATE (:Example {num: 100/i})
634+
CREATE (:Person {num: 100/i})
625635
} IN TRANSACTIONS OF 2 ROWS
626636
RETURN i
627637
----
@@ -637,7 +647,7 @@ When the failure occurred, the first transaction had already been committed, so
637647
.Query
638648
[source, cypher]
639649
----
640-
MATCH (e:Example)
650+
MATCH (e:Person)
641651
RETURN e.num
642652
----
643653

@@ -650,6 +660,235 @@ RETURN e.num
650660
1+d|Rows: 2
651661
|===
652662

663+
In the following example, `ON ERROR CONTINUE` is used after a failed inner transaction to execute the remaining inner transactions and not fail the outer transaction:
664+
665+
.Query
666+
[source, cypher]
667+
----
668+
UNWIND [1, 0, 2, 4] AS i
669+
CALL {
670+
WITH i
671+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
672+
RETURN n
673+
} IN TRANSACTIONS
674+
OF 1 ROW
675+
ON ERROR CONTINUE
676+
RETURN n.num;
677+
----
678+
679+
.Result
680+
[role="queryresult",options="header,footer",cols="1*<m"]
681+
|===
682+
| +n.num+ |
683+
| 100 |
684+
| null |
685+
| 50 |
686+
| 25 |
687+
1+d|Rows: 4
688+
|===
689+
690+
Note the difference in results when batching in transactions of 2 rows:
691+
692+
.Query
693+
[source, cypher, indent=0]
694+
----
695+
UNWIND [1, 0, 2, 4] AS i
696+
CALL {
697+
WITH i
698+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
699+
RETURN n
700+
} IN TRANSACTIONS
701+
OF 2 ROWS
702+
ON ERROR CONTINUE
703+
RETURN n.num;
704+
----
705+
706+
.Result
707+
[role="queryresult",options="header,footer",cols="1*<m"]
708+
|===
709+
| +n.num+ |
710+
| null |
711+
| null |
712+
| 50 |
713+
| 25 |
714+
1+d|Rows: 4
715+
|===
716+
717+
This happens because an inner transaction with the two first `i` elements (1 and 0)
718+
was created, and it fails for 0.
719+
This causes it to be rolled back and the return
720+
variable is filled with nulls for those two elements.
721+
722+
In the following example, `ON ERROR BREAK` is used after a failed inner transaction to not execute the remaining inner transaction and not fail the outer transaction:
723+
724+
.Query
725+
[source, cypher, indent=0]
726+
----
727+
UNWIND [1, 0, 2, 4] AS i
728+
CALL {
729+
WITH i
730+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
731+
RETURN n
732+
} IN TRANSACTIONS
733+
OF 1 ROW
734+
ON ERROR BREAK
735+
RETURN n.num;
736+
----
737+
738+
.Result
739+
[role="queryresult",options="header,footer",cols="1*<m"]
740+
|===
741+
| +n.num+ |
742+
| 100 |
743+
| null |
744+
| null |
745+
| null |
746+
1+d|Rows: 4
747+
|===
748+
749+
Note the difference in results when batching in transactions of 2 rows:
750+
751+
.Query
752+
[source, cypher, indent=0]
753+
----
754+
UNWIND [1, 0, 2, 4] AS i
755+
CALL {
756+
WITH i
757+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
758+
RETURN n
759+
} IN TRANSACTIONS
760+
OF 2 ROWS
761+
ON ERROR BREAK
762+
RETURN n.num;
763+
----
764+
765+
.Result
766+
[role="queryresult",options="header,footer",cols="1*<m"]
767+
|===
768+
| +n.num+ |
769+
| null |
770+
| null |
771+
| null |
772+
| null |
773+
1+d|Rows: 4
774+
|===
775+
776+
In the following example, `ON ERROR FAIL` is used after the failed inner transaction, to not execute the remaining inner transactions and to fail the outer transaction:
777+
778+
.Query
779+
[source, cypher, indent=0, role=test-fail]
780+
----
781+
UNWIND [1, 0, 2, 4] AS i
782+
CALL {
783+
WITH i
784+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
785+
RETURN n
786+
} IN TRANSACTIONS
787+
OF 1 ROW
788+
ON ERROR FAIL
789+
RETURN n.num;
790+
----
791+
792+
.Error message
793+
[source, error, role=test-fail]
794+
----
795+
/ by zero (Transactions committed: 1)
796+
----
797+
798+
=== Status report
799+
Users can also report the execution status of the inner transactions by using `REPORT STATUS AS var`.
800+
This flag is disallowed for `ON ERROR FAIL`. For more information, see <<txs_error_behaviour, error behaviour>>.
801+
802+
After each execution of the inner query finishes (successfully or not), a status value is created that records information about the execution and the transaction that executed it:
803+
804+
* If the inner execution produces one or more rows as output, then a binding to this status value is added to each row, under the selected variable name.
805+
* If the inner execution fails then a single row is produced containing a binding to this status value under the selected variable, and null bindings for all variables that should have been returned by the inner query (if any).
806+
807+
The status value is a map value with the following fields:
808+
809+
* `started`: `true` when the inner transaction was started, `false` otherwise.
810+
* `committed`, true when the inner transaction changes were successfully committed, false otherwise.
811+
* `transactionId`: the inner transaction id, or null if the transaction was not started.
812+
* `errorMessage`, the inner transaction error message, or null in case of no error.
813+
814+
Example of reporting status with `ON ERROR CONTINUE`:
815+
816+
.Query
817+
[source, cypher, indent=0, role=test-result-skip]
818+
----
819+
UNWIND [1, 0, 2, 4] AS i
820+
CALL {
821+
WITH i
822+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
823+
RETURN n
824+
} IN TRANSACTIONS
825+
OF 1 ROW
826+
ON ERROR CONTINUE
827+
REPORT STATUS AS s
828+
RETURN n.num, s;
829+
----
830+
831+
.Result
832+
[role="queryresult",options="header,footer",cols="2*<m"]
833+
|===
834+
| +n.num+ | +s+
835+
| 100 | +{"committed": true, "errorMessage": null, "started": true, "transactionId": "neo4j-transaction-835" }+
836+
| null | +{"committed": false, "errorMessage": "/ by zero", "started": true, "transactionId": "neo4j-transaction-836" }+
837+
| 50 | +{"committed": true, "errorMessage": null, "started": true, "transactionId": "neo4j-transaction-837" }+
838+
| 25 | +{"committed": true, "errorMessage": null, "started": true, "transactionId": "neo4j-transaction-838" }+
839+
2+d|Rows: 4
840+
|===
841+
842+
Example of reporting status with `ON ERROR BREAK`:
843+
844+
.Query
845+
[source, cypher, indent=0]
846+
----
847+
UNWIND [1, 0, 2, 4] AS i
848+
CALL {
849+
WITH i
850+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
851+
RETURN n
852+
} IN TRANSACTIONS
853+
OF 1 ROW
854+
ON ERROR BREAK
855+
REPORT STATUS AS s
856+
RETURN n.num, s.started, s.committed, s.errorMessage;
857+
----
858+
859+
.Result
860+
[role="queryresult",options="header,footer",cols="4*<m"]
861+
|===
862+
| +n.num+ | +s.started+ | +s.committed+ | +s.errorMessage+
863+
| 100 | true | true | null
864+
| null | true | false | "/ by zero"
865+
| null | false | false | null
866+
| null | false | false | null
867+
4+d|Rows: 4
868+
|===
869+
870+
Reporting status with `ON ERROR FAIL` is disallowed:
871+
872+
.Query
873+
[source, cypher, role=test-fail]
874+
----
875+
UNWIND [1, 0, 2, 4] AS i
876+
CALL {
877+
WITH i
878+
CREATE (n:Person {num: 100/i}) // Note, fails when i = 0
879+
RETURN n
880+
} IN TRANSACTIONS
881+
OF 1 ROW
882+
ON ERROR FAIL
883+
REPORT STATUS AS s
884+
RETURN n.num, s.errorMessage;
885+
----
886+
887+
.Error
888+
[source, error, role="noheader"]
889+
----
890+
REPORT STATUS can only be used when specifying ON ERROR CONTINUE or ON ERROR BREAK
891+
----
653892

654893
=== Restrictions
655894

modules/ROOT/pages/clauses/merge.adoc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,6 @@ For example, if there exists a relationship uniqueness constraint on `()-[:ACTED
634634
MERGE (charlie:Person {name: 'Charlie Sheen'})-[r:ACTED_IN {year: 1987}]->(wallStreet:Movie {title: 'Wall Street'})
635635
RETURN charlie.name, type(r), wallStreet.title
636636
----
637-
638637
This is due to the all-or-nothing semantics of `MERGE`, which causes the query to fail if there exists a relationship with the given `year` property but there is no match for the full pattern.
639638
In this example, since no match was found for the pattern, `MERGE` will try to create the full pattern including a relationship with `{year: 1987}`, which will lead to constraint violation error.
640639

0 commit comments

Comments
 (0)