From ab2f9f6efe6cdf2fc75a0d54da999b8288f84a28 Mon Sep 17 00:00:00 2001
From: "Paul A. Jungwirth" <pj@illuminatedcomputing.com>
Date: Mon, 2 Nov 2026 13:51:38 -0800
Subject: [PATCH v2 2/2] Improve error message expanding foo.* in invalid
 location

When a column reference is not allowed, we should use the same error message for
zz.a and (ROW(zz.*)).a. But currently the first gives "cannot use column
reference" and the latter "missing FROM-clause entry". This commit updates
ExpandColumnRefStar so that we get the first error message in both cases.

Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
Backpatch-through: 14
---
 src/backend/parser/parse_target.c          | 7 +++++++
 src/test/regress/expected/create_table.out | 8 ++++++++
 src/test/regress/sql/create_table.sql      | 2 ++
 3 files changed, 17 insertions(+)

diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 728936b502e..7a17ecce272 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -1127,6 +1127,13 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
 	List	   *fields = cref->fields;
 	int			numnames = list_length(fields);
 
+	/*
+	 * Check to see if the column reference is in an invalid place, before
+	 * looking up the name, as transformColumnRef does.  expandNSItemVars
+	 * would catch it anyway, but only if the name resolves.
+	 */
+	checkColumnRefAllowed(pstate, cref->location);
+
 	if (numnames == 1)
 	{
 		/*
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index e7788b78c16..79d927b2dd0 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -133,6 +133,10 @@ CREATE TABLE default_expr_wholerow (id int DEFAULT (ROW(default_expr_wholerow.*)
 ERROR:  cannot use column reference in DEFAULT expression
 LINE 1: ... TABLE default_expr_wholerow (id int DEFAULT (ROW(default_ex...
                                                              ^
+CREATE TABLE default_expr_wholerow (id int DEFAULT (ROW(bar.*)).f1);
+ERROR:  cannot use column reference in DEFAULT expression
+LINE 1: ... TABLE default_expr_wholerow (id int DEFAULT (ROW(bar.*)).f1...
+                                                             ^
 -- but a row constructor with no column reference in it is fine, even one
 -- that expands a composite value that is not a table
 CREATE TABLE default_expr_rowexpr (id int DEFAULT (ROW(1)).f1);
@@ -469,6 +473,10 @@ CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((ROW(p
 ERROR:  cannot use column reference in partition bound expression
 LINE 1: ...fail PARTITION OF list_parted FOR VALUES IN ((ROW(part_bogus...
                                                              ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((ROW(somename.*)).f1);
+ERROR:  cannot use column reference in partition bound expression
+LINE 1: ...fail PARTITION OF list_parted FOR VALUES IN ((ROW(somename.*...
+                                                             ^
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a);
 ERROR:  cannot use column reference in partition bound expression
 LINE 1: ..._bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a);
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index df4ace75d78..8b1de65756d 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -83,6 +83,7 @@ CREATE TABLE default_expr_column (id int DEFAULT (bar.id));
 CREATE TABLE default_expr_agg_column (id int DEFAULT (avg(id)));
 -- a whole-row reference is a column reference too
 CREATE TABLE default_expr_wholerow (id int DEFAULT (ROW(default_expr_wholerow.*)).f1);
+CREATE TABLE default_expr_wholerow (id int DEFAULT (ROW(bar.*)).f1);
 -- but a row constructor with no column reference in it is fine, even one
 -- that expands a composite value that is not a table
 CREATE TABLE default_expr_rowexpr (id int DEFAULT (ROW(1)).f1);
@@ -328,6 +329,7 @@ CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somena
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename.somename);
 -- a whole-row reference to the partition being created is a column reference
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((ROW(part_bogus_expr_fail.*)).f1);
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((ROW(somename.*)).f1);
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a);
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(a));
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(somename));
-- 
2.47.3

