Skip to content

Commit

Permalink
Fix #1513 - Invalid variable reuse in CREATE and MERGE clause (#1576)
Browse files Browse the repository at this point in the history
Allow the reuse of a previously declared vertex variable only if the succeeding
CREATE/MERGE vertex has associated edges
i.e CREATE (n) CREATE (n)             -- invalid
    CREATE (n) CREATE (n)-[:edge]->() -- valid

Fixed another invalid variable reuse where in a CREATE path, edge variable
could be duplicated which resulted in ambiguous reference error

Added regression tests
  • Loading branch information
Zainab-Saad authored Feb 8, 2024
1 parent feb8593 commit 601550b
Show file tree
Hide file tree
Showing 5 changed files with 373 additions and 23 deletions.
120 changes: 117 additions & 3 deletions regress/expected/cypher_create.out
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,9 @@ LINE 2: CREATE p=(p)
SELECT * FROM cypher('cypher_create', $$
CREATE p=() CREATE (p)
$$) as (a agtype);
ERROR: agtype must resolve to a vertex
ERROR: variable p already exists
LINE 2: CREATE p=() CREATE (p)
^
SELECT * FROM cypher('cypher_create', $$
CREATE p=(a)-[p:b]->(a)
$$) as (a agtype);
Expand Down Expand Up @@ -748,7 +750,7 @@ LINE 2: MATCH (p) CREATE (a)-[p:b]->(a)
SELECT * FROM cypher('cypher_create', $$
CREATE (a)-[e:new]->(p)-[e]->(a)
$$) as (a agtype);
ERROR: relationships must be specify a label in CREATE.
ERROR: variable e already exists
LINE 2: CREATE (a)-[e:new]->(p)-[e]->(a)
^
SELECT * FROM cypher('cypher_create', $$
Expand Down Expand Up @@ -793,13 +795,124 @@ $$) as (a agtype);
{"id": 5910974510923777, "label": "CrEaTe", "properties": {}}::vertex
(1 row)

--
-- the following tests should fail due to invalid variable reuse (issue#1513)
--
SELECT * FROM cypher('cypher_create', $$
CREATE (n) CREATE (n) RETURN n
$$) as (n agtype);
ERROR: variable n already exists
LINE 2: CREATE (n) CREATE (n) RETURN n
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n), (n) RETURN n
$$) as (n agtype);
ERROR: variable n already exists
LINE 2: CREATE (n), (n) RETURN n
^
SELECT * FROM cypher('cypher_create', $$
MATCH (n) CREATE (n) RETURN n
$$) as (n agtype);
ERROR: variable n already exists
LINE 2: MATCH (n) CREATE (n) RETURN n
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n), (n)-[:edge]->(n), (n) RETURN n
$$) as (n agtype);
ERROR: variable n already exists
LINE 2: CREATE (n), (n)-[:edge]->(n), (n) RETURN n
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
$$) as (n agtype);
ERROR: variable n already exists
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
$$) as (m agtype);
ERROR: variable m already exists
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
$$) as (e agtype);
ERROR: variable e already exists
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
$$) as (e agtype);
ERROR: variable e already exists
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
^
SELECT * FROM cypher('cypher_create', $$
WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n CREATE (n) RETURN n
$$) as (n agtype);
ERROR: variable n already exists
LINE 2: ..., label: "", properties: {}}::vertex AS n CREATE (n) RETURN ...
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
$$) as (e agtype);
ERROR: variable e already exists
LINE 2: CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
^
SELECT * FROM cypher('cypher_create', $$
CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
$$) as (e agtype);
ERROR: variable e already exists
LINE 2: CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RET...
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
$$) as (e agtype);
ERROR: variable e already exists
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
^
SELECT * FROM cypher('cypher_create', $$
WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->() RETURN e
$$) as (e agtype);
ERROR: variable e already exists
LINE 2: ...74976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->...
^
SELECT * FROM cypher('cypher_create', $$
CREATE (n) WITH n AS r CREATE (r) RETURN r
$$) as (r agtype);
ERROR: variable r already exists
LINE 2: CREATE (n) WITH n AS r CREATE (r) RETURN r
^
-- valid variable reuse
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e1:edge]->(m) CREATE (n)-[e2:edge]->(m)
$$) as (n agtype);
n
---
(0 rows)

SELECT * FROM cypher('cypher_create', $$
CREATE (n) WITH n AS r CREATE (r)-[e:edge]->() RETURN r
$$) as (r agtype);
r
----------------------------------------------------------------
{"id": 281474976710685, "label": "", "properties": {}}::vertex
(1 row)

SELECT * FROM cypher('cypher_create', $$
CREATE (n), (m) WITH n AS r CREATE (m) RETURN m
$$) as (m agtype);
m
----------------------------------------------------------------
{"id": 281474976710689, "label": "", "properties": {}}::vertex
(1 row)

--
-- Clean up
--
DROP TABLE simple_path;
DROP FUNCTION create_test;
SELECT drop_graph('cypher_create', true);
NOTICE: drop cascades to 19 other objects
NOTICE: drop cascades to 20 other objects
DETAIL: drop cascades to table cypher_create._ag_label_vertex
drop cascades to table cypher_create._ag_label_edge
drop cascades to table cypher_create.v
Expand All @@ -819,6 +932,7 @@ drop cascades to table cypher_create.n1
drop cascades to table cypher_create."CREATE"
drop cascades to table cypher_create."create"
drop cascades to table cypher_create."CrEaTe"
drop cascades to table cypher_create.edge
NOTICE: graph "cypher_create" has been dropped
drop_graph
------------
Expand Down
86 changes: 84 additions & 2 deletions regress/expected/cypher_merge.out
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,9 @@ SELECT * FROM cypher('cypher_merge', $$CREATE (n)$$) AS (a agtype);

