Skip to content

Commit 8755072

Browse files
authored
Fix #1513 - Invalid variable reuse in CREATE and MERGE clause (#1515)
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
1 parent cb3efdb commit 8755072

File tree

5 files changed

+373
-23
lines changed

5 files changed

+373
-23
lines changed

regress/expected/cypher_create.out

+117-3
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,9 @@ LINE 2: CREATE p=(p)
714714
SELECT * FROM cypher('cypher_create', $$
715715
CREATE p=() CREATE (p)
716716
$$) as (a agtype);
717-
ERROR: agtype must resolve to a vertex
717+
ERROR: variable p already exists
718+
LINE 2: CREATE p=() CREATE (p)
719+
^
718720
SELECT * FROM cypher('cypher_create', $$
719721
CREATE p=(a)-[p:b]->(a)
720722
$$) as (a agtype);
@@ -748,7 +750,7 @@ LINE 2: MATCH (p) CREATE (a)-[p:b]->(a)
748750
SELECT * FROM cypher('cypher_create', $$
749751
CREATE (a)-[e:new]->(p)-[e]->(a)
750752
$$) as (a agtype);
751-
ERROR: relationships must be specify a label in CREATE.
753+
ERROR: variable e already exists
752754
LINE 2: CREATE (a)-[e:new]->(p)-[e]->(a)
753755
^
754756
SELECT * FROM cypher('cypher_create', $$
@@ -793,13 +795,124 @@ $$) as (a agtype);
793795
{"id": 5910974510923777, "label": "CrEaTe", "properties": {}}::vertex
794796
(1 row)
795797

798+
--
799+
-- the following tests should fail due to invalid variable reuse (issue#1513)
800+
--
801+
SELECT * FROM cypher('cypher_create', $$
802+
CREATE (n) CREATE (n) RETURN n
803+
$$) as (n agtype);
804+
ERROR: variable n already exists
805+
LINE 2: CREATE (n) CREATE (n) RETURN n
806+
^
807+
SELECT * FROM cypher('cypher_create', $$
808+
CREATE (n), (n) RETURN n
809+
$$) as (n agtype);
810+
ERROR: variable n already exists
811+
LINE 2: CREATE (n), (n) RETURN n
812+
^
813+
SELECT * FROM cypher('cypher_create', $$
814+
MATCH (n) CREATE (n) RETURN n
815+
$$) as (n agtype);
816+
ERROR: variable n already exists
817+
LINE 2: MATCH (n) CREATE (n) RETURN n
818+
^
819+
SELECT * FROM cypher('cypher_create', $$
820+
CREATE (n), (n)-[:edge]->(n), (n) RETURN n
821+
$$) as (n agtype);
822+
ERROR: variable n already exists
823+
LINE 2: CREATE (n), (n)-[:edge]->(n), (n) RETURN n
824+
^
825+
SELECT * FROM cypher('cypher_create', $$
826+
CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
827+
$$) as (n agtype);
828+
ERROR: variable n already exists
829+
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
830+
^
831+
SELECT * FROM cypher('cypher_create', $$
832+
CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
833+
$$) as (m agtype);
834+
ERROR: variable m already exists
835+
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
836+
^
837+
SELECT * FROM cypher('cypher_create', $$
838+
CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
839+
$$) as (e agtype);
840+
ERROR: variable e already exists
841+
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
842+
^
843+
SELECT * FROM cypher('cypher_create', $$
844+
CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
845+
$$) as (e agtype);
846+
ERROR: variable e already exists
847+
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
848+
^
849+
SELECT * FROM cypher('cypher_create', $$
850+
WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n CREATE (n) RETURN n
851+
$$) as (n agtype);
852+
ERROR: variable n already exists
853+
LINE 2: ..., label: "", properties: {}}::vertex AS n CREATE (n) RETURN ...
854+
^
855+
SELECT * FROM cypher('cypher_create', $$
856+
CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
857+
$$) as (e agtype);
858+
ERROR: variable e already exists
859+
LINE 2: CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
860+
^
861+
SELECT * FROM cypher('cypher_create', $$
862+
CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
863+
$$) as (e agtype);
864+
ERROR: variable e already exists
865+
LINE 2: CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RET...
866+
^
867+
SELECT * FROM cypher('cypher_create', $$
868+
CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
869+
$$) as (e agtype);
870+
ERROR: variable e already exists
871+
LINE 2: CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
872+
^
873+
SELECT * FROM cypher('cypher_create', $$
874+
WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->() RETURN e
875+
$$) as (e agtype);
876+
ERROR: variable e already exists
877+
LINE 2: ...74976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->...
878+
^
879+
SELECT * FROM cypher('cypher_create', $$
880+
CREATE (n) WITH n AS r CREATE (r) RETURN r
881+
$$) as (r agtype);
882+
ERROR: variable r already exists
883+
LINE 2: CREATE (n) WITH n AS r CREATE (r) RETURN r
884+
^
885+
-- valid variable reuse
886+
SELECT * FROM cypher('cypher_create', $$
887+
CREATE (n)-[e1:edge]->(m) CREATE (n)-[e2:edge]->(m)
888+
$$) as (n agtype);
889+
n
890+
---
891+
(0 rows)
892+
893+
SELECT * FROM cypher('cypher_create', $$
894+
CREATE (n) WITH n AS r CREATE (r)-[e:edge]->() RETURN r
895+
$$) as (r agtype);
896+
r
897+
----------------------------------------------------------------
898+
{"id": 281474976710685, "label": "", "properties": {}}::vertex
899+
(1 row)
900+
901+
SELECT * FROM cypher('cypher_create', $$
902+
CREATE (n), (m) WITH n AS r CREATE (m) RETURN m
903+
$$) as (m agtype);
904+
m
905+
----------------------------------------------------------------
906+
{"id": 281474976710689, "label": "", "properties": {}}::vertex
907+
(1 row)
908+
796909
--
797910
-- Clean up
798911
--
799912
DROP TABLE simple_path;
800913
DROP FUNCTION create_test;
801914
SELECT drop_graph('cypher_create', true);
802-
NOTICE: drop cascades to 19 other objects
915+
NOTICE: drop cascades to 20 other objects
803916
DETAIL: drop cascades to table cypher_create._ag_label_vertex
804917
drop cascades to table cypher_create._ag_label_edge
805918
drop cascades to table cypher_create.v
@@ -819,6 +932,7 @@ drop cascades to table cypher_create.n1
819932
drop cascades to table cypher_create."CREATE"
820933
drop cascades to table cypher_create."create"
821934
drop cascades to table cypher_create."CrEaTe"
935+
drop cascades to table cypher_create.edge
822936
NOTICE: graph "cypher_create" has been dropped
823937
drop_graph
824938
------------

