From 8a769aef6407c62273249ba5a1cef70e4407d303 Mon Sep 17 00:00:00 2001 From: John Gemignani Date: Thu, 4 Apr 2024 17:00:08 -0700 Subject: [PATCH] Fix Issue 1709 - MERGE creates incomplete vertices after the first one Fixed issue 1709 where MERGE appears to create incomplete vertices after the first one. However, the real issue was that SET wasn't seeing the newly created tuples from MERGE. This was due to an incorrect cid when performing the tuple insert in MERGE. The issue was that the cid was being overwritten in the function insert_entity_tuple_cid. Once this was corrected, everything worked fine. Added regression tests. --- regress/expected/cypher_merge.out | 141 +++++++++++++++++++++++++++- regress/sql/cypher_merge.sql | 44 ++++++++- src/backend/executor/cypher_utils.c | 4 +- 3 files changed, 183 insertions(+), 6 deletions(-) diff --git a/regress/expected/cypher_merge.out b/regress/expected/cypher_merge.out index af65c0555..af5bd9ea4 100644 --- a/regress/expected/cypher_merge.out +++ b/regress/expected/cypher_merge.out @@ -1529,15 +1529,140 @@ SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype); --- (0 rows) +-- +-- Issue 1709 - MERGE creates incomplete vertices after the first one +-- This is actually an issue with MERGE not using the correct command id +-- +SELECT * FROM create_graph('issue_1709'); +NOTICE: graph "issue_1709" has been created + create_graph +-------------- + +(1 row) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u) RETURN u $$) AS (u agtype); + u +--- +(0 rows) + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark'}] AS map + MERGE (v:PERSON {first: map.first}) + SET v=map + RETURN v $$) AS (v agtype); + v +----------------------------------------------------------------------------------------------------- + {"id": 844424930131969, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131970, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex +(2 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u) RETURN u $$) AS (u agtype); + u +----------------------------------------------------------------------------------------------------- + {"id": 844424930131969, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131970, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex +(2 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + a +--- +(0 rows) + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark', middle: 'jim'}, {first: 'jane', last: 'doe'}, {first: 'ned', last: 'flanders'}, {first: 'wanda', last: 'cosmo'}] AS map + MERGE (v:PERSON {first: map.first}) + SET v=map + RETURN v $$) AS (v agtype); + v +---------------------------------------------------------------------------------------------------------------------- + {"id": 844424930131971, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131972, "label": "PERSON", "properties": {"last": "stark", "first": "ned", "middle": "jim"}}::vertex + {"id": 844424930131973, "label": "PERSON", "properties": {"last": "doe", "first": "jane"}}::vertex + {"id": 844424930131972, "label": "PERSON", "properties": {"last": "flanders", "first": "ned"}}::vertex + {"id": 844424930131974, "label": "PERSON", "properties": {"last": "cosmo", "first": "wanda"}}::vertex +(5 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u) RETURN u $$) AS (u agtype); + u +-------------------------------------------------------------------------------------------------------- + {"id": 844424930131971, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131973, "label": "PERSON", "properties": {"last": "doe", "first": "jane"}}::vertex + {"id": 844424930131972, "label": "PERSON", "properties": {"last": "flanders", "first": "ned"}}::vertex + {"id": 844424930131974, "label": "PERSON", "properties": {"last": "cosmo", "first": "wanda"}}::vertex +(4 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + a +--- +(0 rows) + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark'}] AS map + MERGE (u: PERSON {last: map.last})-[e:KNOWS]->(v:PERSON {first: map.first}) + SET v=map + RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); + u | e | v +-------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------- + {"id": 844424930131975, "label": "PERSON", "properties": {"last": "snow"}}::vertex | {"id": 1125899906842625, "label": "KNOWS", "end_id": 844424930131976, "start_id": 844424930131975, "properties": {}}::edge | {"id": 844424930131976, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131977, "label": "PERSON", "properties": {"last": "stark"}}::vertex | {"id": 1125899906842626, "label": "KNOWS", "end_id": 844424930131978, "start_id": 844424930131977, "properties": {}}::edge | {"id": 844424930131978, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex +(2 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u)-[e]->(v) RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); + u | e | v +-------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------- + {"id": 844424930131975, "label": "PERSON", "properties": {"last": "snow"}}::vertex | {"id": 1125899906842625, "label": "KNOWS", "end_id": 844424930131976, "start_id": 844424930131975, "properties": {}}::edge | {"id": 844424930131976, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131977, "label": "PERSON", "properties": {"last": "stark"}}::vertex | {"id": 1125899906842626, "label": "KNOWS", "end_id": 844424930131978, "start_id": 844424930131977, "properties": {}}::edge | {"id": 844424930131978, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex +(2 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH ()-[e]->() DELETE e $$) AS (a agtype); + a +--- +(0 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + a +--- +(0 rows) + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark'}] AS map + MERGE (u: PERSON {last: map.last})-[e:KNOWS]->(v:PERSON {first: map.first}) + SET u=map SET v=map + RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); + u | e | v +-----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------- + {"id": 844424930131979, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex | {"id": 1125899906842627, "label": "KNOWS", "end_id": 844424930131980, "start_id": 844424930131979, "properties": {}}::edge | {"id": 844424930131980, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131981, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex | {"id": 1125899906842628, "label": "KNOWS", "end_id": 844424930131982, "start_id": 844424930131981, "properties": {}}::edge | {"id": 844424930131982, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex +(2 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (u)-[e]->(v) RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); + u | e | v +-----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------- + {"id": 844424930131979, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex | {"id": 1125899906842627, "label": "KNOWS", "end_id": 844424930131980, "start_id": 844424930131979, "properties": {}}::edge | {"id": 844424930131980, "label": "PERSON", "properties": {"last": "snow", "first": "jon"}}::vertex + {"id": 844424930131981, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex | {"id": 1125899906842628, "label": "KNOWS", "end_id": 844424930131982, "start_id": 844424930131981, "properties": {}}::edge | {"id": 844424930131982, "label": "PERSON", "properties": {"last": "stark", "first": "ned"}}::vertex +(2 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH ()-[e]->() DELETE e $$) AS (a agtype); + a +--- +(0 rows) + +-- clean up +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + a +--- +(0 rows) + -- -- clean up graphs -- -SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype); +SELECT * FROM cypher('cypher_merge', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); a --- (0 rows) -SELECT * FROM cypher('issue_1630', $$MATCH (n) DETACH DELETE n $$) AS (a agtype); +SELECT * FROM cypher('issue_1630', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); + a +--- +(0 rows) + +SELECT * FROM cypher('issue_1709', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); a --- (0 rows) @@ -1595,6 +1720,18 @@ NOTICE: graph "issue_1691" has been dropped (1 row) +SELECT drop_graph('issue_1709', true); +NOTICE: drop cascades to 4 other objects +DETAIL: drop cascades to table issue_1709._ag_label_vertex +drop cascades to table issue_1709._ag_label_edge +drop cascades to table issue_1709."PERSON" +drop cascades to table issue_1709."KNOWS" +NOTICE: graph "issue_1709" has been dropped + drop_graph +------------ + +(1 row) + -- -- End -- diff --git a/regress/sql/cypher_merge.sql b/regress/sql/cypher_merge.sql index 555aff6b3..59efad1b7 100644 --- a/regress/sql/cypher_merge.sql +++ b/regress/sql/cypher_merge.sql @@ -722,11 +722,50 @@ SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo", "bar"] SELECT * FROM cypher('issue_1691', $$MATCH ()-[e]->() DELETE e $$) AS (a agtype); SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype); +-- +-- Issue 1709 - MERGE creates incomplete vertices after the first one +-- This is actually an issue with MERGE not using the correct command id +-- +SELECT * FROM create_graph('issue_1709'); +SELECT * FROM cypher('issue_1709', $$ MATCH (u) RETURN u $$) AS (u agtype); + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark'}] AS map + MERGE (v:PERSON {first: map.first}) + SET v=map + RETURN v $$) AS (v agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u) RETURN u $$) AS (u agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark', middle: 'jim'}, {first: 'jane', last: 'doe'}, {first: 'ned', last: 'flanders'}, {first: 'wanda', last: 'cosmo'}] AS map + MERGE (v:PERSON {first: map.first}) + SET v=map + RETURN v $$) AS (v agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u) RETURN u $$) AS (u agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark'}] AS map + MERGE (u: PERSON {last: map.last})-[e:KNOWS]->(v:PERSON {first: map.first}) + SET v=map + RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u)-[e]->(v) RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH ()-[e]->() DELETE e $$) AS (a agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + +SELECT * FROM cypher('issue_1709', $$ UNWIND [{first: 'jon', last: 'snow'}, {first: 'ned', last: 'stark'}] AS map + MERGE (u: PERSON {last: map.last})-[e:KNOWS]->(v:PERSON {first: map.first}) + SET u=map SET v=map + RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (u)-[e]->(v) RETURN u,e,v $$) AS (u agtype, e agtype, v agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH ()-[e]->() DELETE e $$) AS (a agtype); +-- clean up +SELECT * FROM cypher('issue_1709', $$ MATCH (u) DELETE u $$) AS (a agtype); + -- -- clean up graphs -- -SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype); -SELECT * FROM cypher('issue_1630', $$MATCH (n) DETACH DELETE n $$) AS (a agtype); +SELECT * FROM cypher('cypher_merge', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); +SELECT * FROM cypher('issue_1630', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); +SELECT * FROM cypher('issue_1709', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); -- -- delete graphs @@ -734,6 +773,7 @@ SELECT * FROM cypher('issue_1630', $$MATCH (n) DETACH DELETE n $$) AS (a agtype) SELECT drop_graph('cypher_merge', true); SELECT drop_graph('issue_1630', true); SELECT drop_graph('issue_1691', true); +SELECT drop_graph('issue_1709', true); -- -- End diff --git a/src/backend/executor/cypher_utils.c b/src/backend/executor/cypher_utils.c index 41091d663..e7a33f4f3 100644 --- a/src/backend/executor/cypher_utils.c +++ b/src/backend/executor/cypher_utils.c @@ -256,8 +256,8 @@ HeapTuple insert_entity_tuple_cid(ResultRelInfo *resultRelInfo, } // Insert the tuple normally - table_tuple_insert(resultRelInfo->ri_RelationDesc, elemTupleSlot, - GetCurrentCommandId(true), 0, NULL); + table_tuple_insert(resultRelInfo->ri_RelationDesc, elemTupleSlot, cid, 0, + NULL); // Insert index entries for the tuple if (resultRelInfo->ri_NumIndices > 0)