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*