Hello
updated patch attached
2010/8/4 Robert Haas <[email protected]>:
> On Tue, Aug 3, 2010 at 7:20 AM, Pavel Stehule <[email protected]> wrote:
>> I hope so I found and fixed last issue - the longer functions was
>> showed directly - without a pager.
>
> As a matter of style, I suggest leaving bool *edited as the last
> argument to do_edit() and inserting int lineno as the second-to-last
> argument.
>
> ! int lineno = -1;
> [...]
> ! if (atoi(ln) < 1)
> ! {
> ! psql_error("invalid line
> number\n");
> ! status = PSQL_CMD_ERROR;
> ! }
> ! else
> ! lineno = atoi(ln);
>
> Why call atoi(n) twice? Can't you just write:
>
> lineno = atoi(n);
> if (lineno < 1) {
> ...error stuff...
> }
fixed
>
> I suggested writing psql_assert(datag != NULL) rather than just
> psql_assert(datag).
>
> Instead of: cannot use a editor navigation without setting
> EDITOR_LINENUMBER_SWITCH variable
> I suggest: cannot edit a specific line because the
> EDITOR_LINENUMBER_SWITCH variable is not set
fixed
>
> I don't find the name get_dg_tag() to be very mnemonic. How about
> get_function_dollarquote_tag()?
>
I used get_functiondef_dollarquote_tag
> In help.c, it looks like you've only added one line but incremented
> the pager count by three.
>
The original value for pager is probably wrong (not actual). I
rechecked real row numbers in external editor.
> In this bit:
>
> ! dqtag = get_dq_tag(lines);
> ! if (dqtag)
> ! {
> ! free(dqtag);
> ! break;
> ! }
> ! else
> ! lineno++;
>
> The "else" is unnecessary. And just after that:
>
> ! if (end_of_line)
> ! lines = end_of_line + 1;
> ! else
> ! break;
>
> You can write this more cleanly by saying if (!end_of_line) break;
> lines = end_of_line + 1.
>
fixed
> The following diff hunk (2213,2218) just adds a blank line and is
> therefore unnecessary. There's a similar hunk in the docs portion of
> the patch.
fixed
>
> In this part:
>
> func = psql_scan_slash_option(scan_state,
>
> OT_WHOLE_LINE, NULL, true);
> ! lineno = extract_lineno_from_funcdesc(func, &status);
> !
> ! if (status != PSQL_CMD_ERROR)
> {
> ! if (!func)
> ! {
> ! /* set up an empty command to fill in
> */
> ! printfPQExpBuffer(query_buf,
> !
> "CREATE FUNCTION ( )\n"
> ! "
> RETURNS \n"
> ! "
> LANGUAGE \n"
> ! "
> -- common options: IMMUTABLE STABLE STRICT SECURITY
> DEFINER\n"
> ! "AS
> $function$\n"
> !
> "\n$function$\n");
> ! }
> ! 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, query_buf))
> ! {
> ! /* error already reported */
> ! status = PSQL_CMD_ERROR;
> ! }
> ! if (func)
> ! free(func);
> }
>
> Why is it correct for if (func) free(func) to be inside the if (status
> != PSQL_CMD_ERROR) block? It looks to me like func gets initialized
> first, before status is set.
fixed
>
> It seems unnecessary for extract_lineno_from_funcdesc() to return the
> line number and have a separate out parameter to return a
> backslashResult. Can't you just return -1 to indicate an error? (You
> might need to move the if (!func) test at the top to the caller, but
> that seems OK.)
I can't to do it. There are three states
1) lineno is wrong
2) lineno is undefined
3) lineno is defined
@1 is solved via backslashResult, @2 lineno is negative, @3 lineno is positive
Regards
Pavel
>
> --
> Robert Haas
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise Postgres Company
>
*** ./doc/src/sgml/ref/psql-ref.sgml.orig 2010-08-03 09:00:48.384710383 +0200
--- ./doc/src/sgml/ref/psql-ref.sgml 2010-08-03 10:44:57.312835131 +0200
***************
*** 1339,1345 ****
<varlistentry>
! <term><literal>\edit</literal> (or <literal>\e</literal>) <literal><optional> <replaceable class="parameter">filename</replaceable> </optional></literal></term>
<listitem>
<para>
--- 1339,1345 ----
<varlistentry>
! <term><literal>\edit</literal> (or <literal>\e</literal>) <literal><optional> <replaceable class="parameter">filename</replaceable> </optional> <optional> linenumber </optional></literal></term>
<listitem>
<para>
***************
*** 1369,1380 ****
systems, <filename>notepad.exe</filename> on Windows systems.
</para>
</tip>
</listitem>
</varlistentry>
<varlistentry>
! <term><literal>\ef <optional> <replaceable class="parameter">function_description</replaceable> </optional></literal></term>
<listitem>
<para>
--- 1369,1387 ----
systems, <filename>notepad.exe</filename> on Windows systems.
</para>
</tip>
+
+ <para>
+ If <replaceable class="parameter">linenumber</replaceable> is
+ specified, then cursor is moved on this line after start of
+ editor (The psql's variable <varname>EDITOR_LINENUMBER_SWITCH</varname>
+ have to be filled).
+ </para>
</listitem>
</varlistentry>
<varlistentry>
! <term><literal>\ef <optional> <replaceable class="parameter">function_description</replaceable> </optional> <optional> linenumber </optional> </literal></term>
<listitem>
<para>
***************
*** 1397,1402 ****
--- 1404,1417 ----
If no function is specified, a blank <command>CREATE FUNCTION</>
template is presented for editing.
</para>
+
+ <para>
+ If <replaceable class="parameter">linenumber</replaceable> is
+ specified, then cursor is moved on this line after start of
+ editor. It count lines from start of function body, not from
+ start of text (The psql's variable <varname>EDITOR_LINENUMBER_SWITCH</varname>
+ have to be filled).
+ </para>
</listitem>
</varlistentry>
***************
*** 2116,2121 ****
--- 2131,2148 ----
<varlistentry>
+ <term><literal>\sf[+] <replaceable class="parameter">function_description</replaceable> <optional> linenumber </optional> </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.
+ If the form <literal>\sf+</literal> is used, then lines are numbered.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>\t</literal></term>
<listitem>
<para>
***************
*** 2123,2128 ****
--- 2150,2161 ----
footer. This command is equivalent to <literal>\pset
tuples_only</literal> and is provided for convenience.
</para>
+
+ <para>
+ If <replaceable class="parameter">linenumber</replaceable> is
+ specified, then cursor is moved on this line after start of
+ editor.
+ </para>
</listitem>
</varlistentry>
***************
*** 2459,2464 ****
--- 2492,2511 ----
</varlistentry>
<varlistentry>
+ <term><varname>EDITOR_LINENUMBER_SWITCH</varname></term>
+ <listitem>
+ <para>
+ Option used for navigation (go to line command) in external
+ editor. When it isn't defined, then you cannot to specify
+ line numbers for <command>\edit</command> and <command>\ef</command>
+ commands. On unix platforms are possible to use a '<option>+</option>'
+ or '<option>--line </option>'. The space after <literal>line</literal>
+ is required.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>ENCODING</varname></term>
<listitem>
<para>
***************
*** 3065,3070 ****
--- 3112,3118 ----
</listitem>
</varlistentry>
+
<varlistentry>
<term><envar>SHELL</envar></term>
*** ./src/bin/psql/command.c.orig 2010-08-03 09:00:48.386710435 +0200
--- ./src/bin/psql/command.c 2010-08-04 16:32:38.388093597 +0200
***************
*** 46,54 ****
--- 46,56 ----
#include "input.h"
#include "large_obj.h"
#include "mainloop.h"
+ #include "pqsignal.h"
#include "print.h"
#include "psqlscan.h"
#include "settings.h"
+ #include <signal.h>
#include "variables.h"
***************
*** 57,63 ****
PsqlScanState scan_state,
PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
! bool *edited);
static bool do_connect(char *dbname, char *user, char *host, char *port);
static bool do_shell(const char *command);
static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
--- 59,65 ----
PsqlScanState scan_state,
PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
! int lineno, bool *edited);
static bool do_connect(char *dbname, char *user, char *host, char *port);
static bool do_shell(const char *command);
static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
***************
*** 66,71 ****
--- 68,76 ----
static void printSSLInfo(void);
+ static int extract_lineno_from_funcdesc(char *func, backslashResult *status);
+ static char *get_functiondef_dollarquote_tag(char *row);
+
#ifdef WIN32
static void checkWin32Codepage(void);
#endif
***************
*** 513,528 ****
else
{
char *fname;
!
fname = psql_scan_slash_option(scan_state,
! OT_NORMAL, NULL, true);
! expand_tilde(&fname);
if (fname)
! canonicalize_path(fname);
! if (do_edit(fname, query_buf, NULL))
! status = PSQL_CMD_NEWEDIT;
! else
! status = PSQL_CMD_ERROR;
free(fname);
}
}
--- 518,554 ----
else
{
char *fname;
! char *ln;
! int lineno = -1;
!
fname = psql_scan_slash_option(scan_state,
! OT_NORMAL, NULL, true);
!
! /* try to get lineno */
if (fname)
! {
! ln = psql_scan_slash_option(scan_state,
! OT_NORMAL, NULL, true);
! if (ln)
! {
! lineno = atoi(ln);
! if (lineno < 1)
! {
! psql_error("invalid line number\n");
! status = PSQL_CMD_ERROR;
! }
! }
! }
! if (status != PSQL_CMD_ERROR)
! {
! expand_tilde(&fname);
! if (fname)
! canonicalize_path(fname);
! if (do_edit(fname, query_buf, lineno, NULL))
! status = PSQL_CMD_NEWEDIT;
! else
! status = PSQL_CMD_ERROR;
! }
free(fname);
}
}
***************
*** 533,538 ****
--- 559,566 ----
*/
else if (strcmp(cmd, "ef") == 0)
{
+ int lineno;
+
if (!query_buf)
{
psql_error("no query buffer\n");
***************
*** 545,580 ****
func = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, true);
! if (!func)
! {
! /* set up an empty command to fill in */
! printfPQExpBuffer(query_buf,
! "CREATE FUNCTION ( )\n"
! " RETURNS \n"
! " LANGUAGE \n"
! " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
! "AS $function$\n"
! "\n$function$\n");
! }
! 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, query_buf))
{
! /* error already reported */
! status = PSQL_CMD_ERROR;
}
if (func)
free(func);
}
if (status != PSQL_CMD_ERROR)
{
bool edited = false;
! if (!do_edit(0, query_buf, &edited))
status = PSQL_CMD_ERROR;
else if (!edited)
puts(_("No changes"));
--- 573,615 ----
func = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, true);
! lineno = extract_lineno_from_funcdesc(func, &status);
!
! if (status != PSQL_CMD_ERROR)
{
! if (!func)
! {
! /* set up an empty command to fill in */
! printfPQExpBuffer(query_buf,
! "CREATE FUNCTION ( )\n"
! " RETURNS \n"
! " LANGUAGE \n"
! " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
! "AS $function$\n"
! "\n$function$\n");
! }
! 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, query_buf))
! {
! /* error already reported */
! status = PSQL_CMD_ERROR;
! }
}
+
if (func)
free(func);
+
}
if (status != PSQL_CMD_ERROR)
{
bool edited = false;
! if (!do_edit(0, query_buf, lineno, &edited))
status = PSQL_CMD_ERROR;
else if (!edited)
puts(_("No changes"));
***************
*** 969,974 ****
--- 1004,1152 ----
free(fname);
}
+ /*
+ * \sf -- show the named function
+ */
+ else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
+ {
+ int first_visible_row = -1;
+ bool with_lno;
+
+ with_lno = (strcmp(cmd, "sf+") == 0);
+
+ if (!query_buf)
+ {
+ psql_error("no query buffer\n");
+ status = PSQL_CMD_ERROR;
+ }
+ else
+ {
+ char *func;
+ Oid foid = InvalidOid;
+
+ func = psql_scan_slash_option(scan_state,
+ OT_WHOLE_LINE, NULL, true);
+
+ first_visible_row = extract_lineno_from_funcdesc(func, &status);
+
+ if (status != PSQL_CMD_ERROR)
+ {
+ if (!func)
+ {
+ /* show error for empty command */
+ psql_error("missing a function name\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, query_buf))
+ {
+ /* error already reported */
+ status = PSQL_CMD_ERROR;
+ }
+ }
+ if (func)
+ free(func);
+ }
+
+ if (status != PSQL_CMD_ERROR)
+ {
+ int lineno = 0;
+ char *row;
+ char *dqtag = NULL;
+ bool is_header = true;
+ bool is_body = false;
+ bool is_footer = false;
+ char *end_of_line;
+ int lines;
+ FILE *output;
+
+
+ /* get number of lines of functiondef - used for possible using a pager */
+ row = query_buf->data;
+ lines = 0;
+ while (*row)
+ {
+ lines++;
+ end_of_line = strchr(row, '\n');
+ if (end_of_line)
+ row = end_of_line + 1;
+ else
+ break;
+ }
+
+ output = PageOutput(lines, pset.popt.topt.pager);
+
+ row = query_buf->data;
+ while (*row)
+ {
+ /* find next end of line */
+ end_of_line = strchr(row, '\n');
+ if (end_of_line)
+ *end_of_line = '\0';
+
+ if (is_header)
+ {
+ /* detect end of header */
+ dqtag = get_functiondef_dollarquote_tag(row);
+ if (dqtag)
+ {
+ is_header = false;
+ is_body = true;
+ lineno = 1;
+ }
+ }
+ else if (is_body)
+ {
+ lineno++;
+ if (strcmp(row, dqtag) == 0)
+ {
+ is_body = false;
+ is_footer = true;
+ }
+ }
+
+ /* can we show rows? */
+ if (first_visible_row < 0 || (first_visible_row <= lineno))
+ {
+ if (with_lno)
+ {
+ if (is_header || is_footer)
+ fprintf(output, "**** %s", row);
+ else
+ fprintf(output, "%4d %s", lineno, row);
+ }
+ else
+ fprintf(output, "%s", row);
+
+ /* return back replaced "\n" */
+ if (end_of_line)
+ fprintf(output, "\n");
+ }
+
+ if (end_of_line)
+ row = end_of_line + 1;
+ else
+ break;
+ }
+
+ /* function pg_get_functiondef uses dollar quoted strings always */
+ psql_assert(dqtag != NULL);
+ free(dqtag);
+
+ if (output != stdout)
+ {
+ pclose(output);
+ #ifndef WIN32
+ pqsignal(SIGPIPE, SIG_DFL);
+ #endif
+ }
+ }
+ }
+
/* \set -- generalized set variable/option command */
else if (strcmp(cmd, "set") == 0)
{
***************
*** 1550,1558 ****
*/
static bool
! editFile(const char *fname)
{
const char *editorName;
char *sys;
int result;
--- 1728,1737 ----
*/
static bool
! editFile(const char *fname, int lineno)
{
const char *editorName;
+ const char *editor_lineno_switch;
char *sys;
int result;
***************
*** 1566,1572 ****
editorName = getenv("VISUAL");
if (!editorName)
editorName = DEFAULT_EDITOR;
!
/*
* On Unix the EDITOR value should *not* be quoted, since it might include
* switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
--- 1745,1762 ----
editorName = getenv("VISUAL");
if (!editorName)
editorName = DEFAULT_EDITOR;
!
! /* Find a EDITOR_LINENUMBER_SWITCH when lineno is used */
! if (lineno >= 1)
! {
! editor_lineno_switch = GetVariable(pset.vars, "EDITOR_LINENUMBER_SWITCH");
! if (!editor_lineno_switch)
! {
! psql_error("EDITOR_LINENUMBER_SWITCH variable is not set\n");
! return false;
! }
! }
!
/*
* On Unix the EDITOR value should *not* be quoted, since it might include
* switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
***************
*** 1574,1584 ****
* severe brain damage in their command shell plus the fact that standard
* program paths include spaces.
*/
! sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
#ifndef WIN32
! sprintf(sys, "exec %s '%s'", editorName, fname);
#else
! sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE, editorName, fname);
#endif
result = system(sys);
if (result == -1)
--- 1764,1796 ----
* severe brain damage in their command shell plus the fact that standard
* program paths include spaces.
*/
! if (lineno >= 1)
! /*
! * allocate sufficient memory for command line content and
! * increase it about space for editor_lineno_switch and lineno
! * (signed int ~ 10 digits) and one space more.
! */
! sys = pg_malloc(strlen(editorName) + strlen(fname) + 10
! + strlen(editor_lineno_switch) + 10 + 1 + 1);
!
! else
! /* allocate sufficient memory for command line content */
! sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
!
#ifndef WIN32
! if (lineno > 0)
! sprintf(sys, "exec %s %s%d '%s'", editorName, editor_lineno_switch, lineno, fname);
! else
! sprintf(sys, "exec %s '%s'", editorName, fname);
#else
! if (lineno > 0)
! sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
! editorName,
! editor_lineno_switch,
! lineno,
! fname);
! else
! sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE, editorName, fname);
#endif
result = system(sys);
if (result == -1)
***************
*** 1593,1599 ****
/* call this one */
static bool
! do_edit(const char *filename_arg, PQExpBuffer query_buf, bool *edited)
{
char fnametmp[MAXPGPATH];
FILE *stream = NULL;
--- 1805,1811 ----
/* call this one */
static bool
! do_edit(const char *filename_arg, PQExpBuffer query_buf, int lineno, bool *edited)
{
char fnametmp[MAXPGPATH];
FILE *stream = NULL;
***************
*** 1685,1691 ****
/* call editor */
if (!error)
! error = !editFile(fname);
if (!error && stat(fname, &after) != 0)
{
--- 1897,1936 ----
/* call editor */
if (!error)
! {
! /* skip header lines */
! if (lineno != -1)
! {
! char *lines = query_buf->data;
! char *dqtag;
!
! /* we have to detect number of header lines */
! while (*lines)
! {
! char *end_of_line = strchr(lines, '\n');
!
! if (end_of_line)
! *end_of_line = '\0';
!
! dqtag = get_functiondef_dollarquote_tag(lines);
! if (dqtag)
! {
! free(dqtag);
! break;
! }
!
! lineno++;
!
! /* leave when there are not next row */
! if (!end_of_line)
! break;
!
! lines = end_of_line + 1;
! }
! }
!
! error = !editFile(fname, lineno);
! }
if (!error && stat(fname, &after) != 0)
{
***************
*** 2241,2243 ****
--- 2486,2583 ----
destroyPQExpBuffer(msg);
}
+
+
+ /*
+ * Returns lineno used in \sf and \ef commands.
+ *
+ * These commands can be completed with number used as line
+ * number for navigation in showed lines / open file. The most
+ * simple method for parsing is reading isolated digits from
+ * right - \ef foo nn, \ef foo(..)nn. Returns -1 when
+ * lineno isn't used in function's descriptor.
+ */
+ static int
+ extract_lineno_from_funcdesc(char *func, backslashResult *status)
+ {
+ char *endfunc;
+ char *c;
+ int lineno = -1;
+
+ if (!func)
+ return lineno;
+
+ endfunc = func + strlen(func) - 1;
+ c = endfunc;
+
+ /* skip useles whitespaces */
+ while (c >= func && isblank(*c))
+ c--;
+
+ /* search the most left digit of continuously number */
+ while (c >= func && isdigit(*c))
+ c--;
+
+ /*
+ * when left char isn't blank and isn't a right parenthesis
+ * then command hasn't a lineno.
+ */
+ if (c < endfunc && c > func)
+ {
+ /*
+ * digits have to be a separated from identifier by right
+ * parenthesis or by space, and there have to be entered
+ * minimal one digit.
+ */
+ if (isdigit(c[1]) && ( isblank(*c) || *c == ')' ))
+ {
+ c++;
+
+ lineno = atoi(c);
+ if (lineno < 1)
+ {
+ psql_error("invalid line number\n");
+ *status = PSQL_CMD_ERROR;
+ }
+ else
+ {
+ /* remove lineno from function descriptor */
+ *c = '\0';
+ }
+ }
+ }
+
+ return lineno;
+ }
+
+ /*
+ * Returns tag of dollar quoted string used as function body, It parses
+ * only result of pg_get_functiondef function, so there are not possibility
+ * use just "'" char. When row doesn't contain a AS part of CREATE FUNCTION
+ * command, then it returns NULL.
+ */
+ static char *
+ get_functiondef_dollarquote_tag(char *row)
+ {
+ char *starttag;
+ char *endtag;
+ int len;
+ char *result;
+
+ /* leave when line doesn't contain a body separator */
+ if (strncmp(row, "AS $function", 12) != 0)
+ return NULL;
+
+ /* detect body's tag */
+ starttag = row + strlen("AS ");
+ endtag = strchr(row + strlen("AS $function"), '$');
+
+ psql_assert(endtag);
+
+ len = endtag - starttag + 1;
+ result = pg_malloc(len + 1);
+ memcpy(result, starttag, len);
+ result[len] = '\0';
+
+ return result;
+ }
*** ./src/bin/psql/help.c.orig 2010-08-03 09:00:48.387710077 +0200
--- ./src/bin/psql/help.c 2010-08-03 13:16:22.264713224 +0200
***************
*** 162,168 ****
{
FILE *output;
! output = PageOutput(87, pager);
/* if you add/remove a line here, change the row count above */
--- 162,168 ----
{
FILE *output;
! output = PageOutput(90, pager);
/* if you add/remove a line here, change the row count above */
***************
*** 174,186 ****
fprintf(output, "\n");
fprintf(output, _("Query Buffer\n"));
! fprintf(output, _(" \\e [FILE] edit the query buffer (or file) with external editor\n"));
! fprintf(output, _(" \\ef [FUNCNAME] edit function definition with external editor\n"));
fprintf(output, _(" \\p show the contents of the query buffer\n"));
fprintf(output, _(" \\r reset (clear) the query buffer\n"));
#ifdef USE_READLINE
fprintf(output, _(" \\s [FILE] display history or save it to file\n"));
#endif
fprintf(output, _(" \\w FILE write query buffer to file\n"));
fprintf(output, "\n");
--- 174,187 ----
fprintf(output, "\n");
fprintf(output, _("Query Buffer\n"));
! fprintf(output, _(" \\e [FILE] [lno] edit the query buffer (or file) with external editor\n"));
! fprintf(output, _(" \\ef [FUNCNAME] [lno] edit function definition with external editor\n"));
fprintf(output, _(" \\p show the contents of the query buffer\n"));
fprintf(output, _(" \\r reset (clear) the query buffer\n"));
#ifdef USE_READLINE
fprintf(output, _(" \\s [FILE] display history or save it to file\n"));
#endif
+ fprintf(output, _(" \\sf[+] FUNCNAME [lno] show finction definition\n"));
fprintf(output, _(" \\w FILE write query buffer to file\n"));
fprintf(output, "\n");
*** ./src/bin/psql/tab-complete.c.orig 2010-08-03 09:00:48.390710399 +0200
--- ./src/bin/psql/tab-complete.c 2010-08-03 09:01:05.996710353 +0200
***************
*** 644,650 ****
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
! "\\set", "\\t", "\\T",
"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
};
--- 644,650 ----
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
! "\\set", "\\sf", "\\t", "\\T",
"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
};
***************
*** 2501,2506 ****
--- 2501,2509 ----
else if (strcmp(prev_wd, "\\ef") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+
+ else if (strncmp(prev_wd, "\\sf", 2) == 0)
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
else if (strcmp(prev_wd, "\\encoding") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers