diff --git a/regress/expected/cypher_merge.out b/regress/expected/cypher_merge.out index ac08a971a..6c888bb00 100644 --- a/regress/expected/cypher_merge.out +++ b/regress/expected/cypher_merge.out @@ -2237,6 +2237,55 @@ SELECT * FROM cypher('merge_actions', $$ MATCH (n) DETACH DELETE n $$) AS (a agt --- (0 rows) +-- +-- Regression test for #2537: DELETE edge + full-path MERGE segfault +-- (apply_update_list scanTupleSlot NULL deref) +-- +SELECT * FROM create_graph('issue_2537'); +NOTICE: graph "issue_2537" has been created + create_graph +-------------- + +(1 row) + +SELECT * FROM cypher('issue_2537', $$ +CREATE (a:base {id: 1})-[r1:r {k0: false}]-> + (n:base {id: 2})-[r0:s {k5: 'x'}]->(b:base {id: 3}) +$$) AS (created agtype); + created +--------- +(0 rows) + +SELECT * FROM cypher('issue_2537', $$ +MATCH (a:base)-[r1:r]->(n:base)-[r0:s]->(b:base) +SET r0.k5 = 'J', r1.k0 = true +WITH range(0, 0) + [0] AS keep, r1 AS old +WHERE 0 IN keep +DELETE old +CREATE (:x) +MERGE p0 = ({id: 129})-[r2:r]->(n2 {id: 130})-[:s]->(:c {id: 131}) +RETURN 1 +$$) AS (value agtype); + value +------- + 1 +(1 row) + +SELECT * FROM drop_graph('issue_2537', true); +NOTICE: drop cascades to 7 other objects +DETAIL: drop cascades to table issue_2537._ag_label_vertex +drop cascades to table issue_2537._ag_label_edge +drop cascades to table issue_2537.base +drop cascades to table issue_2537.r +drop cascades to table issue_2537.s +drop cascades to table issue_2537.x +drop cascades to table issue_2537.c +NOTICE: graph "issue_2537" has been dropped + drop_graph +------------ + +(1 row) + -- -- delete graphs -- diff --git a/regress/sql/cypher_merge.sql b/regress/sql/cypher_merge.sql index 86b3e0235..86a21c239 100644 --- a/regress/sql/cypher_merge.sql +++ b/regress/sql/cypher_merge.sql @@ -1088,6 +1088,30 @@ $$) AS (src agtype, last agtype); -- cleanup SELECT * FROM cypher('merge_actions', $$ MATCH (n) DETACH DELETE n $$) AS (a agtype); +-- +-- Regression test for #2537: DELETE edge + full-path MERGE segfault +-- (apply_update_list scanTupleSlot NULL deref) +-- +SELECT * FROM create_graph('issue_2537'); + +SELECT * FROM cypher('issue_2537', $$ +CREATE (a:base {id: 1})-[r1:r {k0: false}]-> + (n:base {id: 2})-[r0:s {k5: 'x'}]->(b:base {id: 3}) +$$) AS (created agtype); + +SELECT * FROM cypher('issue_2537', $$ +MATCH (a:base)-[r1:r]->(n:base)-[r0:s]->(b:base) +SET r0.k5 = 'J', r1.k0 = true +WITH range(0, 0) + [0] AS keep, r1 AS old +WHERE 0 IN keep +DELETE old +CREATE (:x) +MERGE p0 = ({id: 129})-[r2:r]->(n2 {id: 130})-[:s]->(:c {id: 131}) +RETURN 1 +$$) AS (value agtype); + +SELECT * FROM drop_graph('issue_2537', true); + -- -- delete graphs -- diff --git a/src/backend/executor/cypher_set.c b/src/backend/executor/cypher_set.c index 9b6bf51c5..f3c6f3e68 100644 --- a/src/backend/executor/cypher_set.c +++ b/src/backend/executor/cypher_set.c @@ -416,6 +416,10 @@ void apply_update_list(CustomScanState *node, HTAB *index_cache = NULL; HASHCTL idx_hashctl; + /* if scanTupleSlot is NULL, there is no data to update */ + if (scanTupleSlot == NULL) + return; + /* allocate an array to hold the last update index of each 'entity' */ luindex = palloc0(sizeof(int) * scanTupleSlot->tts_nvalid);