mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Add procedure support to pg_get_functiondef
This also makes procedures work in psql's \ef and \sf commands. Reported-by: Pavel Stehule <pavel.stehule@gmail.com>
This commit is contained in:
@ -17008,22 +17008,22 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
|||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_functiondef(<parameter>func_oid</parameter>)</function></literal></entry>
|
<entry><literal><function>pg_get_functiondef(<parameter>func_oid</parameter>)</function></literal></entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>get definition of a function</entry>
|
<entry>get definition of a function or procedure</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_function_arguments(<parameter>func_oid</parameter>)</function></literal></entry>
|
<entry><literal><function>pg_get_function_arguments(<parameter>func_oid</parameter>)</function></literal></entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>get argument list of function's definition (with default values)</entry>
|
<entry>get argument list of function's or procedure's definition (with default values)</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_function_identity_arguments(<parameter>func_oid</parameter>)</function></literal></entry>
|
<entry><literal><function>pg_get_function_identity_arguments(<parameter>func_oid</parameter>)</function></literal></entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>get argument list to identify a function (without default values)</entry>
|
<entry>get argument list to identify a function or procedure (without default values)</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_function_result(<parameter>func_oid</parameter>)</function></literal></entry>
|
<entry><literal><function>pg_get_function_result(<parameter>func_oid</parameter>)</function></literal></entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>get <literal>RETURNS</literal> clause for function</entry>
|
<entry>get <literal>RETURNS</literal> clause for function (returns null for a procedure)</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_indexdef(<parameter>index_oid</parameter>)</function></literal></entry>
|
<entry><literal><function>pg_get_indexdef(<parameter>index_oid</parameter>)</function></literal></entry>
|
||||||
|
@ -1815,8 +1815,9 @@ Tue Oct 26 21:40:57 CEST 1999
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This command fetches and edits the definition of the named function,
|
This command fetches and edits the definition of the named function or procedure,
|
||||||
in the form of a <command>CREATE OR REPLACE FUNCTION</command> command.
|
in the form of a <command>CREATE OR REPLACE FUNCTION</command> or
|
||||||
|
<command>CREATE OR REPLACE PROCEDURE</command> command.
|
||||||
Editing is done in the same way as for <literal>\edit</literal>.
|
Editing is done in the same way as for <literal>\edit</literal>.
|
||||||
After the editor exits, the updated command waits in the query buffer;
|
After the editor exits, the updated command waits in the query buffer;
|
||||||
type semicolon or <literal>\g</literal> to send it, or <literal>\r</literal>
|
type semicolon or <literal>\g</literal> to send it, or <literal>\r</literal>
|
||||||
@ -2970,8 +2971,9 @@ testdb=> <userinput>\setenv LESS -imx4F</userinput>
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This command fetches and shows the definition of the named function,
|
This command fetches and shows the definition of the named function or procedure,
|
||||||
in the form of a <command>CREATE OR REPLACE FUNCTION</command> command.
|
in the form of a <command>CREATE OR REPLACE FUNCTION</command> or
|
||||||
|
<command>CREATE OR REPLACE PROCEDURE</command> command.
|
||||||
The definition is printed to the current query output channel,
|
The definition is printed to the current query output channel,
|
||||||
as set by <command>\o</command>.
|
as set by <command>\o</command>.
|
||||||
</para>
|
</para>
|
||||||
|
@ -2449,6 +2449,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
|
|||||||
StringInfoData dq;
|
StringInfoData dq;
|
||||||
HeapTuple proctup;
|
HeapTuple proctup;
|
||||||
Form_pg_proc proc;
|
Form_pg_proc proc;
|
||||||
|
bool isfunction;
|
||||||
Datum tmp;
|
Datum tmp;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
const char *prosrc;
|
const char *prosrc;
|
||||||
@ -2472,20 +2473,28 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("\"%s\" is an aggregate function", name)));
|
errmsg("\"%s\" is an aggregate function", name)));
|
||||||
|
|
||||||
|
isfunction = (proc->prorettype != InvalidOid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We always qualify the function name, to ensure the right function gets
|
* We always qualify the function name, to ensure the right function gets
|
||||||
* replaced.
|
* replaced.
|
||||||
*/
|
*/
|
||||||
nsp = get_namespace_name(proc->pronamespace);
|
nsp = get_namespace_name(proc->pronamespace);
|
||||||
appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
|
appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
|
||||||
|
isfunction ? "FUNCTION" : "PROCEDURE",
|
||||||
quote_qualified_identifier(nsp, name));
|
quote_qualified_identifier(nsp, name));
|
||||||
(void) print_function_arguments(&buf, proctup, false, true);
|
(void) print_function_arguments(&buf, proctup, false, true);
|
||||||
appendStringInfoString(&buf, ")\n RETURNS ");
|
appendStringInfoString(&buf, ")\n");
|
||||||
|
if (isfunction)
|
||||||
|
{
|
||||||
|
appendStringInfoString(&buf, " RETURNS ");
|
||||||
print_function_rettype(&buf, proctup);
|
print_function_rettype(&buf, proctup);
|
||||||
|
appendStringInfoChar(&buf, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
print_function_trftypes(&buf, proctup);
|
print_function_trftypes(&buf, proctup);
|
||||||
|
|
||||||
appendStringInfo(&buf, "\n LANGUAGE %s\n",
|
appendStringInfo(&buf, " LANGUAGE %s\n",
|
||||||
quote_identifier(get_language_name(proc->prolang, false)));
|
quote_identifier(get_language_name(proc->prolang, false)));
|
||||||
|
|
||||||
/* Emit some miscellaneous options on one line */
|
/* Emit some miscellaneous options on one line */
|
||||||
@ -2607,10 +2616,11 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
|
|||||||
*
|
*
|
||||||
* Since the user is likely to be editing the function body string, we
|
* 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
|
* shouldn't use a short delimiter that he might easily create a conflict
|
||||||
* with. Hence prefer "$function$", but extend if needed.
|
* with. Hence prefer "$function$"/"$procedure$", but extend if needed.
|
||||||
*/
|
*/
|
||||||
initStringInfo(&dq);
|
initStringInfo(&dq);
|
||||||
appendStringInfoString(&dq, "$function");
|
appendStringInfoChar(&dq, '$');
|
||||||
|
appendStringInfoString(&dq, (isfunction ? "function" : "procedure"));
|
||||||
while (strstr(prosrc, dq.data) != NULL)
|
while (strstr(prosrc, dq.data) != NULL)
|
||||||
appendStringInfoChar(&dq, 'x');
|
appendStringInfoChar(&dq, 'x');
|
||||||
appendStringInfoChar(&dq, '$');
|
appendStringInfoChar(&dq, '$');
|
||||||
|
@ -30,6 +30,17 @@ CALL ptest1(substring(random()::text, 1, 1)); -- ok, volatile arg
|
|||||||
public | ptest1 | | x text | proc
|
public | ptest1 | | x text | proc
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_get_functiondef('ptest1'::regproc);
|
||||||
|
pg_get_functiondef
|
||||||
|
---------------------------------------------------
|
||||||
|
CREATE OR REPLACE PROCEDURE public.ptest1(x text)+
|
||||||
|
LANGUAGE sql +
|
||||||
|
AS $procedure$ +
|
||||||
|
INSERT INTO cp_test VALUES (1, x); +
|
||||||
|
$procedure$ +
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM cp_test ORDER BY b COLLATE "C";
|
SELECT * FROM cp_test ORDER BY b COLLATE "C";
|
||||||
a | b
|
a | b
|
||||||
---+-------
|
---+-------
|
||||||
|
@ -17,6 +17,7 @@ CALL ptest1('xy' || 'zzy'); -- ok, constant-folded arg
|
|||||||
CALL ptest1(substring(random()::text, 1, 1)); -- ok, volatile arg
|
CALL ptest1(substring(random()::text, 1, 1)); -- ok, volatile arg
|
||||||
|
|
||||||
\df ptest1
|
\df ptest1
|
||||||
|
SELECT pg_get_functiondef('ptest1'::regproc);
|
||||||
|
|
||||||
SELECT * FROM cp_test ORDER BY b COLLATE "C";
|
SELECT * FROM cp_test ORDER BY b COLLATE "C";
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user