Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 409c144

Browse files
committed
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.)
1 parent 2c863ca commit 409c144

File tree

3 files changed

+91
-38
lines changed

3 files changed

+91
-38
lines changed

doc/src/sgml/ref/psql-ref.sgml

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.210 2008/09/06 00:01:21 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.211 2008/09/06 20:18:08 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -1161,7 +1161,7 @@ testdb=&gt;
11611161

11621162

11631163
<varlistentry>
1164-
<term><literal>\edit</literal> (or <literal>\e</literal>) <literal>[ <replaceable class="parameter">filename</replaceable> ]</literal></term>
1164+
<term><literal>\edit</literal> (or <literal>\e</literal>) <literal><optional> <replaceable class="parameter">filename</replaceable> </optional></literal></term>
11651165

11661166
<listitem>
11671167
<para>
@@ -1196,7 +1196,7 @@ testdb=&gt;
11961196

11971197

11981198
<varlistentry>
1199-
<term><literal>\ef <replaceable class="parameter">function_description</replaceable> </literal></term>
1199+
<term><literal>\ef <optional> <replaceable class="parameter">function_description</replaceable> </optional></literal></term>
12001200

12011201
<listitem>
12021202
<para>
@@ -1214,6 +1214,11 @@ testdb=&gt;
12141214
The argument types must be given if there is more
12151215
than one function of the same name.
12161216
</para>
1217+
1218+
<para>
1219+
If no function is specified, a blank <command>CREATE FUNCTION</>
1220+
template is presented for editing.
1221+
</para>
12171222
</listitem>
12181223
</varlistentry>
12191224

src/backend/utils/adt/ruleutils.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.283 2008/09/06 00:01:21 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.284 2008/09/06 20:18:08 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -1543,9 +1543,15 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
15431543
elog(ERROR, "null prosrc");
15441544
prosrc = TextDatumGetCString(tmp);
15451545

1546-
/* We always use dollar quoting. Figure out a suitable delimiter. */
1546+
/*
1547+
* We always use dollar quoting. Figure out a suitable delimiter.
1548+
*
1549+
* Since the user is likely to be editing the function body string,
1550+
* we shouldn't use a short delimiter that he might easily create a
1551+
* conflict with. Hence prefer "$function$", but extend if needed.
1552+
*/
15471553
initStringInfo(&dq);
1548-
appendStringInfoChar(&dq, '$');
1554+
appendStringInfoString(&dq, "$function");
15491555
while (strstr(prosrc, dq.data) != NULL)
15501556
appendStringInfoChar(&dq, 'x');
15511557
appendStringInfoChar(&dq, '$');

src/bin/psql/command.c

+74-32
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.194 2008/09/06 00:01:24 tgl Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.195 2008/09/06 20:18:08 tgl Exp $
77
*/
88
#include "postgres_fe.h"
99
#include "command.h"
@@ -62,6 +62,7 @@ static bool do_connect(char *dbname, char *user, char *host, char *port);
6262
static bool do_shell(const char *command);
6363
static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
6464
static bool get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf);
65+
static void minimal_error_message(PGresult *res);
6566

