session. A disadvantage is that errors
in a specific expression or command cannot be detected until that
part of the function is reached in execution. (Trivial syntax
errors will be detected during the initial parsing pass, but
anything deeper will not be detected until execution.)
</para>
<para>
<application>PL/pgSQL</application> (or more precisely, the SPI manager) can
furthermore attempt to cache the execution plan associated with any
particular prepared statement. If a cached plan is not used, then
a fresh execution plan is generated on each visit to the statement,
and the current parameter values (that is, <application>PL/pgSQL</application>
variable values) can be used to optimize the selected plan. If the
statement has no parameters, or is executed many times, the SPI manager
will consider creating a <firstterm>generic</firstterm> plan that is not dependent
on specific parameter values, and caching that for re-use. Typically
this will happen only if the execution plan is not very sensitive to
the values of the <application>PL/pgSQL</application> variables referenced in it.
If it is, generating a plan each time is a net win. See <xref
linkend="sql-prepare"/> for more information about the behavior of
prepared statements.
</para>
<para>
Because <application>PL/pgSQL</application> saves prepared statements
and sometimes execution plans in this way,
SQL commands that appear directly in a
<application>PL/pgSQL</application> function must refer to the
same tables and columns on every execution; that is, you cannot use
a parameter as the name of a table or column in an SQL command. To get
around this restriction, you can construct dynamic commands using
the <application>PL/pgSQL</application> <command>EXECUTE</command>
statement — at the price of performing new parse analysis and
constructing a new execution plan on every execution.
</para>
<para>
The mutable nature of record variables presents another problem in this
connection. When fields of a record variable are used in
expressions or statements, the data types of the fields must not
change from one call of the function to the next, since each
expression will be analyzed using the data type that is present
when the expression is first reached. <command>EXECUTE</command> can be
used to get around this problem when necessary.
</para>
<para>
If the same function is used as a trigger for more than one table,
<application>PL/pgSQL</application> prepares and caches statements
independently for each such table — that is, there is a cache
for each trigger function and table combination, not just for each
function. This alleviates some of the problems with varying
data types; for instance, a trigger function will be able to work
successfully with a column named <literal>key</literal> even if it happens
to have different types in different tables.
</para>
<para>
Likewise, functions having polymorphic argument types have a separate
statement cache for each combination of actual argument types they have
been invoked for, so that data type differences do not cause unexpected
failures.
</para>
<para>
Statement caching can sometimes have surprising effects on the
interpretation of time-sensitive values. For example there
is a difference between what these two functions do:
<programlisting>
CREATE FUNCTION logfunc1(logtxt text) RETURNS void AS $$
BEGIN
INSERT INTO logtable VALUES (logtxt, 'now');
END;
$$ LANGUAGE plpgsql;
</programlisting>
and:
<programlisting>
CREATE FUNCTION logfunc2(logtxt text) RETURNS void AS $$
DECLARE
curtime timestamp;
BEGIN
curtime := 'now';
INSERT INTO logtable VALUES (logtxt, curtime);
END;
$$ LANGUAGE plpgsql;
</programlisting>