Hi. I'm working on a patch where if you say "\ef foo" in psql, it'll start $EDITOR with a "CREATE OR REPLACE FUNCTION" statement to recreate the function. So you edit and save and quit, and if you made any changes, psql will execute the statement.
The psql(/command.c) parts of this are quite simple. I've attached a patch to demonstrate the idea. The problem is, of course, generating the "CREATE OR REPLACE" statement. There is some code to do this in pg_dump.c:dumpFunc(), but it's strongly tied to pg_dump (global variables, output to Archive *, dependencies on other functions, etc.). I could either try to duplicate this code (and there's a lot of it), or rip dumpFunc() and its dependencies out of pg_dump into dumpfunc.c and make it callable both by pg_dump and psql. I've done some work towards the latter, so I know it's possible, but it's a lot of work, which I don't want to do if it won't be accepted anyway. I would appreciate some advice on how to proceed. -- ams
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index f66fd7e..3724533 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -35,6 +35,7 @@ #include "libpq-fe.h" #include "pqexpbuffer.h" #include "dumputils.h" +#include "dumpfunc.h" #include "common.h" #include "copy.h" @@ -53,7 +54,7 @@ static backslashResult exec_command(const char *cmd, PsqlScanState scan_state, PQExpBuffer query_buf); -static bool do_edit(const char *filename_arg, PQExpBuffer query_buf); +static bool do_edit(const char *, PQExpBuffer, bool *); static bool do_connect(char *dbname, char *user, char *host, char *port); static bool do_shell(const char *command); @@ -432,11 +433,71 @@ exec_command(const char *cmd, expand_tilde(&fname); if (fname) canonicalize_path(fname); - status = do_edit(fname, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR; + if (do_edit(fname, query_buf, 0)) + status = PSQL_CMD_NEWEDIT; + else + status = PSQL_CMD_ERROR; free(fname); } } + /* + * \ef -- edit the named function in $EDITOR. + */ + + else if (strcmp(cmd, "ef") == 0) + { + Oid foid; + char *func; + + func = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, true); + if (!func) + { + psql_error("no function name specified\n"); + status = PSQL_CMD_ERROR; + } + + if (!lookup_function_oid(pset.db, func, &foid)) + { + psql_error(PQerrorMessage(pset.db)); + status = PSQL_CMD_ERROR; + } + else + { + bool edited = false; + + termPQExpBuffer(query_buf); + if (foid) + { + char *s = create_or_replace_function_text(foid); + appendPQExpBufferStr(query_buf, s); + free(s); + } + else + { + printfPQExpBuffer(query_buf, + "CREATE FUNCTION %s%s RETURNS ... AS $$\n" + "...\n" + "$$ LANGUAGE '...'\n", + func, strchr(func,'(') ? "" : "(...)" ); + } + + if (!do_edit(0, query_buf, &edited)) + { + status = PSQL_CMD_ERROR; + } + else if (!edited) + { + printf("No changes\n"); + } + else + { + status = PSQL_CMD_SEND; + } + free(func); + } + } + /* \echo and \qecho */ else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0) { @@ -1298,7 +1359,7 @@ editFile(const char *fname) /* call this one */ static bool -do_edit(const char *filename_arg, PQExpBuffer query_buf) +do_edit(const char *filename_arg, PQExpBuffer query_buf, bool *edited) { char fnametmp[MAXPGPATH]; FILE *stream = NULL; @@ -1420,6 +1481,10 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf) psql_error("%s: %s\n", fname, strerror(errno)); error = true; } + else if (edited) + { + *edited = true; + } fclose(stream); }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers