Hi all,

Thanks everyone for the reviews and discussion — I appreciate the time
spent looking at this.

Based on the feedback, I’ve prepared v4 of the patch with the following
updates:

Added a safety guard before calling PQescapeLiteral() to ensure pset.db is
non-NULL and in CONNECTION_OK state, falling back to ALL otherwise.

Kept the RESET completion limited to parameters actually present in
pg_db_role_setting, matching the behavior of other object-specific RESET
forms.

No changes to tab-completion APIs or libreadline interactions.

Regarding tests: I initially attempted to add TAP coverage via
src/bin/psql/t/010_tab_completion.pl, but based on Tom and Robert’s
comments[on discord], that file is intended to validate libreadline
mechanics rather than individual SQL completion cases. Since this change
does not introduce new readline behavior and SQL-based completion paths
during continuation prompts are not reliably exercised by the current test
harness, I’ve left the patch without TAP coverage.

I’m happy to adjust if there is a preferred place or pattern for testing
this kind of completion in the future.

Thanks again for the guidance.


On Mon, Dec 29, 2025 at 1:18 PM zengman <[email protected]> wrote:

> Hi,
>
> I got lots of indentation-related warnings when running git apply (see
> output below).
> Also, I found an issue: the RESET command unexpectedly displays
> "work_mem=16MB",
> which is not correct. I've made a minor fix by adding split_part and
> attached the v3 patch.
>
> Sorry my system is unable to indent with the 2.1.2 version as it is not
yet released,I’ve aligned the indentation with the surrounding code, and CI
/ buildfarm should catch any remaining formatting issues.

Could you please take a look and see if this modification is correct?
>

Yeah,thanks.

Regards,
Vasuki M
C-DAC,Chennai
From 076fe1e55aed2dc878853723883ee245e8db5451 Mon Sep 17 00:00:00 2001
From: Vasuki M <[email protected]>
Date: Tue, 6 Jan 2026 12:07:15 +0530
Subject: [PATCH] [PATCH] psql: Add tab-completion support for       ALTER ROLE
 ... IN      DATABASE ... SET/RESET forms This patch extends psql tab
 completion to support the ALTER ROLE <role> IN DATABASE <dbname> command
 form.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

After SET, psql completes with the list of configurable GUC variables,
matching the behavior of ALTER ROLE … SET.

After RESET, psql completes with configuration variables actually set
for the given (role, database) pair as recorded in
pg_db_role_setting, plus ALL, mirroring ALTER DATABASE … RESET
behavior.

SQL literal quoting is performed using PQescapeLiteral() via the
implicit connection (pset.db). A safety guard ensures a valid
connection is present before invoking it, falling back to ALL
otherwise.

No TAP tests are added, as this change does not introduce new
libreadline interactions and SQL-based completion paths are not
reliably exercised by the current test harness.

Vasuki M
---
 src/bin/psql/tab-complete.in.c | 66 +++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 29 deletions(-)

diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 5174d025531..c5fc2354797 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -2566,40 +2566,48 @@ match_previous_words(int pattern_id,
 	/* ALTER USER/ROLE <name> IN DATABASE <dbname> RESET */
 	else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny, "RESET"))
 	{
-		/*
-		 * Extract tokens: prev5 = role name prev2 = database name
-		 */
-		char	   *role = prev5_wd;
-		char	   *dbname = prev2_wd;
-		char	   *q_role;
-		char	   *q_dbname;
-		char	   *query;
-
-		/* Safe SQL literal quoting using libpq */
-		q_role = PQescapeLiteral(pset.db, role, strlen(role));
-		q_dbname = PQescapeLiteral(pset.db, dbname, strlen(dbname));
-		if (!q_role || !q_dbname)
+		if (!pset.db || PQstatus(pset.db) != CONNECTION_OK)
 		{
-			/* If quoting fails, just fall back to ALL */
-			if (q_role)
-				PQfreemem(q_role);
-			if (q_dbname)
-				PQfreemem(q_dbname);
 			COMPLETE_WITH("ALL");
 		}
 		else
 		{
-			query = psprintf(
-							 " SELECT split_part(unnest(setconfig), \'=\', 1) "
-							 "  FROM pg_db_role_setting "
-							 " WHERE setdatabase = "
-							 "       (SELECT oid FROM pg_database WHERE datname = %s) "
-							 "   AND setrole = %s::regrole",
-							 q_dbname, q_role);
-			COMPLETE_WITH_QUERY_PLUS(query, "ALL");
-			PQfreemem(q_role);
-			PQfreemem(q_dbname);
-			pfree(query);
+			/*
+			 * Extract tokens: prev5 = role name prev2 = database name
+			 */
+			char	   *role = prev5_wd;
+			char	   *dbname = prev2_wd;
+			char	   *q_role;
+			char	   *q_dbname;
+			char	   *query;
+
+			/* Safe SQL literal quoting using libpq */
+			q_role = PQescapeLiteral(pset.db, role, strlen(role));
+			q_dbname = PQescapeLiteral(pset.db, dbname, strlen(dbname));
+			if (!q_role || !q_dbname)
+			{
+				/* If quoting fails, just fall back to ALL */
+				if (q_role)
+					PQfreemem(q_role);
+				if (q_dbname)
+					PQfreemem(q_dbname);
+				COMPLETE_WITH("ALL");
+			}
+			else
+			{
+				query = psprintf(
+								 " SELECT split_part(unnest(setconfig), \'=\', 1) "
+								 "  FROM pg_db_role_setting "
+								 " WHERE setdatabase = "
+								 "       (SELECT oid FROM pg_database WHERE datname = %s) "
+								 "   AND setrole = %s::regrole",
+								 q_dbname, q_role);
+				COMPLETE_WITH_QUERY_PLUS(query, "ALL");
+				PQfreemem(q_role);
+				PQfreemem(q_dbname);
+				pfree(query);
+			}
+
 		}
 	}
 
-- 
2.43.0

Reply via email to