1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Fix bugs in plpgsql's handling of CALL argument lists.

exec_stmt_call() tried to extract information out of a CALL statement's
argument list without using expand_function_arguments(), apparently in
the hope of saving a few nanoseconds by not processing defaulted
arguments.  It got that quite wrong though, leading to crashes with
named arguments, as well as failure to enforce writability of the
argument for a defaulted INOUT parameter.  Fix and simplify the logic
by using expand_function_arguments() before examining the list.

Also, move the argument-examination to just after producing the CALL
command's plan, before invoking the called procedure.  This ensures
that we'll track possible changes in the procedure's argument list
correctly, and avoids a hazard of the plan cache being flushed while
the procedure executes.

Also fix assorted falsehoods and omissions in associated documentation.

Per bug #15477 from Alexey Stepanov.

Patch by me, with some help from Pavel Stehule.  Back-patch to v11.

Discussion: https://postgr.es/m/15477-86075b1d1d319e0a@postgresql.org
Discussion: https://postgr.es/m/CAFj8pRA6UsujpTs9Sdwmk-R6yQykPx46wgjj+YZ7zxm4onrDyw@mail.gmail.com
This commit is contained in:
Tom Lane
2018-11-04 13:25:39 -05:00
parent 6f4e01c7d2
commit 4b0c3712c5
5 changed files with 300 additions and 126 deletions

View File

@ -1864,15 +1864,29 @@ SELECT * FROM get_available_flightid(CURRENT_DATE);
<para>
A procedure does not have a return value. A procedure can therefore end
without a <command>RETURN</command> statement. If
a <command>RETURN</command> statement is desired to exit the code early,
then <symbol>NULL</symbol> must be returned. Returning any other value
will result in an error.
without a <command>RETURN</command> statement. If you wish to use
a <command>RETURN</command> statement to exit the code early, write
just <command>RETURN</command> with no expression.
</para>
<para>
If a procedure has output parameters, then the output values can be
assigned to the parameters as if they were variables. For example:
If the procedure has output parameters, the final values of the output
parameter variables will be returned to the caller.
</para>
</sect2>
<sect2 id="plpgsql-statements-calling-procedure">
<title>Calling a Procedure</title>
<para>
A <application>PL/pgSQL</application> function, procedure,
or <command>DO</command> block can call a procedure
using <command>CALL</command>. Output parameters are handled
differently from the way that <command>CALL</command> works in plain
SQL. Each <literal>INOUT</literal> parameter of the procedure must
correspond to a variable in the <command>CALL</command> statement, and
whatever the procedure returns is assigned back to that variable after
it returns. For example:
<programlisting>
CREATE PROCEDURE triple(INOUT x int)
LANGUAGE plpgsql
@ -1882,7 +1896,13 @@ BEGIN
END;
$$;
CALL triple(5);
DO $$
DECLARE myvar int := 5;
BEGIN
CALL triple(myvar);
RAISE NOTICE 'myvar = %', myvar; -- prints 15
END
$$;
</programlisting>
</para>
</sect2>

View File

@ -33,7 +33,8 @@ CALL <replaceable class="parameter">name</replaceable> ( [ <replaceable class="p
</para>
<para>
If the procedure has output arguments, then a result row will be returned.
If the procedure has any output parameters, then a result row will be
returned, containing the values of those parameters.
</para>
</refsect1>
@ -54,7 +55,7 @@ CALL <replaceable class="parameter">name</replaceable> ( [ <replaceable class="p
<term><replaceable class="parameter">argument</replaceable></term>
<listitem>
<para>
An argument for the procedure call.
An input argument for the procedure call.
See <xref linkend="sql-syntax-calling-funcs"/> for the full details on
function and procedure call syntax, including use of named parameters.
</para>
@ -81,6 +82,12 @@ CALL <replaceable class="parameter">name</replaceable> ( [ <replaceable class="p
Transaction control statements are only allowed if <command>CALL</command>
is executed in its own transaction.
</para>
<para>
<application>PL/pgSQL</application> handles output parameters
in <command>CALL</command> commands differently;
see <xref linkend="plpgsql-statements-calling-procedure"/>.
</para>
</refsect1>
<refsect1>