*** ./doc/src/sgml/ref/psql-ref.sgml.orig 2010-03-21 01:43:40.000000000 +0100 --- ./doc/src/sgml/ref/psql-ref.sgml 2010-03-29 18:19:24.496359110 +0200 *************** *** 1328,1334 **** ! \edit (or \e) filename --- 1328,1334 ---- ! \edit (or \e) filename linenumber *************** *** 1358,1369 **** systems, notepad.exe on Windows systems. ! \ef function_description --- 1358,1375 ---- systems, notepad.exe on Windows systems. + + + If linenumber is + specified, then cursor is moved on this line after start of + editor. + ! \ef function_description linenumber *************** *** 1386,1391 **** --- 1392,1404 ---- If no function is specified, a blank CREATE FUNCTION template is presented for editing. + + + If linenumber 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. + *************** *** 2105,2110 **** --- 2118,2135 ---- + \sf[+] function_description linenumber + + + + This command fetches and shows the definition of the named function, + in the form of a CREATE OR REPLACE FUNCTION command. + If the form \sf+ is used, then lines are numbered. + + + + + \t *************** *** 2112,2117 **** --- 2137,2148 ---- footer. This command is equivalent to \pset tuples_only and is provided for convenience. + + + If linenumber is + specified, then cursor is moved on this line after start of + editor. + *** ./src/bin/psql/command.c.orig 2010-03-29 13:46:55.227484734 +0200 --- ./src/bin/psql/command.c 2010-03-29 16:17:22.220361245 +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); *************** *** 488,500 **** 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; --- 488,517 ---- else { char *fname; ! char *lineno; ! int ln, ! *lnptr = NULL; ! ! fname = psql_scan_slash_option(scan_state, ! OT_NORMAL, NULL, true); ! ! /* try to get lineno */ ! if (fname) ! { ! lineno = psql_scan_slash_option(scan_state, ! OT_NORMAL, NULL, true); ! if (lineno) ! { ! ln = atoi(lineno); ! lnptr = &ln; ! } ! } ! expand_tilde(&fname); if (fname) canonicalize_path(fname); ! if (do_edit(fname, query_buf, NULL, lnptr)) status = PSQL_CMD_NEWEDIT; else status = PSQL_CMD_ERROR; *************** *** 508,513 **** --- 525,533 ---- */ else if (strcmp(cmd, "ef") == 0) { + int lineno; + int *lnptr = NULL; + if (!query_buf) { psql_error("no query buffer\n"); *************** *** 520,525 **** --- 540,574 ---- func = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, true); + + /* + * parse linenumber from the right + */ + if (func && *func) + { + char *endfunc = func + strlen(func) - 1; + char *c; + + c = endfunc; + while (c >= func) + if (!isdigit(*c)) + break; + else + c--; + + if (c < endfunc && c > func) + { + if (*c == ' ' || *c == ')') + { + c++; + /* append rows for SQL decoration */ + lineno = atoi(c) + 3; + *c = '\0'; + lnptr = &lineno; + } + } + } + if (!func) { /* set up an empty command to fill in */ *************** *** 549,555 **** { bool edited = false; ! if (!do_edit(0, query_buf, &edited)) status = PSQL_CMD_ERROR; else if (!edited) puts(_("No changes")); --- 598,604 ---- { bool edited = false; ! if (!do_edit(0, query_buf, &edited, lnptr)) status = PSQL_CMD_ERROR; else if (!edited) puts(_("No changes")); *************** *** 933,938 **** --- 982,1092 ---- free(fname); } + /* + * \sf -- show the named function + */ + else if (strncmp(cmd, "sf", 2) == 0) + { + int lineno; + int *lnptr = NULL; + bool with_lno = false; + + if (strcmp(cmd, "sf+") == 0) + with_lno = true; + + 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); + + /* + * parse linenumber from the right + */ + if (func && *func) + { + char *endfunc = func + strlen(func) - 1; + char *c; + + c = endfunc; + while (c >= func) + if (!isdigit(*c)) + break; + else + c--; + + if (c < endfunc && c > func) + { + if (*c == ' ' || *c == ')') + { + c++; + /* append rows for SQL decoration */ + lineno = atoi(c) + 3; + *c = '\0'; + lnptr = &lineno; + } + } + } + + 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 *c = query_buf->data; + char *ptr; + + printf("\n"); + while (*c) + { + for (ptr = c; *c != '\n'; c++); + *c++ = '\0'; + lineno++; + + if (lnptr && (*lnptr > lineno)) + continue; + + if (!with_lno) + printf("%s\n", ptr); + else + { + /* don't show lineno for first three rows and last row */ + if ((*c == '\0' && lineno != 3) || lineno < 4) + printf("**** %s\n", ptr); + else + printf("%4d %s\n", lineno - 3, ptr); + } + } + printf("\n"); + fflush(stdout); + } + } + /* \set -- generalized set variable/option command */ else if (strcmp(cmd, "set") == 0) { *************** *** 1506,1512 **** */ static bool ! editFile(const char *fname) { const char *editorName; char *sys; --- 1660,1666 ---- */ static bool ! editFile(const char *fname, int *lineno) { const char *editorName; char *sys; *************** *** 1530,1540 **** * 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) --- 1684,1703 ---- * severe brain damage in their command shell plus the fact that standard * program paths include spaces. */ ! sys = pg_malloc(strlen(editorName) + strlen(fname) + 20 + 1); #ifndef WIN32 ! if (!lineno) ! sprintf(sys, "exec %s '%s'", editorName, fname); ! else ! sprintf(sys, "exec %s +%d '%s'", editorName, *lineno, fname); #else ! if (!lineno) ! sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE, editorName, fname); ! else ! sprintf(sys, SYSTEMQUOTE "\"%s\" +%d \"%s\"" SYSTEMQUOTE, ! editorName, ! *lineno, ! fname); #endif result = system(sys); if (result == -1) *************** *** 1549,1555 **** /* call this one */ static bool ! do_edit(const char *filename_arg, PQExpBuffer query_buf, bool *edited) { char fnametmp[MAXPGPATH]; FILE *stream = NULL; --- 1712,1718 ---- /* call this one */ static bool ! do_edit(const char *filename_arg, PQExpBuffer query_buf, bool *edited, int *lineno) { char fnametmp[MAXPGPATH]; FILE *stream = NULL; *************** *** 1641,1647 **** /* call editor */ if (!error) ! error = !editFile(fname); if (!error && stat(fname, &after) != 0) { --- 1804,1810 ---- /* call editor */ if (!error) ! error = !editFile(fname, lineno); if (!error && stat(fname, &after) != 0) { *************** *** 2197,2199 **** --- 2360,2363 ---- destroyPQExpBuffer(msg); } + *** ./src/bin/psql/help.c.orig 2010-03-07 18:02:34.000000000 +0100 --- ./src/bin/psql/help.c 2010-03-29 16:31:31.563360499 +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-02-26 03:01:20.000000000 +0100 --- ./src/bin/psql/tab-complete.c 2010-03-29 16:27:06.543359758 +0200 *************** *** 639,645 **** "\\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 }; --- 639,645 ---- "\\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 }; *************** *** 2446,2451 **** --- 2446,2454 ---- 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);