mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
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.)
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -1161,7 +1161,7 @@ testdb=>
|
|||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
<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>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
@ -1196,7 +1196,7 @@ testdb=>
|
|||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
<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>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
@ -1214,6 +1214,11 @@ testdb=>
|
|||||||
The argument types must be given if there is more
|
The argument types must be given if there is more
|
||||||
than one function of the same name.
|
than one function of the same name.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If no function is specified, a blank <command>CREATE FUNCTION</>
|
||||||
|
template is presented for editing.
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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");
|
elog(ERROR, "null prosrc");
|
||||||
prosrc = TextDatumGetCString(tmp);
|
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);
|
initStringInfo(&dq);
|
||||||
appendStringInfoChar(&dq, '$');
|
appendStringInfoString(&dq, "$function");
|
||||||
while (strstr(prosrc, dq.data) != NULL)
|
while (strstr(prosrc, dq.data) != NULL)
|
||||||
appendStringInfoChar(&dq, 'x');
|
appendStringInfoChar(&dq, 'x');
|
||||||
appendStringInfoChar(&dq, '$');
|
appendStringInfoChar(&dq, '$');
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
|
* 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 "postgres_fe.h"
|
||||||
#include "command.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 do_shell(const char *command);
|
||||||
static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
|
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 bool get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf);
|
||||||
|
static void minimal_error_message(PGresult *res);
|
||||||
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
static void printSSLInfo(void);
|
static void printSSLInfo(void);
|
||||||
@ -433,8 +434,6 @@ exec_command(const char *cmd,
|
|||||||
*/
|
*/
|
||||||
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
|
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
|
||||||
{
|
{
|
||||||
char *fname;
|
|
||||||
|
|
||||||
if (!query_buf)
|
if (!query_buf)
|
||||||
{
|
{
|
||||||
psql_error("no query buffer\n");
|
psql_error("no query buffer\n");
|
||||||
@ -442,6 +441,8 @@ exec_command(const char *cmd,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char *fname;
|
||||||
|
|
||||||
fname = psql_scan_slash_option(scan_state,
|
fname = psql_scan_slash_option(scan_state,
|
||||||
OT_NORMAL, NULL, true);
|
OT_NORMAL, NULL, true);
|
||||||
expand_tilde(&fname);
|
expand_tilde(&fname);
|
||||||
@ -456,53 +457,59 @@ 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)
|
else if (strcmp(cmd, "ef") == 0)
|
||||||
{
|
{
|
||||||
char *func;
|
if (!query_buf)
|
||||||
Oid foid;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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");
|
psql_error("no query buffer\n");
|
||||||
status = PSQL_CMD_ERROR;
|
status = PSQL_CMD_ERROR;
|
||||||
}
|
}
|
||||||
else if (!get_create_function_cmd(pset.db, foid, query_buf))
|
|
||||||
{
|
|
||||||
psql_error(PQerrorMessage(pset.db));
|
|
||||||
status = PSQL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
char *func;
|
||||||
|
Oid foid;
|
||||||
|
|
||||||
|
func = psql_scan_slash_option(scan_state,
|
||||||
|
OT_WHOLE_LINE, NULL, true);
|
||||||
|
if (!func)
|
||||||
|
{
|
||||||
|
/* 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))
|
||||||
|
{
|
||||||
|
/* error already reported */
|
||||||
|
status = PSQL_CMD_ERROR;
|
||||||
|
}
|
||||||
|
else if (!get_create_function_cmd(pset.db, foid, query_buf))
|
||||||
|
{
|
||||||
|
/* error already reported */
|
||||||
|
status = PSQL_CMD_ERROR;
|
||||||
|
}
|
||||||
|
if (func)
|
||||||
|
free(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != PSQL_CMD_ERROR)
|
||||||
{
|
{
|
||||||
bool edited = false;
|
bool edited = false;
|
||||||
|
|
||||||
if (!do_edit(0, query_buf, &edited))
|
if (!do_edit(0, query_buf, &edited))
|
||||||
{
|
|
||||||
status = PSQL_CMD_ERROR;
|
status = PSQL_CMD_ERROR;
|
||||||
}
|
|
||||||
else if (!edited)
|
else if (!edited)
|
||||||
{
|
puts(_("No changes."));
|
||||||
printf("No changes\n");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
status = PSQL_CMD_NEWEDIT;
|
status = PSQL_CMD_NEWEDIT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (func)
|
|
||||||
free(func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \echo and \qecho */
|
/* \echo and \qecho */
|
||||||
@ -1998,7 +2005,10 @@ lookup_function_oid(PGconn *conn, const char *desc, Oid *foid)
|
|||||||
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
|
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
|
||||||
*foid = atooid(PQgetvalue(res, 0, 0));
|
*foid = atooid(PQgetvalue(res, 0, 0));
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
minimal_error_message(res);
|
||||||
result = false;
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
destroyPQExpBuffer(query);
|
destroyPQExpBuffer(query);
|
||||||
@ -2027,10 +2037,42 @@ get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf)
|
|||||||
appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
|
appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
minimal_error_message(res);
|
||||||
result = false;
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
destroyPQExpBuffer(query);
|
destroyPQExpBuffer(query);
|
||||||
|
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user