6667
#ifdef USE_SSL
6768
static void printSSLInfo(void);
@@ -433,15 +434,15 @@ exec_command(const char *cmd,
433434
*/
434435
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
435436
{
436-
char *fname;
437-
438437
if (!query_buf)
439438
{
440439
psql_error("no query buffer\n");
441440
status = PSQL_CMD_ERROR;
442441
}
443442
else
444443
{
444+
char *fname;
445+
445446
fname = psql_scan_slash_option(scan_state,
446447
OT_NORMAL, NULL, true);
447448
expand_tilde(&fname);
@@ -456,53 +457,59 @@ exec_command(const char *cmd,
456457
}
457458

458459
/*
459-
* \ef -- edit the named function in $EDITOR.
460+
* \ef -- edit the named function, or present a blank CREATE FUNCTION
461+
* template if no argument is given
460462
*/
461463
else if (strcmp(cmd, "ef") == 0)
462464
{
463-
char *func;
464-
Oid foid;
465-
466-
func = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, true);
467-
if (!func)
468-
{
469-
psql_error("no function name specified\n");
470-
status = PSQL_CMD_ERROR;
471-
}
472-
else if (!lookup_function_oid(pset.db, func, &foid))
473-
{
474-
psql_error(PQerrorMessage(pset.db));
475-
status = PSQL_CMD_ERROR;
476-
}
477-
else if (!query_buf)
465+
if (!query_buf)
478466
{
479467
psql_error("no query buffer\n");
480468
status = PSQL_CMD_ERROR;
481469
}
482-
else if (!get_create_function_cmd(pset.db, foid, query_buf))
483-
{
484-
psql_error(PQerrorMessage(pset.db));
485-
status = PSQL_CMD_ERROR;
486-
}
487470
else
488471
{
489-
bool edited = false;
472+
char *func;
473+
Oid foid;
490474

491-
if (!do_edit(0, query_buf, &edited))
475+
func = psql_scan_slash_option(scan_state,
476+
OT_WHOLE_LINE, NULL, true);
477+
if (!func)
492478
{
479+
/* set up an empty command to fill in */
480+
printfPQExpBuffer(query_buf,
481+
"CREATE FUNCTION ( )\n"
482+
" RETURNS \n"
483+
" LANGUAGE \n"
484+
" -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
485+
"AS $function$\n"
486+
"\n$function$\n");
487+
}
488+
else if (!lookup_function_oid(pset.db, func, &foid))
489+
{
490+
/* error already reported */
493491
status = PSQL_CMD_ERROR;
494492
}
495-
else if (!edited)
493+
else if (!get_create_function_cmd(pset.db, foid, query_buf))
496494
{
497-
printf("No changes\n");
495+
/* error already reported */
496+
status = PSQL_CMD_ERROR;
498497
}
498+
if (func)
499+
free(func);
500+
}
501+
502+
if (status != PSQL_CMD_ERROR)
503+
{
504+
bool edited = false;
505+
506+
if (!do_edit(0, query_buf, &edited))
507+
status = PSQL_CMD_ERROR;
508+
else if (!edited)
509+
puts(_("No changes."));
499510
else
500-
{
501511
status = PSQL_CMD_NEWEDIT;
502-
}
503512
}
504-
if (func)
505-
free(func);
506513
}
507514

508515
/* \echo and \qecho */
@@ -1998,7 +2005,10 @@ lookup_function_oid(PGconn *conn, const char *desc, Oid *foid)
19982005
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
19992006
*foid = atooid(PQgetvalue(res, 0, 0));
20002007
else
2008+
{
2009+
minimal_error_message(res);
20012010
result = false;
2011+
}
20022012

20032013
PQclear(res);
20042014
destroyPQExpBuffer(query);
@@ -2027,10 +2037,42 @@ get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf)
20272037
appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
20282038
}
20292039
else
2040+
{
2041+
minimal_error_message(res);
20302042
result = false;
2043+
}
20312044

20322045
PQclear(res);
20332046
destroyPQExpBuffer(query);
20342047

20352048
return result;
20362049
}
2050+
2051+
/*
2052+
* Report just the primary error; this is to avoid cluttering the output
2053+
* with, for instance, a redisplay of the internally generated query
2054+
*/
2055+
static void
2056+
minimal_error_message(PGresult *res)
2057+
{
2058+
PQExpBuffer msg;
2059+
const char *fld;
2060+
2061+
msg = createPQExpBuffer();
2062+
2063+
fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
2064+
if (fld)
2065+
printfPQExpBuffer(msg, "%s: ", fld);
2066+
else
2067+
printfPQExpBuffer(msg, "ERROR: ");
2068+
fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
2069+
if (fld)
2070+
appendPQExpBufferStr(msg, fld);
2071+
else
2072+
appendPQExpBufferStr(msg, "(not available)");
2073+
appendPQExpBufferStr(msg, "\n");
2074+
2075+
psql_error(msg->data);
2076+
2077+
destroyPQExpBuffer(msg);
2078+
}

0 commit comments

Comments
 (0)