Improve output of psql's \df+ command.

Add display of proparallel (parallel-safety) when the server is >= 9.6,
and display of proacl (access privileges) for all server versions.
Minor tweak of column ordering to keep related columns together.

Michael Paquier

Discussion: <CAB7nPqTR3Vu3xKOZOYqSm-+bSZV0kqgeGAXD6w5GLbkbfd5Q6w@mail.gmail.com>
This commit is contained in:
Tom Lane 2016-07-11 12:35:03 -04:00
parent 740bf396a1
commit a670c24c38
2 changed files with 48 additions and 19 deletions

View File

@ -1367,9 +1367,9 @@ testdb=&gt;
<listitem> <listitem>
<para> <para>
Lists functions, together with their arguments, return types, and Lists functions, together with their result data types, argument data
function types, which are classified as <quote>agg</> (aggregate), types, and function types, which are classified as <quote>agg</>
<quote>normal</>, <quote>trigger</>, or <quote>window</>. (aggregate), <quote>normal</>, <quote>trigger</>, or <quote>window</>.
To display only functions To display only functions
of specific type(s), add the corresponding letters <literal>a</>, of specific type(s), add the corresponding letters <literal>a</>,
<literal>n</>, <literal>t</>, or <literal>w</> to the command. <literal>n</>, <literal>t</>, or <literal>w</> to the command.
@ -1380,14 +1380,15 @@ testdb=&gt;
objects are shown; supply a pattern or the <literal>S</literal> objects are shown; supply a pattern or the <literal>S</literal>
modifier to include system objects. modifier to include system objects.
If the form <literal>\df+</literal> is used, additional information If the form <literal>\df+</literal> is used, additional information
about each function is shown, including security classification, about each function is shown, including volatility,
volatility, owner, language, source code and description. parallel safety, owner, security classification, access privileges,
language, source code and description.
</para> </para>
<tip> <tip>
<para> <para>
To look up functions taking arguments or returning values of a specific To look up functions taking arguments or returning values of a specific
type, use your pager's search capability to scroll through the data type, use your pager's search capability to scroll through the
<literal>\df</> output. <literal>\df</> output.
</para> </para>
</tip> </tip>

View File

@ -298,7 +298,10 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool translate_columns[] = {false, false, false, false, true, true, true, false, false, false, false}; static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false};
/* No "Parallel" column before 9.6 */
static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false};
if (strlen(functypes) != strspn(functypes, "antwS+")) if (strlen(functypes) != strspn(functypes, "antwS+"))
{ {
@ -410,28 +413,45 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
gettext_noop("Type")); gettext_noop("Type"));
if (verbose) if (verbose)
{
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\""
",\n CASE\n" ",\n CASE\n"
" WHEN p.provolatile = 'i' THEN '%s'\n" " WHEN p.provolatile = 'i' THEN '%s'\n"
" WHEN p.provolatile = 's' THEN '%s'\n" " WHEN p.provolatile = 's' THEN '%s'\n"
" WHEN p.provolatile = 'v' THEN '%s'\n" " WHEN p.provolatile = 'v' THEN '%s'\n"
" END as \"%s\"" " END as \"%s\"",
",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\",\n"
" l.lanname as \"%s\",\n"
" p.prosrc as \"%s\",\n"
" pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
gettext_noop("definer"),
gettext_noop("invoker"),
gettext_noop("Security"),
gettext_noop("immutable"), gettext_noop("immutable"),
gettext_noop("stable"), gettext_noop("stable"),
gettext_noop("volatile"), gettext_noop("volatile"),
gettext_noop("Volatility"), gettext_noop("Volatility"));
if (pset.sversion >= 90600)
appendPQExpBuffer(&buf,
",\n CASE\n"
" WHEN p.proparallel = 'r' THEN '%s'\n"
" WHEN p.proparallel = 's' THEN '%s'\n"
" WHEN p.proparallel = 'u' THEN '%s'\n"
" END as \"%s\"",
gettext_noop("restricted"),
gettext_noop("safe"),
gettext_noop("unsafe"),
gettext_noop("Parallel"));
appendPQExpBuffer(&buf,
",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\""
",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"",
gettext_noop("Owner"), gettext_noop("Owner"),
gettext_noop("definer"),
gettext_noop("invoker"),
gettext_noop("Security"));
appendPQExpBufferStr(&buf, ",\n ");
printACLColumn(&buf, "p.proacl");
appendPQExpBuffer(&buf,
",\n l.lanname as \"%s\""
",\n p.prosrc as \"%s\""
",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
gettext_noop("Language"), gettext_noop("Language"),
gettext_noop("Source code"), gettext_noop("Source code"),
gettext_noop("Description")); gettext_noop("Description"));
}
appendPQExpBufferStr(&buf, appendPQExpBufferStr(&buf,
"\nFROM pg_catalog.pg_proc p" "\nFROM pg_catalog.pg_proc p"
@ -530,8 +550,16 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of functions"); myopt.title = _("List of functions");
myopt.translate_header = true; myopt.translate_header = true;
myopt.translate_columns = translate_columns; if (pset.sversion >= 90600)
myopt.n_translate_columns = lengthof(translate_columns); {
myopt.translate_columns = translate_columns;
myopt.n_translate_columns = lengthof(translate_columns);
}
else
{
myopt.translate_columns = translate_columns_pre_96;
myopt.n_translate_columns = lengthof(translate_columns_pre_96);
}
printQuery(res, &myopt, pset.queryFout, false, pset.logfile); printQuery(res, &myopt, pset.queryFout, false, pset.logfile);