regress/expected/cypher_merge.out

+84-2
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,9 @@ SELECT * FROM cypher('cypher_merge', $$CREATE (n)$$) AS (a agtype);
817817

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

11831185
(1 row)
11841186

1187+
--
1188+
-- the following tests should fail due to invalid variable reuse (issue#1513)
1189+
--
1190+
SELECT * FROM cypher('cypher_merge', $$
1191+
MERGE (n) MERGE (n) RETURN n
1192+
$$) as (a agtype);
1193+
ERROR: variable n already exists
1194+
LINE 2: MERGE (n) MERGE (n) RETURN n
1195+
^
1196+
SELECT * FROM cypher('cypher_merge', $$
1197+
MATCH (n) MERGE (n) RETURN n
1198+
$$) as (a agtype);
1199+
ERROR: variable n already exists
1200+
LINE 2: MATCH (n) MERGE (n) RETURN n
1201+
^
1202+
SELECT * FROM cypher('cypher_merge', $$
1203+
CREATE (n) MERGE (n) RETURN n
1204+
$$) as (a agtype);
1205+
ERROR: variable n already exists
1206+
LINE 2: CREATE (n) MERGE (n) RETURN n
1207+
^
1208+
SELECT * FROM cypher('cypher_merge', $$
1209+
MATCH (n) WITH n AS r MERGE (r) RETURN r
1210+
$$) as (a agtype);
1211+
ERROR: variable r already exists
1212+
LINE 2: MATCH (n) WITH n AS r MERGE (r) RETURN r
1213+
^
1214+
SELECT * FROM cypher('cypher_merge', $$
1215+
WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n MERGE (n) RETURN n
1216+
$$) as (a agtype);
1217+
ERROR: variable n already exists
1218+
LINE 2: ...7, label: "", properties: {}}::vertex AS n MERGE (n) RETURN ...
1219+
^
1220+
SELECT * FROM cypher('cypher_merge', $$
1221+
MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
1222+
$$) as (a agtype);
1223+
ERROR: variable n already exists
1224+
LINE 2: MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
1225+
^
1226+
SELECT * FROM cypher('cypher_merge', $$
1227+
MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
1228+
$$) as (a agtype);
1229+
ERROR: variable 'e' is for an edge
1230+
LINE 2: MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
1231+
^
1232+
SELECT * FROM cypher('cypher_merge', $$
1233+
WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->() RETURN e
1234+
$$) as (a agtype);
1235+
ERROR: variable e already exists
1236+
LINE 2: ...474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->...
1237+
^
1238+
SELECT * FROM cypher('cypher_merge', $$
1239+
MATCH (n) WITH n AS r MERGE (r) RETURN r
1240+
$$) as (a agtype);
1241+
ERROR: variable r already exists
1242+
LINE 2: MATCH (n) WITH n AS r MERGE (r) RETURN r
1243+
^
1244+
-- valid variable reuse
1245+
SELECT * FROM cypher('cypher_merge', $$
1246+
MERGE (n)-[e1:edge]->(m) MERGE (n)-[e2:edge]->()
1247+
$$) as (n agtype);
1248+
n
1249+
---
1250+
(0 rows)
1251+
1252+
SELECT * FROM cypher('cypher_merge', $$
1253+
MERGE (n) WITH n AS r MERGE (r)-[e:edge]->()
1254+
$$) as (a agtype);
1255+
a
1256+
---
1257+
(0 rows)
1258+
1259+
SELECT * FROM cypher('cypher_merge', $$
1260+
CREATE (n), (m) WITH n AS r MERGE (m)
1261+
$$) as (a agtype);
1262+
a
1263+
---
1264+
(0 rows)
1265+
11851266
--clean up
11861267
SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
11871268
a
@@ -1192,7 +1273,7 @@ SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtyp
11921273
* Clean up graph
11931274
*/
11941275
SELECT drop_graph('cypher_merge', true);
1195-
NOTICE: drop cascades to 18 other objects
1276+
NOTICE: drop cascades to 19 other objects
11961277
DETAIL: drop cascades to table cypher_merge._ag_label_vertex
11971278
drop cascades to table cypher_merge._ag_label_edge
11981279
drop cascades to table cypher_merge.e
@@ -1211,6 +1292,7 @@ drop cascades to table cypher_merge."P"
12111292
drop cascades to table cypher_merge."Q"
12121293
drop cascades to table cypher_merge."R"
12131294
drop cascades to table cypher_merge."E1"
1295+
drop cascades to table cypher_merge.edge
12141296
NOTICE: graph "cypher_merge" has been dropped
12151297
drop_graph
12161298
------------

