From 1515cc70ba858c8991dbf2fca9b3b835bff25d78 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Fri, 8 May 2026 15:53:23 +0800
Subject: [PATCH v2] ddlutils: add hints for catalog privilege failures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

pg_get_role_ddl_internal() and pg_get_tablespace_ddl_internal() require
SELECT privilege on their underlying catalogs before reading object
properties.  When this privilege check fails, the error message reports
the user-facing object, such as the role or tablespace whose DDL was
requested, but it does not tell the user which privilege is actually
missing.

Add errhint() messages to explain that SELECT on the relevant catalog is
needed to read the object properties.  This keeps the primary error
message focused on the requested object, while giving users a concrete
way to resolve the failure.

Author: Chao Li <lic@highgo.com>
Reviewed-by: Jim Jones <jim.jones@uni-muenster.de>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Zhenwei Shang <a934172442@gmail.com>
Discussion: https://postgr.es/m/53D05145-CE87-424F-A492-BB22A09BBE11@gmail.com
---
 src/backend/utils/adt/ddlutils.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/adt/ddlutils.c b/src/backend/utils/adt/ddlutils.c
index d6f55c48f37..db72854b1c5 100644
--- a/src/backend/utils/adt/ddlutils.c
+++ b/src/backend/utils/adt/ddlutils.c
@@ -342,8 +342,10 @@ pg_get_role_ddl_internal(Oid roleid, bool pretty, bool memberships)
 	{
 		ReleaseSysCache(tuple);
 		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("permission denied for role %s", rolname)));
+				errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				errmsg("permission denied for role \"%s\"", rolname),
+				errhint("Grant SELECT on catalog \"%s\" to read role properties.",
+						get_rel_name(AuthIdRelationId)));
 	}
 
 	/*
@@ -681,7 +683,12 @@ pg_get_tablespace_ddl_internal(Oid tsid, bool pretty, bool no_owner)
 	if (pg_class_aclcheck(TableSpaceRelationId, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
 	{
 		ReleaseSysCache(tuple);
-		aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, spcname);
+		ereport(ERROR,
+				errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				errmsg("permission denied for tablespace \"%s\"",
+					   spcname),
+				errhint("Grant SELECT on catalog \"%s\" to read tablespace properties.",
+						get_rel_name(TableSpaceRelationId)));
 	}
 
 	/*
-- 
2.50.1 (Apple Git-155)

