From: Peter Eisentraut Date: Fri, 24 Apr 2026 07:12:03 +0000 (+0200) Subject: pg_get_viewdef() and lateral references in COLUMNS of GRAPH_TABLE X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=9d2979dd6856e160f35544d79eb11f2c68c30985;p=thirdparty%2Fpostgresql.git pg_get_viewdef() and lateral references in COLUMNS of GRAPH_TABLE Expressions in GRAPH_TABLE COLUMNS list may have lateral references. get_rule_expr() requires lateral namespaces to deparse such references. get_from_clause_item() does not pass them when processing the expressions in COLUMNS list causing ERROR "bogus varlevelsup: 0 offset 0". Fix get_from_clause_item() to pass input deparse_context containing lateral namespaces to get_rule_expr() instead of the dummy context. Author: Satyanarayana Narlapuram Reviewed-by: Ashutosh Bapat Discussion: https://www.postgresql.org/message-id/flat/CAHg%2BQDcLVa2iBnggkHxY4itZbXtDMfsYHEjnCUYe9hNbnxDi-w%40mail.gmail.com --- diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 78587d223cb..c781cdc84d3 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -13091,22 +13091,16 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) get_graph_pattern_def(rte->graph_pattern, context); appendStringInfoString(buf, " COLUMNS ("); { - ListCell *lc; bool first = true; - foreach(lc, rte->graph_table_columns) + foreach_node(TargetEntry, te, rte->graph_table_columns) { - TargetEntry *te = lfirst_node(TargetEntry, lc); - deparse_context context = {0}; - if (!first) appendStringInfoString(buf, ", "); else first = false; - context.buf = buf; - - get_rule_expr((Node *) te->expr, &context, false); + get_rule_expr((Node *) te->expr, context, false); appendStringInfoString(buf, " AS "); appendStringInfoString(buf, quote_identifier(te->resname)); } diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index 057f283c43d..12b8706b5f3 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -264,7 +264,6 @@ SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.addr ERROR: non-local element variable reference is not supported LINE 1: ...tomers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS ... ^ -DROP TABLE x1; CREATE TABLE v1 ( id int PRIMARY KEY, vname varchar(10), @@ -922,14 +921,25 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e (2 rows) -- ruleutils reverse parsing -CREATE VIEW customers_us AS SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US')-[IS customer_orders | customer_wishlists ]->(l IS orders | wishlists)-[ IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name)) ORDER BY customer_name, product_name; +-- The query in the view definition is intentionally complex to test one view with many +-- features like label disjunction, lateral references, WHERE clauses in graph +-- patterns. +CREATE VIEW customers_us AS +SELECT g.* FROM x1, + GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) + -[IS customer_orders | customer_wishlists ]-> + (l IS orders | wishlists)-[ IS list_items]->(p IS products) + COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + ORDER BY customer_name, product_name; SELECT pg_get_viewdef('customers_us'::regclass); - pg_get_viewdef --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - SELECT customer_name, + - product_name + - FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE ((c.address)::text = 'US'::text))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name))+ - ORDER BY customer_name, product_name; + pg_get_viewdef +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + SELECT g.customer_name, + + g.product_name, + + g.a + + FROM x1, + + GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g+ + ORDER BY g.customer_name, g.product_name; (1 row) -- test view/graph nesting diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 278064818ff..a5df4647b6a 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -162,7 +162,6 @@ SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers WHERE x1.ad -- reference is available SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers)-[IS customer_orders]->(o IS orders WHERE o.order_id = x1.a) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g; -- error SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(x1 IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid, x1.order_id)) g; -- error -DROP TABLE x1; CREATE TABLE v1 ( id int PRIMARY KEY, @@ -525,7 +524,16 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s)-[e]-(d) WHERE s.id = 3 COLUMNS (s.val, e SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- ruleutils reverse parsing -CREATE VIEW customers_us AS SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US')-[IS customer_orders | customer_wishlists ]->(l IS orders | wishlists)-[ IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name)) ORDER BY customer_name, product_name; +-- The query in the view definition is intentionally complex to test one view with many +-- features like label disjunction, lateral references, WHERE clauses in graph +-- patterns. +CREATE VIEW customers_us AS +SELECT g.* FROM x1, + GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) + -[IS customer_orders | customer_wishlists ]-> + (l IS orders | wishlists)-[ IS list_items]->(p IS products) + COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + ORDER BY customer_name, product_name; SELECT pg_get_viewdef('customers_us'::regclass); -- test view/graph nesting