regress/sql/cypher_create.sql

+72
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,78 @@ SELECT * FROM cypher('cypher_create', $$
403403
RETURN a
404404
$$) as (a agtype);
405405

406+
--
407+
-- the following tests should fail due to invalid variable reuse (issue#1513)
408+
--
409+
SELECT * FROM cypher('cypher_create', $$
410+
CREATE (n) CREATE (n) RETURN n
411+
$$) as (n agtype);
412+
413+
SELECT * FROM cypher('cypher_create', $$
414+
CREATE (n), (n) RETURN n
415+
$$) as (n agtype);
416+
417+
SELECT * FROM cypher('cypher_create', $$
418+
MATCH (n) CREATE (n) RETURN n
419+
$$) as (n agtype);
420+
421+
SELECT * FROM cypher('cypher_create', $$
422+
CREATE (n), (n)-[:edge]->(n), (n) RETURN n
423+
$$) as (n agtype);
424+
425+
SELECT * FROM cypher('cypher_create', $$
426+
CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
427+
$$) as (n agtype);
428+
429+
SELECT * FROM cypher('cypher_create', $$
430+
CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
431+
$$) as (m agtype);
432+
433+
SELECT * FROM cypher('cypher_create', $$
434+
CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
435+
$$) as (e agtype);
436+
437+
SELECT * FROM cypher('cypher_create', $$
438+
CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
439+
$$) as (e agtype);
440+
441+
SELECT * FROM cypher('cypher_create', $$
442+
WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n CREATE (n) RETURN n
443+
$$) as (n agtype);
444+
445+
SELECT * FROM cypher('cypher_create', $$
446+
CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
447+
$$) as (e agtype);
448+
449+
SELECT * FROM cypher('cypher_create', $$
450+
CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
451+
$$) as (e agtype);
452+
453+
SELECT * FROM cypher('cypher_create', $$
454+
CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
455+
$$) as (e agtype);
456+
457+
SELECT * FROM cypher('cypher_create', $$
458+
WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->() RETURN e
459+
$$) as (e agtype);
460+
461+
SELECT * FROM cypher('cypher_create', $$
462+
CREATE (n) WITH n AS r CREATE (r) RETURN r
463+
$$) as (r agtype);
464+
465+
-- valid variable reuse
466+
SELECT * FROM cypher('cypher_create', $$
467+
CREATE (n)-[e1:edge]->(m) CREATE (n)-[e2:edge]->(m)
468+
$$) as (n agtype);
469+
470+
SELECT * FROM cypher('cypher_create', $$
471+
CREATE (n) WITH n AS r CREATE (r)-[e:edge]->() RETURN r
472+
$$) as (r agtype);
473+
474+
SELECT * FROM cypher('cypher_create', $$
475+
CREATE (n), (m) WITH n AS r CREATE (m) RETURN m
476+
$$) as (m agtype);
477+
406478
--
407479
-- Clean up
408480
--

0 commit comments

Comments
 (0)