Skip to content

Commit

Permalink
Fix #1884 - Ambiguous column reference error in SET clause
Browse files Browse the repository at this point in the history
The error occured due to SET transform not checking if the target entry
for the RHS item is already present in the query target list and added
the item to tl which resulted in variable name conflict.

Instead transformed the item and added to tl only if target entry for the
var name could not be found

Added regression tests
  • Loading branch information
Zainab-Saad committed May 17, 2024
1 parent 1491235 commit ee18bdf
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 15 deletions.
72 changes: 72 additions & 0 deletions regress/expected/cypher_set.out
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,64 @@ SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
---
(0 rows)

--
-- Issue 1884: column reference is ambiguous error when returning variable used in the RHS of SET clause
--
SELECT create_graph('issue_1884');
NOTICE: graph "issue_1884" has been created
create_graph
--------------

(1 row)

SELECT * FROM cypher('issue_1884', $$ CREATE (n:A), (m:B), (n)-[e:EDGE]->(m) $$) AS (result agtype);
result
--------
(0 rows)

SELECT * FROM cypher('issue_1884', $$ MATCH (n) SET n.node=n RETURN n $$) AS (result agtype);
result
------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "A", "properties": {"node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex
{"id": 1125899906842625, "label": "B", "properties": {"node": {"id": 1125899906842625, "label": "B", "properties": {}}::vertex}}::vertex
(2 rows)

SELECT * FROM cypher('issue_1884', $$ MATCH (n)-[e]->() SET n.edge=e SET e.startNode = n RETURN n, e $$) AS (n agtype, e agtype);
n | e
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "A", "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex | {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {"startNode": {"id": 844424930131969, "label": "A", "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex}}::edge
(1 row)

SELECT * FROM cypher('issue_1884', $$ MATCH (n) WITH n, {a: 1} AS m SET n.int=m.a RETURN n, m $$) AS (n agtype, m agtype);
n | m
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------
{"id": 844424930131969, "label": "A", "properties": {"int": 1, "edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex | {"a": 1}
{"id": 1125899906842625, "label": "B", "properties": {"int": 1, "node": {"id": 1125899906842625, "label": "B", "properties": {}}::vertex}}::vertex | {"a": 1}
(2 rows)

SELECT * FROM cypher('issue_1884', $$ MATCH (n)-[e]->(m) SET e.edge=e, e.endNode=m RETURN m, e $$) AS (m agtype, e agtype);
m | e
----------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 1125899906842625, "label": "B", "properties": {"int": 1, "node": {"id": 1125899906842625, "label": "B", "properties": {}}::vertex}}::vertex | {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {"startNode": {"id": 844424930131969, "label": "A", "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex}}::edge, "endNode": {"id": 1125899906842625, "label": "B", "properties": {"int": 1, "node": {"id": 1125899906842625, "label": "B", "properties": {}}::vertex}}::vertex, "startNode": {"id": 844424930131969, "label": "A", "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex}}::edge
(1 row)

SELECT * FROM cypher('issue_1884', $$ MATCH (n)-[e]->(m) WITH 1 AS a, n, e SET e.int=a, n.int=a RETURN a, n, e $$) AS (a agtype, n agtype, e agtype);
a | n | e
---+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | {"id": 844424930131969, "label": "A", "properties": {"int": 1, "edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex | {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {"int": 1, "edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {"startNode": {"id": 844424930131969, "label": "A", "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex}}::edge, "endNode": {"id": 1125899906842625, "label": "B", "properties": {"int": 1, "node": {"id": 1125899906842625, "label": "B", "properties": {}}::vertex}}::vertex, "startNode": {"id": 844424930131969, "label": "A", "properties": {"edge": {"id": 1407374883553281, "label": "EDGE", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge, "node": {"id": 844424930131969, "label": "A", "properties": {}}::vertex}}::vertex}}::edge
(1 row)

SELECT * FROM cypher('issue_1884', $$ MERGE (n: C) WITH [u IN [1, 2, 3]] AS u, n SET n.a = u RETURN n, u $$) AS (n agtype, u agtype);
n | u
--------------------------------------------------------------------------------+-----------
{"id": 1688849860263937, "label": "C", "properties": {"a": [1, 2, 3]}}::vertex | [1, 2, 3]
(1 row)

SELECT * FROM cypher('issue_1884', $$ MATCH (n) DETACH DELETE n $$) AS (result agtype);
result
--------
(0 rows)

--
-- Clean up
--
Expand Down Expand Up @@ -1038,6 +1096,20 @@ NOTICE: graph "issue_1634" has been dropped

(1 row)

SELECT drop_graph('issue_1884', true);
NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to table issue_1884._ag_label_vertex
drop cascades to table issue_1884._ag_label_edge
drop cascades to table issue_1884."A"
drop cascades to table issue_1884."B"
drop cascades to table issue_1884."EDGE"
drop cascades to table issue_1884."C"
NOTICE: graph "issue_1884" has been dropped
drop_graph
------------

(1 row)

--
-- End
--
18 changes: 18 additions & 0 deletions regress/sql/cypher_set.sql
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,23 @@ SELECT * FROM cypher('issue_1634', $$ MERGE (v:PERSION {id: '1'})

SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);

--
-- Issue 1884: column reference is ambiguous error when returning variable used in the RHS of SET clause
--

SELECT create_graph('issue_1884');

SELECT * FROM cypher('issue_1884', $$ CREATE (n:A), (m:B), (n)-[e:EDGE]->(m) $$) AS (result agtype);

SELECT * FROM cypher('issue_1884', $$ MATCH (n) SET n.node=n RETURN n $$) AS (result agtype);
SELECT * FROM cypher('issue_1884', $$ MATCH (n)-[e]->() SET n.edge=e SET e.startNode = n RETURN n, e $$) AS (n agtype, e agtype);
SELECT * FROM cypher('issue_1884', $$ MATCH (n) WITH n, {a: 1} AS m SET n.int=m.a RETURN n, m $$) AS (n agtype, m agtype);
SELECT * FROM cypher('issue_1884', $$ MATCH (n)-[e]->(m) SET e.edge=e, e.endNode=m RETURN m, e $$) AS (m agtype, e agtype);
SELECT * FROM cypher('issue_1884', $$ MATCH (n)-[e]->(m) WITH 1 AS a, n, e SET e.int=a, n.int=a RETURN a, n, e $$) AS (a agtype, n agtype, e agtype);
SELECT * FROM cypher('issue_1884', $$ MERGE (n: C) WITH [u IN [1, 2, 3]] AS u, n SET n.a = u RETURN n, u $$) AS (n agtype, u agtype);

SELECT * FROM cypher('issue_1884', $$ MATCH (n) DETACH DELETE n $$) AS (result agtype);

--
-- Clean up
--
Expand All @@ -387,6 +404,7 @@ DROP FUNCTION set_test;
SELECT drop_graph('cypher_set', true);
SELECT drop_graph('cypher_set_1', true);
SELECT drop_graph('issue_1634', true);
SELECT drop_graph('issue_1884', true);

--
-- End
Expand Down
63 changes: 48 additions & 15 deletions src/backend/parser/cypher_clause.c
Original file line number Diff line number Diff line change
Expand Up @@ -1701,6 +1701,7 @@ cypher_update_information *transform_cypher_set_item_list(
char *variable_name, *property_name;
String *property_node, *variable_node;
int is_entire_prop_update = 0; // true if a map is assigned to variable
bool rhs_var_exists = false;

// LHS of set_item must be a variable or an indirection.
if (IsA(set_item->prop, ColumnRef))
Expand Down Expand Up @@ -1836,27 +1837,59 @@ cypher_update_information *transform_cypher_set_item_list(
((cypher_map*)set_item->expr)->keep_null = set_item->is_add;
}

// create target entry for the new property value
item->prop_position = (AttrNumber)pstate->p_next_resno;
target_item = transform_cypher_item(cpstate, set_item->expr, NULL,
EXPR_KIND_SELECT_TARGET, NULL,
false);

if (has_a_cypher_list_comprehension_node(set_item->expr))
/*
* if the RHS is a ColumnRef and the TargetEntry for the variable
* already exists, no need to transform the RHS item,
* just add volatile wrapper to the target entry of the existing item
*/
if (IsA(set_item->expr, ColumnRef))
{
query->hasAggs = true;
ColumnRef *cref = (ColumnRef *)set_item->expr;
String *cref_str = linitial(cref->fields);
char *prop_name = cref_str->sval;

int prop_resno = get_target_entry_resno(query->targetList, prop_name);

if (prop_resno != -1)
{
// RHS variable already exists
rhs_var_exists = true;
item->prop_position = prop_resno;
target_item = findTarget(query->targetList, prop_name);
add_volatile_wrapper_to_target_entry(query->targetList,
item->prop_position);
}
}

if (!query->hasAggs && nodeTag(target_item->expr) == T_Aggref)
/*
* if a TargetEntry could not be found for the RHS item, transform the
* item and add to the tl
*/
if (!rhs_var_exists)
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Invalid use of aggregation in this context"),
parser_errposition(pstate, set_item->location)));
}
// create target entry for the new property value
item->prop_position = (AttrNumber)pstate->p_next_resno;

target_item = transform_cypher_item(cpstate, set_item->expr, NULL,
EXPR_KIND_SELECT_TARGET, NULL,
false);

if (has_a_cypher_list_comprehension_node(set_item->expr))
{
query->hasAggs = true;
}

target_item->expr = add_volatile_wrapper(target_item->expr);
if (!query->hasAggs && nodeTag(target_item->expr) == T_Aggref)
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Invalid use of aggregation in this context"),
parser_errposition(pstate, set_item->location)));
}

target_item->expr = add_volatile_wrapper(target_item->expr);
query->targetList = lappend(query->targetList, target_item);
}

query->targetList = lappend(query->targetList, target_item);
info->set_items = lappend(info->set_items, item);
}

Expand Down

0 comments on commit ee18bdf

Please sign in to comment.