Hello updated patch attached
2010/8/4 Robert Haas <robertmh...@gmail.com>: > On Tue, Aug 3, 2010 at 7:20 AM, Pavel Stehule <pavel.steh...@gmail.com> 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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers