Skip to content

Commit 66d1541

Browse files
committed
Fix Issue 1691 - MERGE incorrectly creates multiple vertices (apache#1718)
Fixed issue 1691 where MERGE would incorrectly create multiple vertices. This only occurred when MERGE was being driven by a previous clause. NOTE: To be more correct, the issue is with creating duplicate paths. The reason this happened was due to the visibility of tuples that were created during the MERGE instance. It is not possible to add them in to be rescanned. Because of this limitation, it required adding the ability to MERGE to know what path an instance had already created. Added regression tests.
1 parent 007b4da commit 66d1541

File tree

4 files changed

+744
-38
lines changed

4 files changed

+744
-38
lines changed

Diff for: regress/expected/cypher_merge.out

+165-6
Original file line numberDiff line numberDiff line change
@@ -1263,8 +1263,8 @@ $$) as (a agtype);
12631263
---
12641264
(0 rows)
12651265

1266-
---
1267-
--- Issue 1630 MERGE using array not working in some cases
1266+
--
1267+
-- Issue 1630 - MERGE using array not working in some cases
12681268
--
12691269
SELECT * FROM create_graph('issue_1630');
12701270
NOTICE: graph "issue_1630" has been created
@@ -1387,7 +1387,151 @@ SELECT * FROM cypher('issue_1630',
13871387
{"id": 844424930131974, "label": "PERSION", "properties": {"last": "snow", "first": "jon"}}::vertex | {"last": "snow", "first": "jon"}
13881388
(1 row)
13891389

1390-
--clean up
1390+
--
1391+
-- Issue 1691 - MERGE incorrectly creates multiple vertices
1392+
--
1393+
SELECT * FROM create_graph('issue_1691');
1394+
NOTICE: graph "issue_1691" has been created
1395+
create_graph
1396+
--------------
1397+
1398+
(1 row)
1399+
1400+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
1401+
u
1402+
---
1403+
(0 rows)
1404+
1405+
-- should only create 2 distinct rows but return 4, the extra 2 being duplicates
1406+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo"] as n
1407+
MERGE (u {name: n})-[e:knows]->(v)
1408+
RETURN u, e, v $$) AS (u agtype, e agtype, v agtype);
1409+
u | e | v
1410+
-----------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------
1411+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1412+
{"id": 281474976710659, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131970, "label": "knows", "end_id": 281474976710660, "start_id": 281474976710659, "properties": {}}::edge | {"id": 281474976710660, "label": "", "properties": {}}::vertex
1413+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1414+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1415+
(4 rows)
1416+
1417+
-- should only return the same above 4 rows
1418+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo"] as n
1419+
MERGE (u {name: n})-[e:knows]->(v)
1420+
RETURN u, e, v $$) AS (u agtype, e agtype, v agtype);
1421+
u | e | v
1422+
-----------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------
1423+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1424+
{"id": 281474976710659, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131970, "label": "knows", "end_id": 281474976710660, "start_id": 281474976710659, "properties": {}}::edge | {"id": 281474976710660, "label": "", "properties": {}}::vertex
1425+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1426+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1427+
(4 rows)
1428+
1429+
-- should only return 2 distinct rows from above
1430+
SELECT * FROM cypher('issue_1691', $$ MATCH (u)-[e]->(v)
1431+
RETURN u, e, v $$) AS (u agtype, e agtype, v agtype);
1432+
u | e | v
1433+
-----------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------
1434+
{"id": 281474976710657, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", "properties": {}}::vertex
1435+
{"id": 281474976710659, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131970, "label": "knows", "end_id": 281474976710660, "start_id": 281474976710659, "properties": {}}::edge | {"id": 281474976710660, "label": "", "properties": {}}::vertex
1436+
(2 rows)
1437+
1438+
SELECT * FROM cypher('issue_1691', $$MATCH ()-[e]->() DELETE e $$) AS (a agtype);
1439+
a
1440+
---
1441+
(0 rows)
1442+
1443+
SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype);
1444+
a
1445+
---
1446+
(0 rows)
1447+
1448+
-- should only create 1 record but return 2, one a dup of the other
1449+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "foo"] AS each
1450+
MERGE (v:TEST {name: each})
1451+
RETURN v $$) AS (v agtype);
1452+
v
1453+
----------------------------------------------------------------------------------
1454+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1455+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1456+
(2 rows)
1457+
1458+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
1459+
u
1460+
----------------------------------------------------------------------------------
1461+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1462+
(1 row)
1463+
1464+
-- should just return 5 foo records that are all the same one
1465+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "foo", "bar", "foo", "bar"] AS each
1466+
MERGE (v:TEST {name: "foo"})
1467+
RETURN v $$) AS (v agtype);
1468+
v
1469+
----------------------------------------------------------------------------------
1470+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1471+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1472+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1473+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1474+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1475+
(5 rows)
1476+
1477+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
1478+
u
1479+
----------------------------------------------------------------------------------
1480+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1481+
(1 row)
1482+
1483+
-- should just return 5 bar records that are all the same one
1484+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "foo", "bar", "foo", "bar"] AS each
1485+
MERGE (v:TEST {name: "bar"})
1486+
RETURN v $$) AS (v agtype);
1487+
v
1488+
----------------------------------------------------------------------------------
1489+
{"id": 1125899906842626, "label": "TEST", "properties": {"name": "bar"}}::vertex
1490+
{"id": 1125899906842626, "label": "TEST", "properties": {"name": "bar"}}::vertex
1491+
{"id": 1125899906842626, "label": "TEST", "properties": {"name": "bar"}}::vertex
1492+
{"id": 1125899906842626, "label": "TEST", "properties": {"name": "bar"}}::vertex
1493+
{"id": 1125899906842626, "label": "TEST", "properties": {"name": "bar"}}::vertex
1494+
(5 rows)
1495+
1496+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
1497+
u
1498+
----------------------------------------------------------------------------------
1499+
{"id": 1125899906842625, "label": "TEST", "properties": {"name": "foo"}}::vertex
1500+
{"id": 1125899906842626, "label": "TEST", "properties": {"name": "bar"}}::vertex
1501+
(2 rows)
1502+
1503+
SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype);
1504+
a
1505+
---
1506+
(0 rows)
1507+
1508+
-- should create 2 rows foo->bar and bar->bar and the other 3 are just returning dups
1509+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo", "bar"] as n
1510+
MERGE (u {name: n})-[e1:knows]->(v {name: "bar"})-[e2:knows]->(w)
1511+
RETURN u, e1, v, e2, w $$) AS (u agtype, e1 agtype, v agtype, e2 agtype, w agtype);
1512+
u | e1 | v | e2 | w
1513+
-----------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------
1514+
{"id": 281474976710661, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131972, "label": "knows", "end_id": 281474976710662, "start_id": 281474976710661, "properties": {}}::edge | {"id": 281474976710662, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131971, "label": "knows", "end_id": 281474976710663, "start_id": 281474976710662, "properties": {}}::edge | {"id": 281474976710663, "label": "", "properties": {}}::vertex
1515+
{"id": 281474976710664, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131974, "label": "knows", "end_id": 281474976710665, "start_id": 281474976710664, "properties": {}}::edge | {"id": 281474976710665, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131973, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710665, "properties": {}}::edge | {"id": 281474976710666, "label": "", "properties": {}}::vertex
1516+
{"id": 281474976710661, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131972, "label": "knows", "end_id": 281474976710662, "start_id": 281474976710661, "properties": {}}::edge | {"id": 281474976710662, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131971, "label": "knows", "end_id": 281474976710663, "start_id": 281474976710662, "properties": {}}::edge | {"id": 281474976710663, "label": "", "properties": {}}::vertex
1517+
{"id": 281474976710661, "label": "", "properties": {"name": "foo"}}::vertex | {"id": 844424930131972, "label": "knows", "end_id": 281474976710662, "start_id": 281474976710661, "properties": {}}::edge | {"id": 281474976710662, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131971, "label": "knows", "end_id": 281474976710663, "start_id": 281474976710662, "properties": {}}::edge | {"id": 281474976710663, "label": "", "properties": {}}::vertex
1518+
{"id": 281474976710664, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131974, "label": "knows", "end_id": 281474976710665, "start_id": 281474976710664, "properties": {}}::edge | {"id": 281474976710665, "label": "", "properties": {"name": "bar"}}::vertex | {"id": 844424930131973, "label": "knows", "end_id": 281474976710666, "start_id": 281474976710665, "properties": {}}::edge | {"id": 281474976710666, "label": "", "properties": {}}::vertex
1519+
(5 rows)
1520+
1521+
-- clean up
1522+
SELECT * FROM cypher('issue_1691', $$MATCH ()-[e]->() DELETE e $$) AS (a agtype);
1523+
a
1524+
---
1525+
(0 rows)
1526+
1527+
SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype);
1528+
a
1529+
---
1530+
(0 rows)
1531+
1532+
--
1533+
-- clean up graphs
1534+
--
13911535
SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
13921536
a
13931537
---
@@ -1398,9 +1542,9 @@ SELECT * FROM cypher('issue_1630', $$MATCH (n) DETACH DELETE n $$) AS (a agtype)
13981542
---
13991543
(0 rows)
14001544

