attached updated patch
* don't use a default option for navigation in editor - user have to
set this option explicitly
* name for this psql variable is EDITOR_LINENUMBER_SWITCH -
* updated comments, doc and some issues described by Robert
Regards
Pavel Stehule
2010/8/3 Robert Haas <[email protected]>:
> On Sun, Aug 1, 2010 at 11:48 PM, Robert Haas <[email protected]> wrote:
>>> b) more robust algorithm for header rows identification
>>
>> Have not gotten to this one yet.
>
> I notIce that on WIN32 the default editor is notepad.exe and the
> default editor navigation option is "/". Does "notepad.exe /lineno
> filename" actually work on Windows? A quick Google search suggests
> that the answer is "no", which seems somewhat unfortunate: it means
> we'd be shipping "broken on Win32 out of the box".
>
> http://www.robvanderwoude.com/commandlineswitches.php#Notepad
>
> This is actually my biggest concern about this patch - that it may be
> just too much of a hassle to actually make it work for people. I just
> tried setting $EDITOR to MacOS's TextEdit program, and it turns out
> that TextEdit doesn't understand +. I'm afraid that we're going to
> end up with a situation where it only works for people using emacs or
> vi, and everyone else ends up with a broken install (and, possibly, no
> clear idea how to fix it). Perhaps it would be better to accept \sf
> and reject \sf+ and \ef <func> <lineno>.
>
> Assuming we get past that threshold issue, I'm also wondering whether
> the "navigation option" terminology is best; e.g. set
> PSQL_EDITOR_NAVIGATION_OPTION to configure it. It doesn't seem
> terrible, but it doesn't seem great, either. Anyone have a better
> idea?
>
> The docs are a little rough; they could benefit from some editing by a
> fluent English speaker. If anyone has time to work on this, it would
> be much appreciated.
>
> Instead of "line number is unacceptable", I think you should write
> "invalid line number".
>
> "dollar" should not be spelled "dolar". "function" should not be
> spelled "finction".
>
> This change looks suspiciously like magic. If it's actually safe, it
> needs a comment explaining why:
>
> - sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
> + sys = pg_malloc(strlen(editorName) + strlen(fname) + 20 + 1);
>
> Attempting to compile with this patch applied emits a warning on my
> machine; whether or not the warning is valid, you need to make it go
> away:
>
> command.c: In function ‘HandleSlashCmds’:
> command.c:1055: warning: ‘bsep’ may be used uninitialized in this function
> command.c:1055: note: ‘bsep’ was declared here
>
> Why does the \sf output have a trailing blank line? This seems weird,
> especially because \ef puts no such trailing blank line in the editor.
>
> Instead of:
>
> + /* skip useles whitespaces */
> + while (c >= func)
> + if (isblank(*c))
> + c--;
> + else
> + break;
>
> ...wouldn't it be just as good to write:
>
> while (c >= func && isblank(*c))
> c--;
>
> (and similarly elsewhere)
>
> In extract_separator, if you invert the sense of the first if-test,
> then you can avoid having to indent the entire function contents.
>
> --
> 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-03 10:56:43.901709512 +0200
***************
*** 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);
--- 57,63 ----
PsqlScanState scan_state,
PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
! bool *edited, int lineno);
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 ****
--- 66,74 ----
static void printSSLInfo(void);
+ static int extract_lineno_from_funcdesc(char *func, backslashResult *status);
+ static char *get_dq_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);
}
}
--- 516,553 ----
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)
! {
! if (atoi(ln) < 1)
! {
! psql_error("invalid line number\n");
! status = PSQL_CMD_ERROR;
! }
! else
! lineno = atoi(ln);
! }
! }
! if (status != PSQL_CMD_ERROR)
! {
! expand_tilde(&fname);
! if (fname)
! canonicalize_path(fname);
! if (do_edit(fname, query_buf, NULL, lineno))
! status = PSQL_CMD_NEWEDIT;
! else
! status = PSQL_CMD_ERROR;
! }
free(fname);
}
}
***************
*** 533,538 ****
--- 558,565 ----
*/
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"));
--- 572,612 ----
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, &edited, lineno))
status = PSQL_CMD_ERROR;
else if (!edited)
puts(_("No changes"));
***************
*** 969,974 ****
--- 1001,1123 ----
free(fname);
}
+ /*
+ * \sf -- show the named function
+ */
+ else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
+ {
+ int skip_lines = -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);
+ skip_lines = 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 *lines = query_buf->data;
+ char *dqtag = NULL;
+ bool is_header = true;
+ bool is_body = false;
+ bool is_footer = false;
+ char *end_of_line;
+
+ while (*lines)
+ {
+ /* find next end of line */
+ end_of_line = strchr(lines, '\n');
+ if (end_of_line)
+ *end_of_line = '\0';
+
+ if (is_header)
+ {
+ /* detect end of header */
+ dqtag = get_dq_tag(lines);
+ if (dqtag)
+ {
+ is_header = false;
+ is_body = true;
+ lineno = 1;
+ }
+ }
+ else if (is_body)
+ {
+ lineno++;
+ if (strcmp(lines, dqtag) == 0)
+ {
+ is_body = false;
+ is_footer = true;
+ }
+ }
+
+ /* can we show rows? */
+ if (skip_lines < 0 || (skip_lines <= lineno))
+ {
+ if (with_lno)
+ {
+ if (is_header || is_footer)
+ printf("**** %s", lines);
+ else
+ printf("%4d %s", lineno, lines);
+ }
+ else
+ printf("%s", lines);
+
+ /* return back replaced "\n" */
+ if (end_of_line)
+ printf("\n");
+ }
+
+ if (end_of_line)
+ lines = end_of_line + 1;
+ else
+ break;
+ }
+
+ /* function pg_get_functiondef uses dollar quoted strings always */
+ psql_assert(dqtag);
+ free(dqtag);
+
+ fflush(stdout);
+ }
+ }
+
/* \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;
--- 1699,1708 ----
*/
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
--- 1716,1733 ----
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("cannot use a editor navigation without setting EDITOR_LINENUMBER_SWITCH variable\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)
--- 1735,1767 ----
* 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;
--- 1776,1782 ----
/* call this one */
static bool
! do_edit(const char *filename_arg, PQExpBuffer query_buf, bool *edited, int lineno)
{
char fnametmp[MAXPGPATH];
FILE *stream = NULL;
***************
*** 1685,1691 ****
/* call editor */
if (!error)
! error = !editFile(fname);
if (!error && stat(fname, &after) != 0)
{
--- 1868,1906 ----
/* 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_dq_tag(lines);
! if (dqtag)
! {
! free(dqtag);
! break;
! }
! else
! lineno++;
!
! if (end_of_line)
! lines = end_of_line + 1;
! else
! break;
! }
! }
!
! error = !editFile(fname, lineno);
! }
if (!error && stat(fname, &after) != 0)
{
***************
*** 2213,2218 ****
--- 2428,2434 ----
return result;
}
+
/*
* Report just the primary error; this is to avoid cluttering the output
* with, for instance, a redisplay of the internally generated query
***************
*** 2241,2243 ****
--- 2457,2549 ----
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)
+ {
+ if (isblank(*c) || *c == ')')
+ {
+ c++;
+
+ if (atoi(c) < 1)
+ {
+ psql_error("invalid line number\n");
+ *status = PSQL_CMD_ERROR;
+ }
+ else
+ {
+ lineno = atoi(c);
+ /* 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_dq_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 09:01:05.994713167 +0200
***************
*** 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