]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix LATERAL references in GRAPH_TABLE with multi-label pattern
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 5 Jun 2026 07:27:31 +0000 (09:27 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 5 Jun 2026 07:27:51 +0000 (09:27 +0200)
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
src/test/regress/expected/graph_table.out
src/test/regress/sql/graph_table.sql

index 33d4e866d7435033c9063c65751073e92bfc4ce0..7db17bec312e97bfc774c0af9f2ce5fd5ff1de73 100644 (file)
@@ -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);
index cc6d80afd82ea6e032483833f18301729736303a..27b721d4480cbe060e1ab151cf8a1f6596fa0ea4 100644 (file)
@@ -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
index 0e381ec72bce32880b530bbae50dc7757e05313c..d7608100c95fb08219f5e62a1cd47dfa3fe68916 100644 (file)
@@ -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