Add a \sf (show function) command to psql, for those times when you need to
look at a function but don't wish to fire up an editor. Pavel Stehule, reviewed by Jan Urbanski
This commit is contained in:
parent
946b078044
commit
b6e06942c6
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.248 2010/08/12 00:40:59 tgl Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.249 2010/08/14 13:59:49 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -2136,6 +2136,33 @@ lo_import 152801
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>\sf[+] <replaceable class="parameter">function_description</> </literal></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This command fetches and shows the definition of the named function,
|
||||||
|
in the form of a <command>CREATE OR REPLACE FUNCTION</> command.
|
||||||
|
The definition is printed to the current query output channel,
|
||||||
|
as set by <command>\o</command>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The target function can be specified by name alone, or by name
|
||||||
|
and arguments, for example <literal>foo(integer, text)</>.
|
||||||
|
The argument types must be given if there is more
|
||||||
|
than one function of the same name.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If <literal>+</literal> is appended to the command name, then the
|
||||||
|
output lines are numbered, with the first line of the function body
|
||||||
|
being line 1.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>\t</literal></term>
|
<term><literal>\t</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.226 2010/08/12 00:40:59 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.227 2010/08/14 13:59:49 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -1083,6 +1083,121 @@ exec_command(const char *cmd,
|
|||||||
free(opt0);
|
free(opt0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* \sf -- show a function's source code */
|
||||||
|
else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
|
||||||
|
{
|
||||||
|
bool show_linenumbers = (strcmp(cmd, "sf+") == 0);
|
||||||
|
PQExpBuffer func_buf;
|
||||||
|
char *func;
|
||||||
|
Oid foid = InvalidOid;
|
||||||
|
|
||||||
|
func_buf = createPQExpBuffer();
|
||||||
|
func = psql_scan_slash_option(scan_state,
|
||||||
|
OT_WHOLE_LINE, NULL, true);
|
||||||
|
if (!func)
|
||||||
|
{
|
||||||
|
psql_error("function name is required\n");
|
||||||
|
status = PSQL_CMD_ERROR;
|
||||||
|
}
|
||||||
|
else if (!lookup_function_oid(pset.db, func, &foid))
|
||||||
|
{
|
||||||
|
/* error already reported */
|
||||||
|
status = PSQL_CMD_ERROR;
|
||||||
|
}
|
||||||
|
else if (!get_create_function_cmd(pset.db, foid, func_buf))
|
||||||
|
{
|
||||||
|
/* error already reported */
|
||||||
|
status = PSQL_CMD_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FILE *output;
|
||||||
|
bool is_pager;
|
||||||
|
|
||||||
|
/* Select output stream: stdout, pager, or file */
|
||||||
|
if (pset.queryFout == stdout)
|
||||||
|
{
|
||||||
|
/* count lines in function to see if pager is needed */
|
||||||
|
int lineno = 0;
|
||||||
|
const char *lines = func_buf->data;
|
||||||
|
|
||||||
|
while (*lines != '\0')
|
||||||
|
{
|
||||||
|
lineno++;
|
||||||
|
/* find start of next line */
|
||||||
|
lines = strchr(lines, '\n');
|
||||||
|
if (!lines)
|
||||||
|
break;
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = PageOutput(lineno, pset.popt.topt.pager);
|
||||||
|
is_pager = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* use previously set output file, without pager */
|
||||||
|
output = pset.queryFout;
|
||||||
|
is_pager = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_linenumbers)
|
||||||
|
{
|
||||||
|
bool in_header = true;
|
||||||
|
int lineno = 0;
|
||||||
|
char *lines = func_buf->data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lineno "1" should correspond to the first line of the
|
||||||
|
* function body. We expect that pg_get_functiondef() will
|
||||||
|
* emit that on a line beginning with "AS $function", and that
|
||||||
|
* there can be no such line before the real start of the
|
||||||
|
* function body.
|
||||||
|
*
|
||||||
|
* Note that this loop scribbles on func_buf.
|
||||||
|
*/
|
||||||
|
while (*lines != '\0')
|
||||||
|
{
|
||||||
|
char *eol;
|
||||||
|
|
||||||
|
if (in_header && strncmp(lines, "AS $function", 12) == 0)
|
||||||
|
in_header = false;
|
||||||
|
/* increment lineno only for body's lines */
|
||||||
|
if (!in_header)
|
||||||
|
lineno++;
|
||||||
|
|
||||||
|
/* find and mark end of current line */
|
||||||
|
eol = strchr(lines, '\n');
|
||||||
|
if (eol != NULL)
|
||||||
|
*eol = '\0';
|
||||||
|
|
||||||
|
/* show current line as appropriate */
|
||||||
|
if (in_header)
|
||||||
|
fprintf(output, " %s\n", lines);
|
||||||
|
else
|
||||||
|
fprintf(output, "%-7d %s\n", lineno, lines);
|
||||||
|
|
||||||
|
/* advance to next line, if any */
|
||||||
|
if (eol == NULL)
|
||||||
|
break;
|
||||||
|
lines = ++eol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* just send the function definition to output */
|
||||||
|
fputs(func_buf->data, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_pager)
|
||||||
|
ClosePager(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func)
|
||||||
|
free(func);
|
||||||
|
destroyPQExpBuffer(func_buf);
|
||||||
|
}
|
||||||
|
|
||||||
/* \t -- turn off headers and row count */
|
/* \t -- turn off headers and row count */
|
||||||
else if (strcmp(cmd, "t") == 0)
|
else if (strcmp(cmd, "t") == 0)
|
||||||
{
|
{
|
||||||
@ -1093,7 +1208,6 @@ exec_command(const char *cmd,
|
|||||||
free(opt);
|
free(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* \T -- define html <table ...> attributes */
|
/* \T -- define html <table ...> attributes */
|
||||||
else if (strcmp(cmd, "T") == 0)
|
else if (strcmp(cmd, "T") == 0)
|
||||||
{
|
{
|
||||||
@ -1667,7 +1781,7 @@ editFile(const char *fname, int lineno)
|
|||||||
editorName, fname);
|
editorName, fname);
|
||||||
#else
|
#else
|
||||||
if (lineno > 0)
|
if (lineno > 0)
|
||||||
sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
|
sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
|
||||||
editorName, editor_lineno_switch, lineno, fname);
|
editorName, editor_lineno_switch, lineno, fname);
|
||||||
else
|
else
|
||||||
sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
|
sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.162 2010/08/13 20:56:18 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.163 2010/08/14 13:59:49 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ slashUsage(unsigned short int pager)
|
|||||||
{
|
{
|
||||||
FILE *output;
|
FILE *output;
|
||||||
|
|
||||||
output = PageOutput(89, pager);
|
output = PageOutput(90, pager);
|
||||||
|
|
||||||
/* if you add/remove a line here, change the row count above */
|
/* if you add/remove a line here, change the row count above */
|
||||||
|
|
||||||
@ -220,6 +220,7 @@ slashUsage(unsigned short int pager)
|
|||||||
fprintf(output, _(" \\du[+] [PATTERN] list roles (users)\n"));
|
fprintf(output, _(" \\du[+] [PATTERN] list roles (users)\n"));
|
||||||
fprintf(output, _(" \\dv[S+] [PATTERN] list views\n"));
|
fprintf(output, _(" \\dv[S+] [PATTERN] list views\n"));
|
||||||
fprintf(output, _(" \\l[+] list all databases\n"));
|
fprintf(output, _(" \\l[+] list all databases\n"));
|
||||||
|
fprintf(output, _(" \\sf[+] FUNCNAME show a function's definition\n"));
|
||||||
fprintf(output, _(" \\z [PATTERN] same as \\dp\n"));
|
fprintf(output, _(" \\z [PATTERN] same as \\dp\n"));
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.201 2010/07/20 03:54:19 rhaas Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.202 2010/08/14 13:59:49 tgl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
@ -644,7 +644,7 @@ psql_completion(char *text, int start, int end)
|
|||||||
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
|
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
|
||||||
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
|
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
|
||||||
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
|
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
|
||||||
"\\set", "\\t", "\\T",
|
"\\set", "\\sf", "\\t", "\\T",
|
||||||
"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
|
"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2517,6 +2517,8 @@ psql_completion(char *text, int start, int end)
|
|||||||
|
|
||||||
COMPLETE_WITH_LIST(my_list);
|
COMPLETE_WITH_LIST(my_list);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(prev_wd, "\\sf") == 0 || strcmp(prev_wd, "\\sf+") == 0)
|
||||||
|
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
|
||||||
else if (strcmp(prev_wd, "\\cd") == 0 ||
|
else if (strcmp(prev_wd, "\\cd") == 0 ||
|
||||||
strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
|
strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
|
||||||
strcmp(prev_wd, "\\g") == 0 ||
|
strcmp(prev_wd, "\\g") == 0 ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user