postgres.git / summary / log / commit / refs

commit    4cb2a9863d89b320f37eb1bd76822f6f65e59311
Author:   Peter Eisentraut <peter@eisentraut.org>
Date:     Fri Jun 05 07:27:31 2026 +0000

    Fix LATERAL references in GRAPH_TABLE with multi-label pattern
    
    When rewriting a GRAPH_TABLE into a subquery,
    replace_property_refs_mutator() bumps levelsup of lateral references
    by one so that they reference outside the subquery.  This works for
    path patterns that result in only one path query.  Patterns that
    produce multiple path queries are rewritten as a UNION of path
    queries.  Since every path query becomes a subquery of the UNION
    statement, the levelsup of lateral references in those path queries
    need an additional bump.  This adjustment was missing resulting in the
    lateral references being interpreted as references in the UNION query
    itself.  This caused different symptoms like a crash in
    create_lateral_join_info() or error "plan should not reference
    subplan's variable".  The symptoms varied depending on the number of
    RangeTblEntries in the UNION statement.
    
    This commit adds the missing adjustment.
    
    Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
    Author: Satya Narlapuram <satyanarlapuram@gmail.com>
    Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
    Discussion: https://www.postgresql.org/message-id/flat/CAHg%2BQDfnLzsgjaQ_CiKSpP4JH3MKOiwoawEcCzXa9uYr45yiWw%40mail.gmail.com


src/backend/rewrite/rewriteGraphTable.c | 7 +++++++ src/test/regress/expected/graph_table.out | 14 ++++++++++++++ src/test/regress/sql/graph_table.sql | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index 33d4e866d74..7db17bec312 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -714,6 +714,13 @@ generate_setop_from_pathqueries(List *pathqueries, List **rtable, List **targetl lquery = linitial_node(Query, pathqueries); + /* + * Each path query will become a subquery of the UNION statement. So any + * Vars that already refer outside the path query must be adjusted for + * additional query level. + */ + IncrementVarSublevelsUp((Node *) lquery, 1, 1); + pni = addRangeTableEntryForSubquery(make_parsestate(NULL), lquery, NULL, false, false); *rtable = lappend(*rtable, pni->p_rte); diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cc6d80afd82..27b721d4480 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -254,6 +254,20 @@ SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers WHERE x1.ad 2 | customer1 | 1 | 1 (2 rows) +-- lateral reference with multi-label pattern, which is rewritten as UNION of +-- path queries +SELECT x1.a, g.* FROM x1, + GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.customer_id = x1.a)-[IS customer_orders | customer_wishlists]->(l IS lists)-[IS list_items]->(p IS products) + COLUMNS (x1.a AS outer_id, c.name AS customer_name, p.name AS product_name, l.list_type)) g + ORDER BY 1, 3, 4, 5; + a | outer_id | customer_name | product_name | list_type +---+----------+---------------+--------------+----------- + 1 | 1 | customer1 | product1 | order + 1 | 1 | customer1 | product2 | order + 2 | 2 | customer2 | product1 | order + 2 | 2 | customer2 | product1 | wishlist +(4 rows) + -- non-local property references are not allowed, even if a lateral column -- 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 diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 0e381ec72bc..d7608100c95 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -158,6 +158,12 @@ CREATE TABLE x1 (a int, address text); INSERT INTO x1 VALUES (1, 'one'), (2, 'two'); SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(o IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid)); SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers WHERE x1.address = 'US')-[IS customer_orders]->(o IS orders) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g; +-- lateral reference with multi-label pattern, which is rewritten as UNION of +-- path queries +SELECT x1.a, g.* FROM x1, + GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.customer_id = x1.a)-[IS customer_orders | customer_wishlists]->(l IS lists)-[IS list_items]->(p IS products) + COLUMNS (x1.a AS outer_id, c.name AS customer_name, p.name AS product_name, l.list_type)) g + ORDER BY 1, 3, 4, 5; -- non-local property references are not allowed, even if a lateral column -- 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 [parent: 72498a86989e]