psql: add \dconfig command to show server's configuration parameters.

Plain \dconfig is basically equivalent to SHOW except that you can
give it a pattern with wildcards, either to match multiple GUCs or
because you don't exactly remember the name you want.

\dconfig+ adds type, context, and access-privilege information,
mainly because every other kind of object privilege has a psql command
to show it, so GUC privileges should too.  (A form of this command was
in some versions of the patch series leading up to commit a0ffa885e.
We pulled it out then because of doubts that the design and code were
up to snuff, but I think subsequent work has resolved that.)

In passing, fix incorrect completion of GUC names in GRANT/REVOKE
ON PARAMETER: a0ffa885e neglected to use the VERBATIM form of
COMPLETE_WITH_QUERY, so it misbehaved for custom (qualified) GUC
names.

Mark Dilger and Tom Lane

Discussion: https://postgr.es/m/3118455.1649267333@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2022-04-07 17:09:44 -04:00
parent 16acf7f1aa
commit 3e707fbb40
10 changed files with 127 additions and 6 deletions

View File

@ -2205,7 +2205,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
<entry><literal>PARAMETER</literal></entry>
<entry><literal>sA</literal></entry>
<entry>none</entry>
<entry>none</entry>
<entry><literal>\dconfig+</literal></entry>
</row>
<row>
<entry><literal>SCHEMA</literal></entry>

View File

@ -1380,6 +1380,23 @@ testdb=&gt;
</varlistentry>
<varlistentry>
<term><literal>\dconfig[+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
<listitem>
<para>
Lists server configuration parameters and their values.
If <replaceable class="parameter">pattern</replaceable>
is specified, only parameters whose names match the pattern are
listed.
If <literal>+</literal> is appended to the command name, each
parameter is listed with its data type, context in which the
parameter can be set, and access privileges (if non-default access
privileges have been granted).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\dC[+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
<listitem>

View File

@ -780,7 +780,14 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
success = describeTablespaces(pattern, show_verbose);
break;
case 'c':
success = listConversions(pattern, show_verbose, show_system);
if (strncmp(cmd, "dconfig", 7) == 0)
success = describeConfigurationParameters(pattern,
show_verbose,
show_system);
else
success = listConversions(pattern,
show_verbose,
show_system);
break;
case 'C':
success = listCasts(pattern, show_verbose);

View File

@ -4364,6 +4364,68 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
return true;
}
/*
* \dconfig
*
* Describes configuration parameters.
*/
bool
describeConfigurationParameters(const char *pattern, bool verbose,
bool showSystem)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT s.name AS \"%s\", "
"pg_catalog.current_setting(s.name) AS \"%s\"",
gettext_noop("Parameter"),
gettext_noop("Value"));
if (verbose)
{
appendPQExpBuffer(&buf,
", s.vartype AS \"%s\", s.context AS \"%s\", ",
gettext_noop("Type"),
gettext_noop("Context"));
if (pset.sversion >= 150000)
printACLColumn(&buf, "p.paracl");
else
appendPQExpBuffer(&buf, "NULL AS \"%s\"",
gettext_noop("Access privileges"));
}
appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
if (verbose && pset.sversion >= 150000)
appendPQExpBufferStr(&buf,
" LEFT JOIN pg_catalog.pg_parameter_acl p\n"
" ON pg_catalog.lower(s.name) = p.parname\n");
processSQLNamePattern(pset.db, &buf, pattern,
false, false,
NULL, "pg_catalog.lower(s.name)", NULL,
NULL);
appendPQExpBufferStr(&buf, "ORDER BY 1;");
res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of configuration parameters");
myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
PQclear(res);
return true;
}
/*
* \dy
*

View File

@ -76,6 +76,10 @@ extern bool listDomains(const char *pattern, bool verbose, bool showSystem);
/* \dc */
extern bool listConversions(const char *pattern, bool verbose, bool showSystem);
/* \dconfig */
extern bool describeConfigurationParameters(const char *pattern, bool verbose,
bool showSystem);
/* \dC */
extern bool listCasts(const char *pattern, bool verbose);

View File

@ -166,7 +166,7 @@ slashUsage(unsigned short int pager)
* Use "psql --help=commands | wc" to count correctly. It's okay to count
* the USE_READLINE line even in builds without that.
*/
output = PageOutput(137, pager ? &(pset.popt.topt) : NULL);
output = PageOutput(138, pager ? &(pset.popt.topt) : NULL);
fprintf(output, _("General\n"));
fprintf(output, _(" \\copyright show PostgreSQL usage and distribution terms\n"));
@ -231,6 +231,7 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n"));
fprintf(output, _(" \\db[+] [PATTERN] list tablespaces\n"));
fprintf(output, _(" \\dc[S+] [PATTERN] list conversions\n"));
fprintf(output, _(" \\dconfig[+] [PATTERN] list configuration parameters\n"));
fprintf(output, _(" \\dC[+] [PATTERN] list casts\n"));
fprintf(output, _(" \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n"));
fprintf(output, _(" \\dD[S+] [PATTERN] list domains\n"));

View File

@ -1004,6 +1004,7 @@ static const SchemaQuery Query_for_trigger_of_table = {
"SELECT nspname FROM pg_catalog.pg_namespace "\
" WHERE nspname LIKE '%s'"
/* Use COMPLETE_WITH_QUERY_VERBATIM with these queries for GUC names: */
#define Query_for_list_of_alter_system_set_vars \
"SELECT name FROM "\
" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
@ -1690,7 +1691,7 @@ psql_completion(const char *text, int start, int end)
"\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
"\\copyright", "\\crosstabview",
"\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
"\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
"\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD",
"\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
"\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
@ -3780,7 +3781,7 @@ psql_completion(const char *text, int start, int end)
TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_alter_system_set_vars);
else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
@ -4532,6 +4533,8 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
else if (TailMatchesCS("\\db*"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
else if (TailMatchesCS("\\dconfig*"))
COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_show_vars);
else if (TailMatchesCS("\\dD*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
else if (TailMatchesCS("\\des*"))

View File

@ -918,8 +918,12 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
* Convert shell-style 'pattern' into the regular expression(s) we want to
* execute. Quoting/escaping into SQL literal format will be done below
* using appendStringLiteralConn().
*
* If the caller provided a schemavar, we want to split the pattern on
* ".", otherwise not.
*/
patternToSQLRegex(PQclientEncoding(conn), NULL, &schemabuf, &namebuf,
patternToSQLRegex(PQclientEncoding(conn), NULL,
(schemavar ? &schemabuf : NULL), &namebuf,
pattern, force_escape);
/*

View File

@ -5090,6 +5090,23 @@ List of access methods
hash | uuid_ops | uuid | uuid | 2 | uuid_hash_extended
(5 rows)
-- check \dconfig
set work_mem = 10240;
\dconfig work_mem
List of configuration parameters
Parameter | Value
-----------+-------
work_mem | 10MB
(1 row)
\dconfig+ work*
List of configuration parameters
Parameter | Value | Type | Context | Access privileges
-----------+-------+---------+---------+-------------------
work_mem | 10MB | integer | user |
(1 row)
reset work_mem;
-- check \df, \do with argument specifications
\df *sqrt
List of functions

View File

@ -1241,6 +1241,12 @@ drop role regress_partitioning_role;
\dAp+ btree float_ops
\dAp * pg_catalog.uuid_ops
-- check \dconfig
set work_mem = 10240;
\dconfig work_mem
\dconfig+ work*
reset work_mem;
-- check \df, \do with argument specifications
\df *sqrt
\df *sqrt num*