1401-
/*
1402-
* Clean up graph
1403-
*/
1545+
--
1546+
-- delete graphs
1547+
--
14041548
SELECT drop_graph('cypher_merge', true);
14051549
NOTICE: drop cascades to 19 other objects
14061550
DETAIL: drop cascades to table cypher_merge._ag_label_vertex
@@ -1439,3 +1583,18 @@ NOTICE: graph "issue_1630" has been dropped
14391583

14401584
(1 row)
14411585

1586+
SELECT drop_graph('issue_1691', true);
1587+
NOTICE: drop cascades to 4 other objects
1588+
DETAIL: drop cascades to table issue_1691._ag_label_vertex
1589+
drop cascades to table issue_1691._ag_label_edge
1590+
drop cascades to table issue_1691.knows
1591+
drop cascades to table issue_1691."TEST"
1592+
NOTICE: graph "issue_1691" has been dropped
1593+
drop_graph
1594+
------------
1595+
1596+
(1 row)
1597+
1598+
--
1599+
-- End
1600+
--

Diff for: regress/sql/cypher_merge.sql

+64-6
Original file line numberDiff line numberDiff line change
@@ -606,8 +606,8 @@ SELECT * FROM cypher('cypher_merge', $$
606606
CREATE (n), (m) WITH n AS r MERGE (m)
607607
$$) as (a agtype);
608608

