From 0f0d9be9ba02fb90272d2053986f2b5aa4a0c25c Mon Sep 17 00:00:00 2001 From: Muhammad Taha Naveed Date: Mon, 9 Sep 2024 22:31:26 +0500 Subject: [PATCH] Fix issue 1955 - List comprehension in WHERE clause (#2094) - Fixed issue when MATCH clause variable is referenced inside list comprehension in WHERE clause or in property constraint. - Added regression tests. --- regress/expected/list_comprehension.out | 47 +++++++++++++++++++++++++ regress/sql/list_comprehension.sql | 8 +++++ src/backend/parser/cypher_expr.c | 3 +- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/regress/expected/list_comprehension.out b/regress/expected/list_comprehension.out index 0260fa5ef..bf5731d2a 100644 --- a/regress/expected/list_comprehension.out +++ b/regress/expected/list_comprehension.out @@ -617,6 +617,53 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WITH *, [i in [1,2,3]] a [1, 2, 3] (1 row) +-- Issue 1955 - variable reference in list comprehension +SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list=[i IN u.list] RETURN u $$) AS (result agtype); + result +--------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex + {"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex + {"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex + {"id": 281474976710657, "label": "", "properties": {"a": [], "b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex + {"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex + {"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex + {"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex + {"id": 844424930131969, "label": "csm_match", "properties": {"list": ["abc", "def", "ghi"]}}::vertex +(8 rows) + +SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list=[i IN u.list WHERE i>0] RETURN u $$) AS (result agtype); + result +-------------------------------------------------------------------------------------------------------- + {"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex + {"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex + {"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex + {"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex + {"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex +(5 rows) + +SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE size([e in u.list where e starts with "a"])>0 RETURN u $$) AS (result agtype); + result +------------------------------------------------------------------------------------------------------ + {"id": 844424930131969, "label": "csm_match", "properties": {"list": ["abc", "def", "ghi"]}}::vertex +(1 row) + +SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list | i+1]}) RETURN u $$) AS (result agtype); + result +-------------------------------------------------------------------------- + {"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex +(1 row) + +SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list WHERE i>0]}) RETURN u$$) AS (result agtype); + result +-------------------------------------------------------------------------------------------------------- + {"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex + {"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex + {"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex + {"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex + {"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex +(5 rows) + +-- Clean up SELECT * FROM drop_graph('list_comprehension', true); NOTICE: drop cascades to 4 other objects DETAIL: drop cascades to table list_comprehension._ag_label_vertex diff --git a/regress/sql/list_comprehension.sql b/regress/sql/list_comprehension.sql index cef92a22a..cb941a61b 100644 --- a/regress/sql/list_comprehension.sql +++ b/regress/sql/list_comprehension.sql @@ -157,4 +157,12 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WITH * WHERE u.list=[i I SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WITH * WITH *, [i in [1,2,3]] as list RETURN list LIMIT 1 $$) AS (result agtype); SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WITH *, [i in [1,2,3]] as list WITH * RETURN list LIMIT 1 $$) AS (result agtype); +-- Issue 1955 - variable reference in list comprehension +SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list=[i IN u.list] RETURN u $$) AS (result agtype); +SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list=[i IN u.list WHERE i>0] RETURN u $$) AS (result agtype); +SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE size([e in u.list where e starts with "a"])>0 RETURN u $$) AS (result agtype); +SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list | i+1]}) RETURN u $$) AS (result agtype); +SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list WHERE i>0]}) RETURN u$$) AS (result agtype); + +-- Clean up SELECT * FROM drop_graph('list_comprehension', true); \ No newline at end of file diff --git a/src/backend/parser/cypher_expr.c b/src/backend/parser/cypher_expr.c index 654223c92..f1651a017 100644 --- a/src/backend/parser/cypher_expr.c +++ b/src/backend/parser/cypher_expr.c @@ -1309,7 +1309,8 @@ static Node *transform_column_ref_for_indirection(cypher_parsestate *cpstate, } /* find the properties column of the NSI and return a var for it */ - node = scanNSItemForColumn(pstate, pnsi, 0, "properties", cr->location); + node = scanNSItemForColumn(pstate, pnsi, levels_up, "properties", + cr->location); /* * Error out if we couldn't find it.