This is an automated email from the ASF dual-hosted git repository.
jgemignani pushed a commit to branch PG12
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/PG12 by this push:
new 24a1c8fc Fix issue #1398 - SET followed by DELETE does not delete
(#1416)
24a1c8fc is described below
commit 24a1c8fcb610f94d9f479bc5390512f0326c6187
Author: Rafsun Masud <[email protected]>
AuthorDate: Tue Nov 28 11:35:00 2023 -0800
Fix issue #1398 - SET followed by DELETE does not delete (#1416)
In the DELETE executor, tuples were being locked\deleted using the command
ID
returned by GetCurrentCommandId(). However, the original tuples were
retrieved
using a command ID stored in the estate.
To fix it- before the retrieval of a tuple, estate command IDs are set using
GetCurrentCommandId() so it matches if the tuple is to be deleted later.
Additional changes:
-------------------
Fixed an incorrect cypher_delete test. The query
`MATCH (n1)-[e]->() DELETE n1, e RETURN n1` should be able to delete n1 and
e
without requiring DETACH DELETE.
TODO:
-----
It may be a good idea to audit the executors for any inconsistent use of
command IDs.
---
regress/expected/cypher_delete.out | 75 ++++++++++++++++++++++++++++++++++--
regress/sql/cypher_delete.sql | 19 +++++++++
src/backend/executor/cypher_delete.c | 4 ++
3 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/regress/expected/cypher_delete.out
b/regress/expected/cypher_delete.out
index 7ac07dfd..3cdbbf8b 100644
--- a/regress/expected/cypher_delete.out
+++ b/regress/expected/cypher_delete.out
@@ -234,14 +234,17 @@ SELECT * FROM cypher('cypher_delete', $$CREATE
(n:v)-[:e]->(:v)$$) AS (a agtype)
(0 rows)
SELECT * FROM cypher('cypher_delete', $$MATCH(n1)-[e]->() DELETE n1, e RETURN
n1$$) AS (a agtype);
-ERROR: Cannot delete a vertex that has edge(s). Delete the edge(s) first, or
try DETACH DELETE.
+ a
+-----------------------------------------------------------------
+ {"id": 844424930131990, "label": "v", "properties": {}}::vertex
+(1 row)
+
--Cleanup
SELECT * FROM cypher('cypher_delete', $$MATCH(n) DETACH DELETE n RETURN n$$)
AS (a agtype);
a
-----------------------------------------------------------------
- {"id": 844424930131990, "label": "v", "properties": {}}::vertex
{"id": 844424930131991, "label": "v", "properties": {}}::vertex
-(2 rows)
+(1 row)
SELECT * FROM cypher('cypher_delete', $$MATCH(n) RETURN n$$) AS (a agtype);
a
@@ -758,6 +761,72 @@ NOTICE: graph "detach_delete" has been dropped
(1 row)
+--
+-- SET followed by DELETE
+--
+SELECT create_graph('setdelete');
+NOTICE: graph "setdelete" has been created
+ create_graph
+--------------
+
+(1 row)
+
+-- MATCH (x) SET x DELETE x
+SELECT * FROM cypher('setdelete', $$ CREATE (:A), (:A), (:A) $$) as ("CREATE"
agtype);
+ CREATE
+--------
+(0 rows)
+
+SELECT * FROM cypher('setdelete', $$ MATCH (x:A) SET x.age = 24 DELETE x $$)
as ("SET + DELETE" agtype);
+ SET + DELETE
+--------------
+(0 rows)
+
+SELECT id as "expected: 0 rows" FROM setdelete._ag_label_vertex;
+ expected: 0 rows
+------------------
+(0 rows)
+
+-- MATCH (n)-[e]->(m) SET e DETACH DELETE n
+SELECT * FROM cypher('setdelete', $$ CREATE (:n)-[:e]->(:m), (:n)-[:e]->(:m)
$$) AS ("CREATE" agtype);
+ CREATE
+--------
+(0 rows)
+
+SELECT * FROM cypher('setdelete', $$ MATCH (n)-[e]->(m) SET e.i = 1 DETACH
DELETE n RETURN id(m) $$) AS ("SET + DETACH DELETE" agtype);
+ SET + DETACH DELETE
+---------------------
+ 1688849860263937
+ 1688849860263938
+(2 rows)
+
+SELECT id as "expected: 2 rows (m vertices)" FROM setdelete._ag_label_vertex;
+ expected: 2 rows (m vertices)
+-------------------------------
+ 1688849860263937
+ 1688849860263938
+(2 rows)
+
+SELECT id as "expected: 0 rows" FROM setdelete._ag_label_edge;
+ expected: 0 rows
+------------------
+(0 rows)
+
+-- clean up
+SELECT drop_graph('setdelete', true);
+NOTICE: drop cascades to 6 other objects
+DETAIL: drop cascades to table setdelete._ag_label_vertex
+drop cascades to table setdelete._ag_label_edge
+drop cascades to table setdelete."A"
+drop cascades to table setdelete.n
+drop cascades to table setdelete.e
+drop cascades to table setdelete.m
+NOTICE: graph "setdelete" has been dropped
+ drop_graph
+------------
+
+(1 row)
+
--
-- Clean up
--
diff --git a/regress/sql/cypher_delete.sql b/regress/sql/cypher_delete.sql
index f0d98b6e..4ddea60c 100644
--- a/regress/sql/cypher_delete.sql
+++ b/regress/sql/cypher_delete.sql
@@ -283,6 +283,25 @@ SELECT * FROM cypher('detach_delete', $$ MATCH ()-[e]->()
RETURN e.name $$) as (
SELECT drop_graph('detach_delete', true);
+--
+-- SET followed by DELETE
+--
+SELECT create_graph('setdelete');
+
+-- MATCH (x) SET x DELETE x
+SELECT * FROM cypher('setdelete', $$ CREATE (:A), (:A), (:A) $$) as ("CREATE"
agtype);
+SELECT * FROM cypher('setdelete', $$ MATCH (x:A) SET x.age = 24 DELETE x $$)
as ("SET + DELETE" agtype);
+SELECT id as "expected: 0 rows" FROM setdelete._ag_label_vertex;
+
+-- MATCH (n)-[e]->(m) SET e DETACH DELETE n
+SELECT * FROM cypher('setdelete', $$ CREATE (:n)-[:e]->(:m), (:n)-[:e]->(:m)
$$) AS ("CREATE" agtype);
+SELECT * FROM cypher('setdelete', $$ MATCH (n)-[e]->(m) SET e.i = 1 DETACH
DELETE n RETURN id(m) $$) AS ("SET + DETACH DELETE" agtype);
+SELECT id as "expected: 2 rows (m vertices)" FROM setdelete._ag_label_vertex;
+SELECT id as "expected: 0 rows" FROM setdelete._ag_label_edge;
+
+-- clean up
+SELECT drop_graph('setdelete', true);
+
--
-- Clean up
--
diff --git a/src/backend/executor/cypher_delete.c
b/src/backend/executor/cypher_delete.c
index ee440971..45e7d8e0 100644
--- a/src/backend/executor/cypher_delete.c
+++ b/src/backend/executor/cypher_delete.c
@@ -436,6 +436,8 @@ static void process_delete_list(CustomScanState *node)
/*
* Setup the scan description, with the correct snapshot and scan keys.
*/
+ estate->es_snapshot->curcid = GetCurrentCommandId(false);
+ estate->es_output_cid = GetCurrentCommandId(false);
scan_desc = table_beginscan(resultRelInfo->ri_RelationDesc,
estate->es_snapshot, 1, scan_keys);
@@ -500,6 +502,8 @@ static void check_for_connected_edges(CustomScanState *node)
resultRelInfo = create_entity_result_rel_info(estate, graph_name,
label_name);
+ estate->es_snapshot->curcid = GetCurrentCommandId(false);
+ estate->es_output_cid = GetCurrentCommandId(false);
scan_desc = table_beginscan(resultRelInfo->ri_RelationDesc,
estate->es_snapshot, 0, NULL);
slot = ExecInitExtraTupleSlot(