From 162bf302b53687dd787a6c59f4b46574eec1120e Mon Sep 17 00:00:00 2001 From: John Gemignani <jrgemignani@gmail.com> Date: Fri, 27 Oct 2023 06:40:51 -0700 Subject: [PATCH] Fix Issue 945 - incorrect count(*) return values (#1288) (#1312) Fixed issue 945 where count(*) would have incorrect return values. NOTE - We need to re-evaluate if we want to use output_node or not. If output_node is set to false, then it basically short circuits match for instances where a variable isn't specified - MATCH () RETURN 0; MATCH () MATCH () RETURN 0; While, on the surface, this appears to be a good way to improve execution time of commands that won't do anything, it also causes chained commands to not work correctly. This is because a match without a variable will still feed its tuples to the next stage(s) even though they won't necessarily be sent to the output. For example, with count(*) - MATCH () RETURN count(*); MATCH () MATCH RETURN count(*); With output_node set to false, it won't send the tuples. We will likely need to remove all of the output_node logic. However, this needs to be reviewed. For now, we just set it to true and update the output of the regression tests. Updated regression tests to accomodate the change. Added new regression tests to cover overlooked cases. --- regress/expected/cypher_delete.out | 2 +- regress/expected/cypher_match.out | 282 +++++++++++++++++++++++++---- regress/expected/cypher_set.out | 2 +- regress/expected/expr.out | 16 +- regress/sql/cypher_match.sql | 38 ++++ src/backend/parser/cypher_clause.c | 18 +- 6 files changed, 312 insertions(+), 46 deletions(-) diff --git a/regress/expected/cypher_delete.out b/regress/expected/cypher_delete.out index 0a44ded2b..7ac07dfda 100644 --- a/regress/expected/cypher_delete.out +++ b/regress/expected/cypher_delete.out @@ -707,8 +707,8 @@ SELECT * FROM cypher('detach_delete', $$ MATCH ()-[e]->() RETURN e.name $$) as ( ------- "ab" "cd" - "nm" "am" + "nm" "pq" (5 rows) diff --git a/regress/expected/cypher_match.out b/regress/expected/cypher_match.out index 42a991521..3632d26db 100644 --- a/regress/expected/cypher_match.out +++ b/regress/expected/cypher_match.out @@ -144,9 +144,9 @@ $$) AS (a agtype); a --------------------------------------------------------------------------------------------------------------------------- {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (4 rows) SELECT * FROM cypher('cypher_match', $$ @@ -154,10 +154,10 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (a agtype); a --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge - {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge + {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge (4 rows) SELECT * FROM cypher('cypher_match', $$ @@ -174,8 +174,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (a agtype); a ---------------------------------------------------------------------------------- - {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex + {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex (2 rows) -- Right Path Test @@ -232,8 +232,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (a agtype); a --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) SELECT * FROM cypher('cypher_match', $$ @@ -241,8 +241,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (a agtype); a --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) SELECT * FROM cypher('cypher_match', $$ @@ -250,8 +250,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (a agtype); a --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) --Left Path Test @@ -308,8 +308,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (a agtype); a --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) --Divergent Path Tests @@ -348,10 +348,10 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (i agtype); i ---------------------------------------------------------------------------------- - {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex - {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex + {"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex + {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex (4 rows) SELECT * FROM cypher('cypher_match', $$ @@ -378,13 +378,13 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (i agtype); i ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex]::path [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex]::path [{"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path - [{"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path - [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex]::path + [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex]::path + [{"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path + [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex]::path (8 rows) @@ -402,8 +402,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (i agtype); i --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) SELECT * FROM cypher('cypher_match', $$ @@ -412,8 +412,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (i agtype); i --------------------------------------------------------------------------------------------------------------------------- - {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge + {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge (2 rows) SELECT * FROM cypher('cypher_match', $$ @@ -558,18 +558,18 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (i agtype, c agtype); i | c ---+----------- - | "initial" - 0 | "initial" - 1 | "initial" - | "middle" - 0 | "middle" - 1 | "middle" | "middle" 0 | "middle" 1 | "middle" | "end" 0 | "end" 1 | "end" + | "initial" + 0 | "initial" + 1 | "initial" + | "middle" + 0 | "middle" + 1 | "middle" (12 rows) -- @@ -708,12 +708,12 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (r0 agtype); r0 --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge - {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge - {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge + {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 2533274790395906, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685249, "properties": {}}::edge + {"id": 2533274790395905, "label": "e3", "end_id": 2251799813685250, "start_id": 2251799813685251, "properties": {}}::edge (6 rows) SELECT * FROM cypher('cypher_match', $$ @@ -721,8 +721,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (r0 agtype); r0 --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) SELECT * FROM cypher('cypher_match', $$ @@ -730,8 +730,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (r0 agtype); r0 --------------------------------------------------------------------------------------------------------------------------- - {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge (2 rows) SELECT * FROM cypher('cypher_match', $$ @@ -766,7 +766,6 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (r1 agtype); r1 --------------------------------------------------------------------------------------------------------------------------- - {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge @@ -776,8 +775,9 @@ $$) AS (r1 agtype); {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge - {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge (12 rows) SELECT * FROM cypher('cypher_match', $$ @@ -785,10 +785,10 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (r0 agtype, r1 agtype); r0 | r1 ---------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge - {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge | {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge | {"id": 1970324836974593, "label": "e2", "end_id": 1688849860263939, "start_id": 1688849860263938, "properties": {}}::edge (4 rows) -- valid variable reuse for vertex labels across clauses @@ -860,8 +860,8 @@ SELECT * FROM cypher('cypher_match', $$ $$) AS (r0 agtype); r0 --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge (2 rows) -- invalid variable reuse for vertex @@ -2310,13 +2310,31 @@ SELECT * FROM cypher('cypher_match', $$ MATCH () MATCH (_{name: "Dave"}) RETURN a --- 0 -(1 row) + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(10 rows) SELECT * FROM cypher('cypher_match', $$ MATCH () MATCH (_{name: "Dave"}) RETURN _ $$) as (a agtype); a ------------------------------------------------------------------------------ {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex -(1 row) + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex +(10 rows) SELECT * FROM cypher('cypher_match', $$ MATCH (my_age_default_{name: "Dave"}) RETURN my_age_default_$$) as (a agtype); a @@ -2328,7 +2346,16 @@ SELECT * FROM cypher('cypher_match', $$ MATCH () MATCH (my_age_default_{name: "D a ------------------------------------------------------------------------------ {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex -(1 row) + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex + {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex +(10 rows) -- these should fail as they are prefixed with _age_default_ which is only for internal use SELECT * FROM cypher('cypher_match', $$ MATCH (_age_default_) RETURN _age_default_ $$) as (a agtype); @@ -2583,6 +2610,180 @@ SELECT * FROM cypher('test_enable_containment', $$ EXPLAIN (COSTS OFF) MATCH (x: Filter: ((agtype_access_operator(VARIADIC ARRAY[properties, '"school"'::agtype, '"name"'::agtype]) = '"XYZ"'::agtype) AND (agtype_access_operator(VARIADIC ARRAY[properties, '"school"'::agtype, '"program"'::agtype, '"degree"'::agtype]) = '"BSc"'::agtype) AND (agtype_access_operator(VARIADIC ARRAY[properties, '"phone"'::agtype]) @> '[987654321]'::agtype) AND (agtype_access_operator(VARIADIC ARRAY[properties, '"parents"'::agtype]) @> '{}'::agtype)) (2 rows) +-- +-- Issue 945 +-- +SELECT create_graph('issue_945'); +NOTICE: graph "issue_945" has been created + create_graph +-------------- + +(1 row) + +SELECT * FROM cypher('issue_945', $$ + CREATE (a:Part {part_num: '123'}), + (b:Part {part_num: '345'}), + (c:Part {part_num: '456'}), + (d:Part {part_num: '789'}) + $$) as (result agtype); + result +-------- +(0 rows) + +-- should match 4 +SELECT * FROM cypher('issue_945', $$ + MATCH (a:Part) RETURN a + $$) as (result agtype); + result +------------------------------------------------------------------------------------- + {"id": 844424930131969, "label": "Part", "properties": {"part_num": "123"}}::vertex + {"id": 844424930131970, "label": "Part", "properties": {"part_num": "345"}}::vertex + {"id": 844424930131971, "label": "Part", "properties": {"part_num": "456"}}::vertex + {"id": 844424930131972, "label": "Part", "properties": {"part_num": "789"}}::vertex +(4 rows) + +-- each should return 4 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) RETURN count(*) $$) as (result agtype); + result +-------- + 4 +(1 row) + +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) RETURN count(*) $$) as (result agtype); + result +-------- + 4 +(1 row) + +-- each should return 4 rows of 0 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) RETURN 0 $$) as (result agtype); + result +-------- + 0 + 0 + 0 + 0 +(4 rows) + +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) RETURN 0 $$) as (result agtype); + result +-------- + 0 + 0 + 0 + 0 +(4 rows) + +-- each should return 16 rows of 0 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (:Part) RETURN 0 $$) as (result agtype); + result +-------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(16 rows) + +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (:Part) RETURN 0 $$) as (result agtype); + result +-------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(16 rows) + +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (b:Part) RETURN 0 $$) as (result agtype); + result +-------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(16 rows) + +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (b:Part) RETURN 0 $$) as (result agtype); + result +-------- + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 +(16 rows) + +-- each should return a count of 16 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (:Part) RETURN count(*) $$) as (result agtype); + result +-------- + 16 +(1 row) + +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (:Part) RETURN count(*) $$) as (result agtype); + result +-------- + 16 +(1 row) + +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (b:Part) RETURN count(*) $$) as (result agtype); + result +-------- + 16 +(1 row) + +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (b:Part) RETURN count(*) $$) as (result agtype); + result +-------- + 16 +(1 row) + -- -- Clean up -- @@ -2635,6 +2836,17 @@ NOTICE: graph "test_enable_containment" has been dropped (1 row) +SELECT drop_graph('issue_945', true); +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table issue_945._ag_label_vertex +drop cascades to table issue_945._ag_label_edge +drop cascades to table issue_945."Part" +NOTICE: graph "issue_945" has been dropped + drop_graph +------------ + +(1 row) + -- -- End -- diff --git a/regress/expected/cypher_set.out b/regress/expected/cypher_set.out index 1b391a0f3..5ef1ef3a1 100644 --- a/regress/expected/cypher_set.out +++ b/regress/expected/cypher_set.out @@ -167,8 +167,8 @@ SELECT * FROM cypher('cypher_set', $$MATCH ()-[n]->(:other_v) RETURN n$$) AS (a ---------------------------------------------------------------------------------------------------------------------------------------- {"id": 1125899906842625, "label": "e", "end_id": 1407374883553281, "start_id": 281474976710657, "properties": {"i": 3, "j": 20}}::edge {"id": 1125899906842626, "label": "e", "end_id": 1407374883553282, "start_id": 844424930131969, "properties": {"i": 3, "j": 20}}::edge - {"id": 1125899906842627, "label": "e", "end_id": 1407374883553283, "start_id": 844424930131971, "properties": {"i": 3, "j": 20}}::edge {"id": 1125899906842628, "label": "e", "end_id": 1407374883553284, "start_id": 844424930131970, "properties": {"i": 3, "j": 20}}::edge + {"id": 1125899906842627, "label": "e", "end_id": 1407374883553283, "start_id": 844424930131971, "properties": {"i": 3, "j": 20}}::edge (4 rows) SELECT * FROM cypher('cypher_set', $$ diff --git a/regress/expected/expr.out b/regress/expected/expr.out index f7497d57e..2357f9f66 100644 --- a/regress/expected/expr.out +++ b/regress/expected/expr.out @@ -2230,10 +2230,10 @@ SELECT * FROM cypher('expr', $$ MATCH (v) RETURN v $$) AS (expression agtype); SELECT * FROM cypher('expr', $$ MATCH ()-[e]-() RETURN e $$) AS (expression agtype); expression --------------------------------------------------------------------------------------------------------------------------- - {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge - {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge + {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge + {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge (4 rows) -- id() @@ -2242,10 +2242,10 @@ SELECT * FROM cypher('expr', $$ $$) AS (id agtype); id ------------------ - 1407374883553282 1407374883553281 - 1407374883553282 1407374883553281 + 1407374883553282 + 1407374883553282 (4 rows) SELECT * FROM cypher('expr', $$ @@ -2284,10 +2284,10 @@ SELECT * FROM cypher('expr', $$ $$) AS (start_id agtype); start_id ------------------ - 1125899906842625 1125899906842626 - 1125899906842625 1125899906842626 + 1125899906842625 + 1125899906842625 (4 rows) -- should return null @@ -2317,10 +2317,10 @@ SELECT * FROM cypher('expr', $$ $$) AS (end_id agtype); end_id ------------------ - 1125899906842626 1125899906842627 - 1125899906842626 1125899906842627 + 1125899906842626 + 1125899906842626 (4 rows) -- should return null diff --git a/regress/sql/cypher_match.sql b/regress/sql/cypher_match.sql index e4db18ac1..b9a766afa 100644 --- a/regress/sql/cypher_match.sql +++ b/regress/sql/cypher_match.sql @@ -1132,12 +1132,50 @@ SELECT count(*) FROM cypher('test_enable_containment', $$ MATCH (x:Customer {pho SELECT count(*) FROM cypher('test_enable_containment', $$ MATCH (x:Customer {phone:[654765876]}) RETURN x $$) as (a agtype); SELECT * FROM cypher('test_enable_containment', $$ EXPLAIN (COSTS OFF) MATCH (x:Customer {school:{name:'XYZ',program:{degree:'BSc'}},phone:[987654321],parents:{}}) RETURN x $$) as (a agtype); +-- +-- Issue 945 +-- +SELECT create_graph('issue_945'); +SELECT * FROM cypher('issue_945', $$ + CREATE (a:Part {part_num: '123'}), + (b:Part {part_num: '345'}), + (c:Part {part_num: '456'}), + (d:Part {part_num: '789'}) + $$) as (result agtype); + +-- should match 4 +SELECT * FROM cypher('issue_945', $$ + MATCH (a:Part) RETURN a + $$) as (result agtype); + +-- each should return 4 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) RETURN count(*) $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) RETURN count(*) $$) as (result agtype); + +-- each should return 4 rows of 0 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) RETURN 0 $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) RETURN 0 $$) as (result agtype); + +-- each should return 16 rows of 0 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (:Part) RETURN 0 $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (:Part) RETURN 0 $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (b:Part) RETURN 0 $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (b:Part) RETURN 0 $$) as (result agtype); + +-- each should return a count of 16 +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (:Part) RETURN count(*) $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (:Part) RETURN count(*) $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (:Part) MATCH (b:Part) RETURN count(*) $$) as (result agtype); +SELECT * FROM cypher('issue_945', $$ MATCH (a:Part) MATCH (b:Part) RETURN count(*) $$) as (result agtype); + + -- -- Clean up -- SELECT drop_graph('cypher_match', true); SELECT drop_graph('test_retrieve_var', true); SELECT drop_graph('test_enable_containment', true); +SELECT drop_graph('issue_945', true); -- -- End diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c index bf7b2bbea..ee6fa938b 100644 --- a/src/backend/parser/cypher_clause.c +++ b/src/backend/parser/cypher_clause.c @@ -4078,7 +4078,7 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query, node->name), parser_errposition(pstate, node->location))); } - + /* * Checks the previous clauses to see if the variable already * exists. @@ -4095,6 +4095,22 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query, output_node = (special_VLE_case && !node->name && !node->props) ? false : INCLUDE_NODE_IN_JOIN_TREE(path, node); + /* + * TODO + * + * We need to re-evaluate if we want to use output_node or not. + * If output_node is set to false, then it basically short circuits + * the match for instances where a variable isn't specified. While, + * on the surface, this appears to be a good way to improve + * execution time of commands that won't do anything, it also + * causes chained commands to not work correctly. This is because + * a match without a variable will still feed its tuples to the next + * stage(s). With this set to false, it won't. So we likely need to + * remove all of the output_node logic. This needs to be reviewed, + * though. For now, we just set it to true and update the output of + * the regression tests. + */ + output_node = true; /* transform vertex */ expr = transform_cypher_node(cpstate, node, &query->targetList,