Commit 409c144d authored by Tom Lane's avatar Tom Lane

Adjust psql's new \ef command to present an empty CREATE FUNCTION template

for editing if no function name is specified.  This seems a much cleaner way
to offer that functionality than the original patch had.  In passing,
de-clutter the error displays that are given for a bogus function-name
argument, and standardize on "$function$" as the default delimiter for the
function body.  (The original coding would use the shortest possible
dollar-quote delimiter, which seems to create unnecessarily high risk of
later conflicts with the user-modified function body.)
parent 2c863ca8
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.210 2008/09/06 00:01:21 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.211 2008/09/06 20:18:08 tgl Exp $
PostgreSQL documentation
-->
......@@ -1161,7 +1161,7 @@ testdb=&gt;
<varlistentry>
<term><literal>\edit</literal> (or <literal>\e</literal>) <literal>[ <replaceable class="parameter">filename</replaceable> ]</literal></term>
<term><literal>\edit</literal> (or <literal>\e</literal>) <literal><optional> <replaceable class="parameter">filename</replaceable> </optional></literal></term>
<listitem>
<para>
......@@ -1196,7 +1196,7 @@ testdb=&gt;
<varlistentry>
<term><literal>\ef <replaceable class="parameter">function_description</replaceable> </literal></term>
<term><literal>\ef <optional> <replaceable class="parameter">function_description</replaceable> </optional></literal></term>
<listitem>
<para>
......@@ -1214,6 +1214,11 @@ testdb=&gt;
The argument types must be given if there is more
than one function of the same name.
</para>
<para>
If no function is specified, a blank <command>CREATE FUNCTION</>
template is presented for editing.
</para>
</listitem>
</varlistentry>
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.283 2008/09/06 00:01:21 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.284 2008/09/06 20:18:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1543,9 +1543,15 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
elog(ERROR, "null prosrc");
prosrc = TextDatumGetCString(tmp);
/* We always use dollar quoting. Figure out a suitable delimiter. */
/*
* We always use dollar quoting. Figure out a suitable delimiter.
*
* Since the user is likely to be editing the function body string,
* we shouldn't use a short delimiter that he might easily create a
* conflict with. Hence prefer "$function$", but extend if needed.
*/
initStringInfo(&dq);
appendStringInfoChar(&dq, '$');
appendStringInfoString(&dq, "$function");
while (strstr(prosrc, dq.data) != NULL)
appendStringInfoChar(&dq, 'x');
appendStringInfoChar(&dq, '$');
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.194 2008/09/06 00:01:24 tgl Exp $
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.195 2008/09/06 20:18:08 tgl Exp $
*/
#include "postgres_fe.h"
#include "command.h"
......@@ -62,6 +62,7 @@ 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);
static bool get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf);
static void minimal_error_message(PGresult *res);
#ifdef USE_SSL
static void printSSLInfo(void);
......@@ -433,8 +434,6 @@ exec_command(const char *cmd,
*/
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
{
char *fname;
if (!query_buf)
{
psql_error("no query buffer\n");
......@@ -442,6 +441,8 @@ exec_command(const char *cmd,
}
else
{
char *fname;
fname = psql_scan_slash_option(scan_state,
OT_NORMAL, NULL, true);
expand_tilde(&fname);
......@@ -456,54 +457,60 @@ exec_command(const char *cmd,
}
/*
* \ef -- edit the named function in $EDITOR.
* \ef -- edit the named function, or present a blank CREATE FUNCTION
* template if no argument is given
*/
else if (strcmp(cmd, "ef") == 0)
{
if (!query_buf)
{
psql_error("no query buffer\n");
status = PSQL_CMD_ERROR;
}
else
{
char *func;
Oid foid;
func = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, true);
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;
/* 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))
{
psql_error(PQerrorMessage(pset.db));
status = PSQL_CMD_ERROR;
}
else if (!query_buf)
{
psql_error("no query buffer\n");
/* error already reported */
status = PSQL_CMD_ERROR;
}
else if (!get_create_function_cmd(pset.db, foid, query_buf))
{
psql_error(PQerrorMessage(pset.db));
/* error already reported */
status = PSQL_CMD_ERROR;
}
else
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)
{
printf("No changes\n");
}
puts(_("No changes."));
else
{
status = PSQL_CMD_NEWEDIT;
}
}
if (func)
free(func);
}
/* \echo and \qecho */
else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
......@@ -1998,7 +2005,10 @@ lookup_function_oid(PGconn *conn, const char *desc, Oid *foid)
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
*foid = atooid(PQgetvalue(res, 0, 0));
else
{
minimal_error_message(res);
result = false;
}
PQclear(res);
destroyPQExpBuffer(query);
......@@ -2027,10 +2037,42 @@ get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf)
appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
}
else
{
minimal_error_message(res);
result = false;
}
PQclear(res);
destroyPQExpBuffer(query);
return result;
}
/*
* Report just the primary error; this is to avoid cluttering the output
* with, for instance, a redisplay of the internally generated query
*/
static void
minimal_error_message(PGresult *res)
{
PQExpBuffer msg;
const char *fld;
msg = createPQExpBuffer();
fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
if (fld)
printfPQExpBuffer(msg, "%s: ", fld);
else
printfPQExpBuffer(msg, "ERROR: ");
fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
if (fld)
appendPQExpBufferStr(msg, fld);
else
appendPQExpBufferStr(msg, "(not available)");
appendPQExpBufferStr(msg, "\n");
psql_error(msg->data);
destroyPQExpBuffer(msg);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment