Skip to content

Commit

Permalink
Fix issue #1398 - SET followed by DELETE does not delete (#1412)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rafsun42 authored and jrgemignani committed Dec 13, 2023
1 parent 0bd3285 commit a82f64b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 3 deletions.
75 changes: 72 additions & 3 deletions regress/expected/cypher_delete.out
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
--
Expand Down
19 changes: 19 additions & 0 deletions regress/sql/cypher_delete.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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
--
Expand Down
4 changes: 4 additions & 0 deletions src/backend/executor/cypher_delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,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);

Expand Down Expand Up @@ -501,6 +503,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(
Expand Down

0 comments on commit a82f64b

Please sign in to comment.