From 8c75b0d94e507a60616d304e85153461cf96c2c5 Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Tue, 9 Jun 2026 20:14:13 +0530
Subject: [PATCH v2] Add the missing RTE_GRAPH_TABLE case to
 transformLockingClause()

A FOR UPDATE/SHARE clause that names a GRAPH_TABLE alias hit the
internal "unrecognized RTE type" error rather than a user-friendly
"FOR ... cannot be applied to a GRAPH_TABLE" message:

    CREATE TABLE v(id int PRIMARY KEY, vname text);
    CREATE PROPERTY GRAPH g VERTEX TABLES (v);
    SELECT * FROM GRAPH_TABLE(g MATCH (a) COLUMNS (a.vname)) gt
      FOR UPDATE OF gt;
    -- ERROR: unrecognized RTE type: 8

Add an explicit case for RTE_GRAPH_TABLE that raises
ERRCODE_FEATURE_NOT_SUPPORTED, matching the convention already used
for RTE_FUNCTION, RTE_TABLEFUNC, RTE_VALUES, RTE_CTE and
RTE_NAMEDTUPLESTORE.  Tests cover both the named-rel and the
all-rels code paths.

Author: SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>
Reported-by: SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>
Reviewed-by: Zhenwei Shang <a934172442@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://postgr.es/m/CAHg%2BQDcE9wp6nOEC3SCRQ90nrCO%3DQF%2BOZq1MG8Qc6hnusmogqw%40mail.gmail.com
---
 src/backend/parser/analyze.c              | 16 +++++++++++++++-
 src/test/regress/expected/graph_table.out | 16 ++++++++++++++++
 src/test/regress/sql/graph_table.sql      |  7 +++++++
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 93fa66ae57c..74294581ef9 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -3866,7 +3866,7 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
 										   allrels, true);
 					break;
 				default:
-					/* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
+					/* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE, GRAPH_TABLE */
 					break;
 			}
 		}
@@ -4001,6 +4001,20 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
 											LCS_asString(lc->strength)),
 									 parser_errposition(pstate, thisrel->location)));
 							break;
+						case RTE_GRAPH_TABLE:
+							/*
+							 * XXX: push the row mark down to the
+							 * relations the GRAPH_TABLE expands to
+							 * during rewriting.
+							 */
+							ereport(ERROR,
+									(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							/*------
+							  translator: %s is a SQL row locking clause such as FOR UPDATE */
+									 errmsg("%s cannot be applied to a GRAPH_TABLE",
+											LCS_asString(lc->strength)),
+									 parser_errposition(pstate, thisrel->location)));
+							break;
 
 							/* Shouldn't be possible to see RTE_RESULT here */
 
diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out
index 70d986e8ab0..d95752cf92c 100644
--- a/src/test/regress/expected/graph_table.out
+++ b/src/test/regress/expected/graph_table.out
@@ -1077,4 +1077,20 @@ SELECT src.vname, count(*) FROM v1 AS src
  v13   |     1
 (3 rows)
 
+-- FOR UPDATE/SHARE on GRAPH_TABLE: not supported when the alias is named
+-- in the locking clause; silently ignored when no relations are named.
+SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS vl1) COLUMNS (src.vname)) gt
+  FOR UPDATE OF gt;  -- error
+ERROR:  FOR UPDATE cannot be applied to a GRAPH_TABLE
+LINE 2:   FOR UPDATE OF gt;
+                        ^
+SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS vl1) COLUMNS (src.vname)) gt
+  FOR UPDATE;  -- ok, lock silently skipped for GRAPH_TABLE
+ vname 
+-------
+ v11
+ v12
+ v13
+(3 rows)
+
 -- leave the objects behind for pg_upgrade/pg_dump tests
diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql
index 0b44f70d7e7..3976db4e231 100644
--- a/src/test/regress/sql/graph_table.sql
+++ b/src/test/regress/sql/graph_table.sql
@@ -612,4 +612,11 @@ SELECT src.vname, count(*) FROM v1 AS src
   HAVING count(*) >= (SELECT count(*) FROM GRAPH_TABLE (g1 MATCH (a IS vl1 | vl2) COLUMNS (a.vname AS n)) WHERE n = src.vname)
   ORDER BY vname;
 
+-- FOR UPDATE/SHARE on GRAPH_TABLE: not supported when the alias is named
+-- in the locking clause; silently ignored when no relations are named.
+SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS vl1) COLUMNS (src.vname)) gt
+  FOR UPDATE OF gt;  -- error
+SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS vl1) COLUMNS (src.vname)) gt
+  FOR UPDATE;  -- ok, lock silently skipped for GRAPH_TABLE
+
 -- leave the objects behind for pg_upgrade/pg_dump tests
-- 
2.34.1

