Thanks to visit codestin.com
Credit goes to github.com

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

Lines changed: 8 additions & 3 deletions
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

Lines changed: 9 additions & 3 deletions
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

Lines changed: 74 additions & 32 deletions
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)