This is an automated email from the ASF dual-hosted git repository.

jgemignani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/age.git


The following commit(s) were added to refs/heads/master by this push:
     new 5fbe064a Fix issue #1398 - SET followed by DELETE does not delete 
(#1412)
5fbe064a is described below

commit 5fbe064a913f03dd13058cc21b7b7fb0cdf910cb
Author: Rafsun Masud <rafsu...@gmail.com>
AuthorDate: Tue Nov 21 15:57:35 2023 -0800

    Fix issue #1398 - SET followed by DELETE does not delete (#1412)
    
    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 1cca3313..2a3b01f3 100644
--- a/src/backend/executor/cypher_delete.c
+++ b/src/backend/executor/cypher_delete.c
@@ -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);
 
@@ -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(

Reply via email to