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
