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

Reply via email to