diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml
index 492a960247..77ce39766c 100644
--- a/doc/src/sgml/ddl.sgml
+++ b/doc/src/sgml/ddl.sgml
@@ -2205,7 +2205,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
PARAMETER
sA
none
- none
+ \dconfig+
SCHEMA
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index f01adb1fd2..92e5c50300 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1380,6 +1380,23 @@ testdb=>
+
+ \dconfig[+] [ pattern ]
+
+
+ Lists server configuration parameters and their values.
+ If pattern
+ is specified, only parameters whose names match the pattern are
+ listed.
+ If + 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).
+
+
+
+
+
\dC[+] [ pattern ]
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 079f4a1a76..db071d561f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -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);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 3f1b3802c2..797ef233c9 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -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
*
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index fd6079679c..7872c71f58 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -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);
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index b3971bce64..1d3601e594 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -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"));
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index a2df39d0c1..8f163fb7ba 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -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*"))
diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index bca50ec6de..1c61840462 100644
--- a/src/fe_utils/string_utils.c
+++ b/src/fe_utils/string_utils.c
@@ -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);
/*
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 185c505312..8e11ebbcaa 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -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
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index 8f49a5f347..bf372c37a5 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -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*