609-
---
610-
--- Issue 1630 MERGE using array not working in some cases
609+
--
610+
-- Issue 1630 - MERGE using array not working in some cases
611611
--
612612
SELECT * FROM create_graph('issue_1630');
613613
SELECT * FROM cypher('issue_1630', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
@@ -670,13 +670,71 @@ SELECT * FROM cypher('issue_1630',
670670
MERGE (v:PERSION {first: cols.first, last: cols.last})
671671
RETURN v, cols $$) AS (v agtype, cols agtype);
672672

673+
--
674+
-- Issue 1691 - MERGE incorrectly creates multiple vertices
675+
--
676+
SELECT * FROM create_graph('issue_1691');
677+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
678+
679+
-- should only create 2 distinct rows but return 4, the extra 2 being duplicates
680+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo"] as n
681+
MERGE (u {name: n})-[e:knows]->(v)
682+
RETURN u, e, v $$) AS (u agtype, e agtype, v agtype);
683+
-- should only return the same above 4 rows
684+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo"] as n
685+
MERGE (u {name: n})-[e:knows]->(v)
686+
RETURN u, e, v $$) AS (u agtype, e agtype, v agtype);
687+
-- should only return 2 distinct rows from above
688+
SELECT * FROM cypher('issue_1691', $$ MATCH (u)-[e]->(v)
689+
RETURN u, e, v $$) AS (u agtype, e agtype, v agtype);
690+
691+
SELECT * FROM cypher('issue_1691', $$MATCH ()-[e]->() DELETE e $$) AS (a agtype);
692+
SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype);
693+
694+
-- should only create 1 record but return 2, one a dup of the other
695+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "foo"] AS each
696+
MERGE (v:TEST {name: each})
697+
RETURN v $$) AS (v agtype);
698+
699+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
700+
701+
-- should just return 5 foo records that are all the same one
702+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "foo", "bar", "foo", "bar"] AS each
703+
MERGE (v:TEST {name: "foo"})
704+
RETURN v $$) AS (v agtype);
705+
706+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
707+
708+
-- should just return 5 bar records that are all the same one
709+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "foo", "bar", "foo", "bar"] AS each
710+
MERGE (v:TEST {name: "bar"})
711+
RETURN v $$) AS (v agtype);
712+
713+
SELECT * FROM cypher('issue_1691', $$ MATCH (u) RETURN (u) $$) AS (u agtype);
714+
SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype);
715+
716+
-- should create 2 rows foo->bar and bar->bar and the other 3 are just returning dups
717+
SELECT * FROM cypher('issue_1691', $$ UNWIND ["foo", "bar", "foo", "foo", "bar"] as n
718+
MERGE (u {name: n})-[e1:knows]->(v {name: "bar"})-[e2:knows]->(w)
719+
RETURN u, e1, v, e2, w $$) AS (u agtype, e1 agtype, v agtype, e2 agtype, w agtype);
720+
721+
-- clean up
722+
SELECT * FROM cypher('issue_1691', $$MATCH ()-[e]->() DELETE e $$) AS (a agtype);
723+
SELECT * FROM cypher('issue_1691', $$MATCH (u) DELETE u $$) AS (a agtype);
673724

674-
--clean up
725+
--
726+
-- clean up graphs
727+
--
675728
SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
676729
SELECT * FROM cypher('issue_1630', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
677730

678-
/*
679-
* Clean up graph
680-
*/
731+
--
732+
-- delete graphs
733+
--
681734
SELECT drop_graph('cypher_merge', true);
682735
SELECT drop_graph('issue_1630', true);
736+
SELECT drop_graph('issue_1691', true);
737+
738+
--
739+
-- End
740+
--

0 commit comments

Comments
 (0)