--test query
SELECT * FROM cypher('cypher_merge', $$MATCH (n) OPTIONAL MATCH (n)-[:e]->(m) MERGE (m)$$) AS (a agtype);
ERROR: Existing variable m cannot be NULL in MERGE clause
ERROR: variable m already exists
LINE 1: ..., $$MATCH (n) OPTIONAL MATCH (n)-[:e]->(m) MERGE (m)$$) AS (...
^
-- validate only 1 vertex exits
SELECT * FROM cypher('cypher_merge', $$MATCH (n) RETURN n$$) AS (a agtype);
a
Expand Down Expand Up @@ -1182,6 +1184,85 @@ NOTICE: graph "issue_1219" has been dropped

(1 row)

--
-- the following tests should fail due to invalid variable reuse (issue#1513)
--
SELECT * FROM cypher('cypher_merge', $$
MERGE (n) MERGE (n) RETURN n
$$) as (a agtype);
ERROR: variable n already exists
LINE 2: MERGE (n) MERGE (n) RETURN n
^
SELECT * FROM cypher('cypher_merge', $$
MATCH (n) MERGE (n) RETURN n
$$) as (a agtype);
ERROR: variable n already exists
LINE 2: MATCH (n) MERGE (n) RETURN n
^
SELECT * FROM cypher('cypher_merge', $$
CREATE (n) MERGE (n) RETURN n
$$) as (a agtype);
ERROR: variable n already exists
LINE 2: CREATE (n) MERGE (n) RETURN n
^
SELECT * FROM cypher('cypher_merge', $$
MATCH (n) WITH n AS r MERGE (r) RETURN r
$$) as (a agtype);
ERROR: variable r already exists
LINE 2: MATCH (n) WITH n AS r MERGE (r) RETURN r
^
SELECT * FROM cypher('cypher_merge', $$
WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n MERGE (n) RETURN n
$$) as (a agtype);
ERROR: variable n already exists
LINE 2: ...7, label: "", properties: {}}::vertex AS n MERGE (n) RETURN ...
^
SELECT * FROM cypher('cypher_merge', $$
MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
$$) as (a agtype);
ERROR: variable n already exists
LINE 2: MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
^
SELECT * FROM cypher('cypher_merge', $$
MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
$$) as (a agtype);
ERROR: variable 'e' is for an edge
LINE 2: MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
^
SELECT * FROM cypher('cypher_merge', $$
WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->() RETURN e
$$) as (a agtype);
ERROR: variable e already exists
LINE 2: ...474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->...
^
SELECT * FROM cypher('cypher_merge', $$
MATCH (n) WITH n AS r MERGE (r) RETURN r
$$) as (a agtype);
ERROR: variable r already exists
LINE 2: MATCH (n) WITH n AS r MERGE (r) RETURN r
^
-- valid variable reuse
SELECT * FROM cypher('cypher_merge', $$
MERGE (n)-[e1:edge]->(m) MERGE (n)-[e2:edge]->()
$$) as (n agtype);
n
---
(0 rows)

SELECT * FROM cypher('cypher_merge', $$
MERGE (n) WITH n AS r MERGE (r)-[e:edge]->()
$$) as (a agtype);
a
---
(0 rows)

SELECT * FROM cypher('cypher_merge', $$
CREATE (n), (m) WITH n AS r MERGE (m)
$$) as (a agtype);
a
---
(0 rows)

--clean up
SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
a
Expand All @@ -1192,7 +1273,7 @@ SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtyp
* Clean up graph
*/
SELECT drop_graph('cypher_merge', true);
NOTICE: drop cascades to 18 other objects
NOTICE: drop cascades to 19 other objects
DETAIL: drop cascades to table cypher_merge._ag_label_vertex
drop cascades to table cypher_merge._ag_label_edge
drop cascades to table cypher_merge.e
Expand All @@ -1211,6 +1292,7 @@ drop cascades to table cypher_merge."P"
drop cascades to table cypher_merge."Q"
drop cascades to table cypher_merge."R"
drop cascades to table cypher_merge."E1"
drop cascades to table cypher_merge.edge
NOTICE: graph "cypher_merge" has been dropped
drop_graph
------------
Expand Down
72 changes: 72 additions & 0 deletions regress/sql/cypher_create.sql
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,78 @@ SELECT * FROM cypher('cypher_create', $$
RETURN a
$$) as (a agtype);

--
-- the following tests should fail due to invalid variable reuse (issue#1513)
--
SELECT * FROM cypher('cypher_create', $$
CREATE (n) CREATE (n) RETURN n
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n), (n) RETURN n
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
MATCH (n) CREATE (n) RETURN n
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n), (n)-[:edge]->(n), (n) RETURN n
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
$$) as (m agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
$$) as (e agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
$$) as (e agtype);

SELECT * FROM cypher('cypher_create', $$
WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n CREATE (n) RETURN n
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
$$) as (e agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
$$) as (e agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
$$) as (e agtype);

SELECT * FROM cypher('cypher_create', $$
WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->() RETURN e
$$) as (e agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n) WITH n AS r CREATE (r) RETURN r
$$) as (r agtype);

-- valid variable reuse
SELECT * FROM cypher('cypher_create', $$
CREATE (n)-[e1:edge]->(m) CREATE (n)-[e2:edge]->(m)
$$) as (n agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n) WITH n AS r CREATE (r)-[e:edge]->() RETURN r
$$) as (r agtype);

SELECT * FROM cypher('cypher_create', $$
CREATE (n), (m) WITH n AS r CREATE (m) RETURN m
$$) as (m agtype);

--
-- Clean up
--
Expand Down
Loading

0 comments on commit 601550b

Please sign in to comment.