From ce448a1b559b5a3b68a78e226277451ef76cb095 Mon Sep 17 00:00:00 2001
From: Satya Narlapuram <satyanarlapuram@gmail.com>
Date: Sat, 25 Apr 2026 16:43:33 +0000
Subject: [PATCH] Improve error message for graph variable references in subqueries
 within GRAPH_TABLE

When a subquery inside GRAPH_TABLE COLUMNS or MATCH WHERE references a
graph pattern variable, the error was a confusing "missing FROM-clause
entry for table".  Fix by walking the parentParseState chain in
transformGraphTablePropertyRef() to detect the graph variable and report
a clear "cannot be used in a subquery" error instead.
---
 src/backend/parser/parse_graphtable.c     | 28 +++++++++++++++++++++++
 src/test/regress/expected/graph_table.out | 15 ++++++++++++
 src/test/regress/sql/graph_table.sql      | 11 +++++++++
 3 files changed, 54 insertions(+)

diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c
index 73fbfb54..5e5da5bc 100644
--- a/src/backend/parser/parse_graphtable.c
+++ b/src/backend/parser/parse_graphtable.c
@@ -81,7 +81,35 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref)
 	GraphTableParseState *gpstate = pstate->p_graph_table_pstate;
 
 	if (!gpstate)
+	{
+		/*
+		 * No GRAPH_TABLE context in this ParseState; may be inside a
+		 * subquery whose sub-ParseState doesn't inherit p_graph_table_pstate.
+		 * Walk up the parent chain to detect graph variable references and
+		 * report a clear error instead of "missing FROM-clause entry".
+		 */
+		if (list_length(cref->fields) == 2)
+		{
+			Node	   *field1 = linitial(cref->fields);
+
+			if (!IsA(field1, A_Star))
+			{
+				for (ParseState *ps = pstate->parentParseState;
+					 ps != NULL;
+					 ps = ps->parentParseState)
+				{
+					if (ps->p_graph_table_pstate &&
+						list_member(ps->p_graph_table_pstate->variables, field1))
+						ereport(ERROR,
+								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+								 errmsg("graph pattern variable reference \"%s\" cannot be used in a subquery",
+										strVal(field1)),
+								 parser_errposition(pstate, cref->location)));
+				}
+			}
+		}
 		return NULL;
+	}
 
 	if (list_length(cref->fields) == 2)
 	{
diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out
index a2d7cdf3..d3c20610 100644
--- a/src/test/regress/expected/graph_table.out
+++ b/src/test/regress/expected/graph_table.out
@@ -1032,6 +1032,21 @@ SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE src.vprop1 >
 ERROR:  subqueries within GRAPH_TABLE reference are not supported
 SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE out_degree(src.vname) > (SELECT max(out_degree(nname)) FROM GRAPH_TABLE (g1 MATCH (node) COLUMNS (node.vname AS nname))) COLUMNS(src.vname AS sname, dest.vname AS dname));
 ERROR:  subqueries within GRAPH_TABLE reference are not supported
+-- subquery referencing graph variable in COLUMNS (should report clear error)
+SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS vl1)
+  COLUMNS (src.vname AS sname,
+           (SELECT count(*) FROM v1 WHERE vprop1 = src.vprop1) AS cnt)) gt;
+ERROR:  graph pattern variable reference "src" cannot be used in a subquery
+LINE 3: ...          (SELECT count(*) FROM v1 WHERE vprop1 = src.vprop1...
+                                                             ^
+-- EXISTS subquery referencing graph variable in MATCH WHERE
+SELECT * FROM GRAPH_TABLE (g1
+  MATCH (src IS vl1 WHERE EXISTS (
+    SELECT 1 FROM v1 WHERE vprop1 = src.vprop1))
+  COLUMNS (src.vname AS sname)) gt;
+ERROR:  graph pattern variable reference "src" cannot be used in a subquery
+LINE 3:     SELECT 1 FROM v1 WHERE vprop1 = src.vprop1))
+                                            ^
 -- GRAPH_TABLE subquery in HAVING clause
 SELECT src.vname, count(*)
   FROM v1 AS src
diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql
index b054dbdf..2521c4ca 100644
--- a/src/test/regress/sql/graph_table.sql
+++ b/src/test/regress/sql/graph_table.sql
@@ -590,6 +590,17 @@ SELECT * FROM customers co WHERE co.customer_id = (SELECT customer_id FROM GRAPH
 SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE src.vprop1 > (SELECT max(v1.vprop1) FROM v1) COLUMNS(src.vname AS sname, dest.vname AS dname));
 SELECT sname, dname FROM GRAPH_TABLE (g1 MATCH (src)->(dest) WHERE out_degree(src.vname) > (SELECT max(out_degree(nname)) FROM GRAPH_TABLE (g1 MATCH (node) COLUMNS (node.vname AS nname))) COLUMNS(src.vname AS sname, dest.vname AS dname));
 
+-- subquery referencing graph variable in COLUMNS (should report clear error)
+SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS vl1)
+  COLUMNS (src.vname AS sname,
+           (SELECT count(*) FROM v1 WHERE vprop1 = src.vprop1) AS cnt)) gt;
+
+-- EXISTS subquery referencing graph variable in MATCH WHERE
+SELECT * FROM GRAPH_TABLE (g1
+  MATCH (src IS vl1 WHERE EXISTS (
+    SELECT 1 FROM v1 WHERE vprop1 = src.vprop1))
+  COLUMNS (src.vname AS sname)) gt;
+
 -- GRAPH_TABLE subquery in HAVING clause
 SELECT src.vname, count(*)
   FROM v1 AS src
-- 
2.43.0

