Home Explore Blog CI



postgresql

65th chunk of `doc/src/sgml/plpgsql.sgml`
2141786dbea7b16c987d00df621f533b7da4b1c107f98b610000000100000fad
 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 &mdash; 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 &mdash; 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>

Title: PL/pgSQL Plan Caching Details and Implications
Summary
PL/pgSQL attempts to cache execution plans for prepared statements; if caching is disabled, a fresh plan is generated with each execution, optimizing based on current parameter values. The SPI manager may create generic plans for parameter-insensitive statements or frequently executed statements. SQL commands must reference consistent tables and columns across executions. Dynamic commands using EXECUTE can bypass this restriction, though incurring parsing and plan construction overhead. Mutable record variables' field types must remain consistent across function calls. Triggers have separate statement caches per table, mitigating data type issues. Functions with polymorphic arguments also maintain separate caches for each argument type combination. Statement caching impacts time-sensitive value interpretation, illustrated by examples.