psql: Add option for procedures to \df

This commit is contained in:
Peter Eisentraut 2018-07-14 12:17:49 +02:00
parent 9915735ebb
commit 07055a2c8c
6 changed files with 76 additions and 20 deletions

View File

@ -1423,16 +1423,16 @@ testdb=>
<varlistentry> <varlistentry>
<term><literal>\df[antwS+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term> <term><literal>\df[anptwS+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
<listitem> <listitem>
<para> <para>
Lists functions, together with their result data types, argument data Lists functions, together with their result data types, argument data
types, and function types, which are classified as <quote>agg</quote> types, and function types, which are classified as <quote>agg</quote>
(aggregate), <quote>normal</quote>, <quote>trigger</quote>, or <quote>window</quote>. (aggregate), <quote>normal</quote>, <quote>procedure</quote>, <quote>trigger</quote>, or <quote>window</quote>.
To display only functions To display only functions
of specific type(s), add the corresponding letters <literal>a</literal>, of specific type(s), add the corresponding letters <literal>a</literal>,
<literal>n</literal>, <literal>t</literal>, or <literal>w</literal> to the command. <literal>n</literal>, <literal>p</literal>, <literal>t</literal>, or <literal>w</literal> to the command.
If <replaceable If <replaceable
class="parameter">pattern</replaceable> is specified, only class="parameter">pattern</replaceable> is specified, only
functions whose names match the pattern are shown. functions whose names match the pattern are shown.

View File

@ -754,6 +754,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
case 'S': case 'S':
case 'a': case 'a':
case 'n': case 'n':
case 'p':
case 't': case 't':
case 'w': case 'w':
success = describeFunctions(&cmd[2], pattern, show_verbose, show_system); success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);

View File

@ -312,6 +312,7 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
{ {
bool showAggregate = strchr(functypes, 'a') != NULL; bool showAggregate = strchr(functypes, 'a') != NULL;
bool showNormal = strchr(functypes, 'n') != NULL; bool showNormal = strchr(functypes, 'n') != NULL;
bool showProcedure = strchr(functypes, 'p') != NULL;
bool showTrigger = strchr(functypes, 't') != NULL; bool showTrigger = strchr(functypes, 't') != NULL;
bool showWindow = strchr(functypes, 'w') != NULL; bool showWindow = strchr(functypes, 'w') != NULL;
bool have_where; bool have_where;
@ -323,9 +324,20 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
/* No "Parallel" column before 9.6 */ /* 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}; 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, "anptwS+"))
{ {
psql_error("\\df only takes [antwS+] as options\n"); psql_error("\\df only takes [anptwS+] as options\n");
return true;
}
if (showProcedure && pset.sversion < 110000)
{
char sverbuf[32];
psql_error("\\df does not take a \"%c\" option with server version %s\n",
'p',
formatPGVersionNumber(pset.sversion, false,
sverbuf, sizeof(sverbuf)));
return true; return true;
} }
@ -333,15 +345,18 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
{ {
char sverbuf[32]; char sverbuf[32];
psql_error("\\df does not take a \"w\" option with server version %s\n", psql_error("\\df does not take a \"%c\" option with server version %s\n",
'w',
formatPGVersionNumber(pset.sversion, false, formatPGVersionNumber(pset.sversion, false,
sverbuf, sizeof(sverbuf))); sverbuf, sizeof(sverbuf)));
return true; return true;
} }
if (!showAggregate && !showNormal && !showTrigger && !showWindow) if (!showAggregate && !showNormal && !showProcedure && !showTrigger && !showWindow)
{ {
showAggregate = showNormal = showTrigger = true; showAggregate = showNormal = showTrigger = true;
if (pset.sversion >= 110000)
showProcedure = true;
if (pset.sversion >= 80400) if (pset.sversion >= 80400)
showWindow = true; showWindow = true;
} }
@ -505,7 +520,7 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
have_where = false; have_where = false;
/* filter by function type, if requested */ /* filter by function type, if requested */
if (showNormal && showAggregate && showTrigger && showWindow) if (showNormal && showAggregate && showProcedure && showTrigger && showWindow)
/* Do nothing */ ; /* Do nothing */ ;
else if (showNormal) else if (showNormal)
{ {
@ -523,6 +538,17 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
else else
appendPQExpBufferStr(&buf, "NOT p.proisagg\n"); appendPQExpBufferStr(&buf, "NOT p.proisagg\n");
} }
if (!showProcedure && pset.sversion >= 110000)
{
if (have_where)
appendPQExpBufferStr(&buf, " AND ");
else
{
appendPQExpBufferStr(&buf, "WHERE ");
have_where = true;
}
appendPQExpBufferStr(&buf, "p.prokind <> 'p'\n");
}
if (!showTrigger) if (!showTrigger)
{ {
if (have_where) if (have_where)
@ -572,6 +598,13 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool
"p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n"); "p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n");
needs_or = true; needs_or = true;
} }
if (showProcedure)
{
if (needs_or)
appendPQExpBufferStr(&buf, " OR ");
appendPQExpBufferStr(&buf, "p.prokind = 'p'\n");
needs_or = true;
}
if (showWindow) if (showWindow)
{ {
if (needs_or) if (needs_or)

View File

@ -235,7 +235,7 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\des[+] [PATTERN] list foreign servers\n")); fprintf(output, _(" \\des[+] [PATTERN] list foreign servers\n"));
fprintf(output, _(" \\deu[+] [PATTERN] list user mappings\n")); fprintf(output, _(" \\deu[+] [PATTERN] list user mappings\n"));
fprintf(output, _(" \\dew[+] [PATTERN] list foreign-data wrappers\n")); fprintf(output, _(" \\dew[+] [PATTERN] list foreign-data wrappers\n"));
fprintf(output, _(" \\df[antw][S+] [PATRN] list [only agg/normal/trigger/window] functions\n")); fprintf(output, _(" \\df[anptw][S+] [PATRN] list [only agg/normal/procedures/trigger/window] functions\n"));
fprintf(output, _(" \\dF[+] [PATTERN] list text search configurations\n")); fprintf(output, _(" \\dF[+] [PATTERN] list text search configurations\n"));
fprintf(output, _(" \\dFd[+] [PATTERN] list text search dictionaries\n")); fprintf(output, _(" \\dFd[+] [PATTERN] list text search dictionaries\n"));
fprintf(output, _(" \\dFp[+] [PATTERN] list text search parsers\n")); fprintf(output, _(" \\dFp[+] [PATTERN] list text search parsers\n"));

View File

@ -15,14 +15,6 @@ LANGUAGE SQL
AS $$ AS $$
INSERT INTO cp_test VALUES (1, x); INSERT INTO cp_test VALUES (1, x);
$$; $$;
SELECT ptest1('x'); -- error
ERROR: ptest1(unknown) is a procedure
LINE 1: SELECT ptest1('x');
^
HINT: To call a procedure, use CALL.
CALL ptest1('a'); -- ok
CALL ptest1('xy' || 'zzy'); -- ok, constant-folded arg
CALL ptest1(substring(random()::numeric(20,15)::text, 1, 1)); -- ok, volatile arg
\df ptest1 \df ptest1
List of functions List of functions
Schema | Name | Result data type | Argument data types | Type Schema | Name | Result data type | Argument data types | Type
@ -41,6 +33,30 @@ SELECT pg_get_functiondef('ptest1'::regproc);
(1 row) (1 row)
-- show only normal functions
\dfn public.*test*1
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+--------------+------------------+---------------------+------
public | cp_testfunc1 | integer | a integer | func
(1 row)
-- show only procedures
\dfp public.*test*1
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+--------+------------------+---------------------+------
public | ptest1 | | x text | proc
(1 row)
SELECT ptest1('x'); -- error
ERROR: ptest1(unknown) is a procedure
LINE 1: SELECT ptest1('x');
^
HINT: To call a procedure, use CALL.
CALL ptest1('a'); -- ok
CALL ptest1('xy' || 'zzy'); -- ok, constant-folded arg
CALL ptest1(substring(random()::numeric(20,15)::text, 1, 1)); -- ok, volatile arg
SELECT * FROM cp_test ORDER BY b COLLATE "C"; SELECT * FROM cp_test ORDER BY b COLLATE "C";
a | b a | b
---+------- ---+-------

View File

@ -11,14 +11,20 @@ AS $$
INSERT INTO cp_test VALUES (1, x); INSERT INTO cp_test VALUES (1, x);
$$; $$;
\df ptest1
SELECT pg_get_functiondef('ptest1'::regproc);
-- show only normal functions
\dfn public.*test*1
-- show only procedures
\dfp public.*test*1
SELECT ptest1('x'); -- error SELECT ptest1('x'); -- error
CALL ptest1('a'); -- ok CALL ptest1('a'); -- ok
CALL ptest1('xy' || 'zzy'); -- ok, constant-folded arg CALL ptest1('xy' || 'zzy'); -- ok, constant-folded arg
CALL ptest1(substring(random()::numeric(20,15)::text, 1, 1)); -- ok, volatile arg CALL ptest1(substring(random()::numeric(20,15)::text, 1, 1)); -- ok, volatile arg
\df ptest1
SELECT pg_get_functiondef('ptest1'::regproc);
SELECT * FROM cp_test ORDER BY b COLLATE "C"; SELECT * FROM cp_test ORDER BY b COLLATE "C";