From e182cc2bea150680f5664cac3cec70c5e9842418 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Date: Tue, 2 Jun 2026 15:51:41 +0530
Subject: [PATCH v20260602 10/10] 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 reference outside the subquery. This works for path patterns
which result in only one path query.  Patterns that produce multiple
path queries are rewritten as UNION of path queries. Since every path
query becomes a subquery of UNION statement, the levelsup of lateral
references in those path queries need 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 upon 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/CAHg+QDfnLzsgjaQ_CiKSpP4JH3MKOiwoawEcCzXa9uYr45yiWw@mail.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 2292ca6dcee..7df7f9fd70a 100644
--- a/src/backend/rewrite/rewriteGraphTable.c
+++ b/src/backend/rewrite/rewriteGraphTable.c
@@ -720,6 +720,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 475ac20d376..c229212cb51 100644
--- a/src/test/regress/expected/graph_table.out
+++ b/src/test/regress/expected/graph_table.out
@@ -263,6 +263,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 5412f10ac3c..e30c908dccc 100644
--- a/src/test/regress/sql/graph_table.sql
+++ b/src/test/regress/sql/graph_table.sql
@@ -160,6 +160,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
-- 
2.34.1

