1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-20 15:22:23 +03:00

Redesign query-snapshot timing so that volatile functions in READ COMMITTED

mode see a fresh snapshot for each command in the function, rather than
using the latest interactive command's snapshot.  Also, suppress fresh
snapshots as well as CommandCounterIncrement inside STABLE and IMMUTABLE
functions, instead using the snapshot taken for the most closely nested
regular query.  (This behavior is only sane for read-only functions, so
the patch also enforces that such functions contain only SELECT commands.)
As per my proposal of 6-Sep-2004; I note that I floated essentially the
same proposal on 19-Jun-2002, but that discussion tailed off without any
action.  Since 8.0 seems like the right place to be taking possibly
nontrivial backwards compatibility hits, let's get it done now.
This commit is contained in:
Tom Lane
2004-09-13 20:10:13 +00:00
parent d69528881a
commit b2c4071299
41 changed files with 1764 additions and 834 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.23 2004/05/16 23:22:07 neilc Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpython.sgml,v 1.24 2004/09/13 20:05:18 tgl Exp $ -->
<chapter id="plpython">
<title>PL/Python - Python Procedural Language</title>
@ -175,7 +175,7 @@ def __plpython_procedure_myfunc_23456():
row number and column name. It has these additional methods:
<function>nrows</function> which returns the number of rows
returned by the query, and <function>status</function> which is the
<function>SPI_exec()</function> return value. The result object
<function>SPI_execute()</function> return value. The result object
can be modified.
</para>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.58 2004/07/11 23:23:43 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.59 2004/09/13 20:05:38 tgl Exp $
-->
<refentry id="SQL-CREATEFUNCTION">
@ -172,7 +172,7 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
These attributes inform the system whether it is safe to
replace multiple evaluations of the function with a single
evaluation, for run-time optimization. At most one choice
should be specified. If none of these appear,
may be specified. If none of these appear,
<literal>VOLATILE</literal> is the default assumption.
</para>
@ -206,6 +206,10 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
to prevent calls from being optimized away; an example is
<literal>setval()</>.
</para>
<para>
For additional details see <xref linkend="xfunc-volatility">.
</para>
</listitem>
</varlistentry>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.295 2004/09/10 18:39:54 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.296 2004/09/13 20:05:18 tgl Exp $
-->
<appendix id="release">
@ -337,6 +337,26 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.295 2004/09/10 18:39:54 tgl Exp
</para>
</listitem>
<listitem>
<para>
In <literal>READ COMMITTED</> serialization mode, volatile functions
now see the results of concurrent transactions committed up to the
beginning of each statement within the function, rather than up to the
beginning of the interactive command that called the function.
</para>
</listitem>
<listitem>
<para>
Functions declared <literal>STABLE</> or <literal>IMMUTABLE</> always
use the snapshot of the calling query, and therefore do not see the
effects of actions taken after the calling query starts, whether in
their own transaction or other transactions. Such a function must be
read-only, too, meaning that it cannot use any SQL commands other than
<command>SELECT</>.
</para>
</listitem>
<listitem>
<para>
Non-deferred AFTER triggers are now fired immediately after completion
@ -1434,6 +1454,26 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.295 2004/09/10 18:39:54 tgl Exp
<title>Server-Side Language Changes</title>
<itemizedlist>
<listitem>
<para>
In <literal>READ COMMITTED</> serialization mode, volatile functions
now see the results of concurrent transactions committed up to the
beginning of each statement within the function, rather than up to the
beginning of the interactive command that called the function.
</para>
</listitem>
<listitem>
<para>
Functions declared <literal>STABLE</> or <literal>IMMUTABLE</> always
use the snapshot of the calling query, and therefore do not see the
effects of actions taken after the calling query starts, whether in
their own transaction or other transactions. Such a function must be
read-only, too, meaning that it cannot use any SQL commands other than
<command>SELECT</>.
</para>
</listitem>
<listitem>
<para>
Non-deferred AFTER triggers are now fired immediately after completion

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.34 2004/04/01 21:28:43 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.35 2004/09/13 20:05:25 tgl Exp $
-->
<chapter id="spi">
@ -206,7 +206,7 @@ int SPI_finish(void)
<refnamediv>
<refname>SPI_push</refname>
<refpurpose>pushes SPI stack to allow recursive SPI calls</refpurpose>
<refpurpose>pushes SPI stack to allow recursive SPI usage</refpurpose>
</refnamediv>
<indexterm><primary>SPI_push</primary></indexterm>
@ -221,8 +221,24 @@ void SPI_push(void)
<title>Description</title>
<para>
<function>SPI_push</function> pushes a new environment on to the
SPI call stack, allowing recursive calls to use a new environment.
<function>SPI_push</function> should be called before executing another
procedure that might itself wish to use SPI.
After <function>SPI_push</function>, SPI is no longer in a
<quote>connected</> state, and SPI function calls will be rejected unless
a fresh <function>SPI_connect</function> is done. This ensures a clean
separation between your procedure's SPI state and that of another procedure
you call. After the other procedure returns, call
<function>SPI_pop</function> to restore access to your own SPI state.
</para>
<para>
Note that <function>SPI_execute</function> and related functions
automatically do the equivalent of <function>SPI_push</function> before
passing control back to the SQL execution engine, so it is not necessary
for you to worry about this when using those functions.
Only when you are directly calling arbitrary code that might contain
<function>SPI_connect</function> calls do you need to issue
<function>SPI_push</function> and <function>SPI_pop</function>.
</para>
</refsect1>
@ -237,7 +253,7 @@ void SPI_push(void)
<refnamediv>
<refname>SPI_pop</refname>
<refpurpose>pops SPI stack to allow recursive SPI calls</refpurpose>
<refpurpose>pops SPI stack to return from recursive SPI usage</refpurpose>
</refnamediv>
<indexterm><primary>SPI_pop</primary></indexterm>
@ -253,7 +269,7 @@ void SPI_pop(void)
<para>
<function>SPI_pop</function> pops the previous environment from the
SPI call stack. For use when returning from recursive SPI calls.
SPI call stack. See <function>SPI_push</function>.
</para>
</refsect1>
@ -261,21 +277,21 @@ void SPI_pop(void)
<!-- *********************************************** -->
<refentry id="spi-spi-exec">
<refentry id="spi-spi-execute">
<refmeta>
<refentrytitle>SPI_exec</refentrytitle>
<refentrytitle>SPI_execute</refentrytitle>
</refmeta>
<refnamediv>
<refname>SPI_exec</refname>
<refname>SPI_execute</refname>
<refpurpose>execute a command</refpurpose>
</refnamediv>
<indexterm><primary>SPI_exec</primary></indexterm>
<indexterm><primary>SPI_execute</primary></indexterm>
<refsynopsisdiv>
<synopsis>
int SPI_exec(const char * <parameter>command</parameter>, int <parameter>count</parameter>)
int SPI_execute(const char * <parameter>command</parameter>, bool <parameter>read_only</parameter>, int <parameter>count</parameter>)
</synopsis>
</refsynopsisdiv>
@ -283,27 +299,65 @@ int SPI_exec(const char * <parameter>command</parameter>, int <parameter>count</
<title>Description</title>
<para>
<function>SPI_exec</function> executes the specified SQL command
for <parameter>count</parameter> rows.
<function>SPI_execute</function> executes the specified SQL command
for <parameter>count</parameter> rows. If <parameter>read_only</parameter>
is <literal>true</>, the command must be read-only, and execution overhead
is somewhat reduced.
</para>
<para>
This function should only be called from a connected procedure. If
<parameter>count</parameter> is zero then it executes the command
This function may only be called from a connected procedure.
</para>
<para>
If <parameter>count</parameter> is zero then the command is executed
for all rows that it applies to. If <parameter>count</parameter>
is greater than 0, then the number of rows for which the command
will be executed is restricted (much like a
<literal>LIMIT</literal> clause). For example,
<programlisting>
SPI_exec("INSERT INTO tab SELECT * FROM tab", 5);
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
</programlisting>
will allow at most 5 rows to be inserted into the table.
</para>
<para>
You may pass multiple commands in one string, and the command may
be rewritten by rules. <function>SPI_exec</function> returns the
result for the command executed last.
You may pass multiple commands in one string, and the commands may
be rewritten by rules. <function>SPI_execute</function> returns the
result for the command executed last. The <parameter>count</parameter>
limit applies to each command separately, but it is not applied to
hidden commands generated by rules.
</para>
<para>
When <parameter>read_only</parameter> is <literal>false</>,
<function>SPI_execute</function> increments the command
counter and computes a new <firstterm>snapshot</> before executing each
command in the string. The snapshot does not actually change if the
current transaction isolation level is <literal>SERIALIZABLE</>, but in
<literal>READ COMMITTED</> mode the snapshot update allows each command to
see the results of newly committed transactions from other sessions.
This is essential for consistent behavior when the commands are modifying
the database.
</para>
<para>
When <parameter>read_only</parameter> is <literal>true</>,
<function>SPI_execute</function> does not update either the snapshot
or the command counter, and it allows only plain <command>SELECT</>
commands to appear in the command string. The commands are executed
using the snapshot previously established for the surrounding query.
This execution mode is somewhat faster than the read/write mode due
to eliminating per-command overhead. It also allows genuinely
<firstterm>stable</> functions to be built: since successive executions
will all use the same snapshot, there will be no change in the results.
</para>
<para>
It is generally unwise to mix read-only and read-write commands within
a single function using SPI; that could result in very confusing behavior,
since the read-only queries would not see the results of any database
updates done by the read-write queries.
</para>
<para>
@ -311,7 +365,7 @@ SPI_exec("INSERT INTO tab SELECT * FROM tab", 5);
is returned in the global variable <varname>SPI_processed</varname>
(unless the return value of the function is
<symbol>SPI_OK_UTILITY</symbol>). If the return value of the
function is <symbol>SPI_OK_SELECT</symbol> then you may the use
function is <symbol>SPI_OK_SELECT</symbol> then you may use the
global pointer <literal>SPITupleTable *SPI_tuptable</literal> to
access the result rows.
</para>
@ -330,7 +384,7 @@ typedef struct
} SPITupleTable;
</programlisting>
<structfield>vals</> is an array of pointers to rows. (The number
of valid entries is given by <varname>SPI_processed</varname>).
of valid entries is given by <varname>SPI_processed</varname>.)
<structfield>tupdesc</> is a row descriptor which you may pass to
SPI functions dealing with rows. <structfield>tuptabcxt</>,
<structfield>alloced</>, and <structfield>free</> are internal
@ -358,6 +412,15 @@ typedef struct
</listitem>
</varlistentry>
<varlistentry>
<term><literal>bool <parameter>read_only</parameter></literal></term>
<listitem>
<para>
<literal>true</> for read-only execution
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>int <parameter>count</parameter></literal></term>
<listitem>
@ -504,14 +567,15 @@ typedef struct
<title>Notes</title>
<para>
The functions <function>SPI_exec</function>,
<function>SPI_execp</function>, and
<function>SPI_prepare</function> change both
The functions <function>SPI_execute</function>,
<function>SPI_exec</function>,
<function>SPI_execute_plan</function>, and
<function>SPI_execp</function> change both
<varname>SPI_processed</varname> and
<varname>SPI_tuptable</varname> (just the pointer, not the contents
of the structure). Save these two global variables into local
procedure variables if you need to access the result of
<function>SPI_exec</function> or <function>SPI_execp</function>
procedure variables if you need to access the result table of
<function>SPI_execute</function> or a related function
across later calls.
</para>
</refsect1>
@ -519,6 +583,70 @@ typedef struct
<!-- *********************************************** -->
<refentry id="spi-spi-exec">
<refmeta>
<refentrytitle>SPI_exec</refentrytitle>
</refmeta>
<refnamediv>
<refname>SPI_exec</refname>
<refpurpose>execute a read/write command</refpurpose>
</refnamediv>
<indexterm><primary>SPI_exec</primary></indexterm>
<refsynopsisdiv>
<synopsis>
int SPI_exec(const char * <parameter>command</parameter>, int <parameter>count</parameter>)
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<function>SPI_exec</function> is the same as
<function>SPI_execute</function>, with the latter's
<parameter>read_only</parameter> parameter always taken as
<literal>false</>.
</para>
</refsect1>
<refsect1>
<title>Arguments</title>
<variablelist>
<varlistentry>
<term><literal>const char * <parameter>command</parameter></literal></term>
<listitem>
<para>
string containing command to execute
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>int <parameter>count</parameter></literal></term>
<listitem>
<para>
maximum number of rows to process or return
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>
See <function>SPI_execute</function>.
</para>
</refsect1>
</refentry>
<!-- *********************************************** -->
<refentry id="spi-spi-prepare">
<refmeta>
<refentrytitle>SPI_prepare</refentrytitle>
@ -551,14 +679,14 @@ void * SPI_prepare(const char * <parameter>command</parameter>, int <parameter>n
may be advantageous to perform the planning only once.
<function>SPI_prepare</function> converts a command string into an
execution plan that can be executed repeatedly using
<function>SPI_execp</function>.
<function>SPI_execute_plan</function>.
</para>
<para>
A prepared command can be generalized by writing parameters
(<literal>$1</>, <literal>$2</>, etc.) in place of what would be
constants in a normal command. The actual values of the parameters
are then specified when <function>SPI_execp</function> is called.
are then specified when <function>SPI_execute_plan</function> is called.
This allows the prepared command to be used over a wider range of
situations than would be possible without parameters.
</para>
@ -610,10 +738,10 @@ void * SPI_prepare(const char * <parameter>command</parameter>, int <parameter>n
<title>Return Value</title>
<para>
<function>SPI_prepare</function> returns non-null pointer to an
execution plan. On error, <symbol>NULL</symbol> will be returned.
In both cases, <varname>SPI_result</varname> will be set analogous
to the value returned by <function>SPI_exec</function>, except that
<function>SPI_prepare</function> returns a non-null pointer to an
execution plan. On error, <symbol>NULL</symbol> will be returned,
and <varname>SPI_result</varname> will be set to one of the same
error codes used by <function>SPI_execute</function>, except that
it is set to <symbol>SPI_ERROR_ARGUMENT</symbol> if
<parameter>command</parameter> is <symbol>NULL</symbol>, or if
<parameter>nargs</> is less than 0, or if <parameter>nargs</> is
@ -642,7 +770,7 @@ void * SPI_prepare(const char * <parameter>command</parameter>, int <parameter>n
<refnamediv>
<refname>SPI_getargcount</refname>
<refpurpose>returns the number of arguments needed when executing a plan
<refpurpose>returns the number of arguments needed by a plan
prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
@ -659,7 +787,7 @@ int SPI_getargcount(void * <parameter>plan</parameter>)
<para>
<function>SPI_getargcount</function> returns the number of arguments needed
when executing a plan prepared by <function>SPI_prepare</function>.
to execute a plan prepared by <function>SPI_prepare</function>.
</para>
</refsect1>
@ -681,7 +809,7 @@ int SPI_getargcount(void * <parameter>plan</parameter>)
<refsect1>
<title>Return Value</title>
<para>
The expected argument count for the <parameter>plan</parameter> or
The expected argument count for the <parameter>plan</parameter>, or
<symbol>SPI_ERROR_ARGUMENT</symbol> if the <parameter>plan
</parameter> is <symbol>NULL</symbol>
</para>
@ -697,8 +825,8 @@ int SPI_getargcount(void * <parameter>plan</parameter>)
<refnamediv>
<refname>SPI_getargtypeid</refname>
<refpurpose>returns the expected typeid for the specified argument when
executing a plan prepared by <function>SPI_prepare</function></refpurpose>
<refpurpose>returns the expected typeid for the specified argument of
a plan prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_getargtypeid</primary></indexterm>
@ -714,7 +842,7 @@ Oid SPI_getargtypeid(void * <parameter>plan</parameter>, int <parameter>argIndex
<para>
<function>SPI_getargtypeid</function> returns the Oid representing the type
id for argument at <parameter>argIndex</parameter> in a plan prepared by
id for the <parameter>argIndex</parameter>'th argument of a plan prepared by
<function>SPI_prepare</function>. First argument is at index zero.
</para>
</refsect1>
@ -746,11 +874,11 @@ Oid SPI_getargtypeid(void * <parameter>plan</parameter>, int <parameter>argIndex
<refsect1>
<title>Return Value</title>
<para>
The type id of the argument at the given index or <symbol>
SPI_ERROR_ARGUMENT</symbol> if the <parameter>plan</parameter> is
The type id of the argument at the given index, or
<symbol>SPI_ERROR_ARGUMENT</symbol> if the <parameter>plan</parameter> is
<symbol>NULL</symbol> or <parameter>argIndex</parameter> is less than 0 or
not less than the number of arguments declared for the <parameter>plan
</parameter>
not less than the number of arguments declared for the
<parameter>plan</parameter>
</para>
</refsect1>
</refentry>
@ -765,8 +893,8 @@ Oid SPI_getargtypeid(void * <parameter>plan</parameter>, int <parameter>argIndex
<refnamediv>
<refname>SPI_is_cursor_plan</refname>
<refpurpose>returns <symbol>true</symbol> if a plan
prepared by <function>SPI_prepare</function> can be passed
as an argument to <function>SPI_cursor_open</function></refpurpose>
prepared by <function>SPI_prepare</function> can be used with
<function>SPI_cursor_open</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_is_cursor_plan</primary></indexterm>
@ -784,7 +912,7 @@ bool SPI_is_cursor_plan(void * <parameter>plan</parameter>)
<function>SPI_is_cursor_plan</function> returns <symbol>true</symbol>
if a plan prepared by <function>SPI_prepare</function> can be passed
as an argument to <function>SPI_cursor_open</function> and <symbol>
false</symbol> if that is not the case. The criteria is that the
false</symbol> if that is not the case. The criteria are that the
<parameter>plan</parameter> represents one single command and that this
command is a <command>SELECT</command> without an <command>INTO</command>
clause.
@ -819,21 +947,22 @@ bool SPI_is_cursor_plan(void * <parameter>plan</parameter>)
<!-- *********************************************** -->
<refentry id="spi-spi-execp">
<refentry id="spi-spi-execute-plan">
<refmeta>
<refentrytitle>SPI_execp</refentrytitle>
<refentrytitle>SPI_execute_plan</refentrytitle>
</refmeta>
<refnamediv>
<refname>SPI_execp</refname>
<refname>SPI_execute_plan</refname>
<refpurpose>executes a plan prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<indexterm><primary>SPI_execp</primary></indexterm>
<indexterm><primary>SPI_execute_plan</primary></indexterm>
<refsynopsisdiv>
<synopsis>
int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>, int <parameter>count</parameter>)
int SPI_execute_plan(void * <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>,
bool <parameter>read_only</parameter>, int <parameter>count</parameter>)
</synopsis>
</refsynopsisdiv>
@ -841,9 +970,10 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<title>Description</title>
<para>
<function>SPI_execp</function> executes a plan prepared by
<function>SPI_prepare</function>. <parameter>tcount</parameter>
has the same interpretation as in <function>SPI_exec</function>.
<function>SPI_execute_plan</function> executes a plan prepared by
<function>SPI_prepare</function>. <parameter>read_only</parameter> and
<parameter>count</parameter> have the same interpretation as in
<function>SPI_execute</function>.
</para>
</refsect1>
@ -861,10 +991,11 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
</varlistentry>
<varlistentry>
<term><literal>Datum *<parameter>values</parameter></literal></term>
<term><literal>Datum * <parameter>values</parameter></literal></term>
<listitem>
<para>
actual parameter values
An array of actual parameter values. Must have same length as the
plan's number of arguments.
</para>
</listitem>
</varlistentry>
@ -873,7 +1004,8 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<term><literal>const char * <parameter>nulls</parameter></literal></term>
<listitem>
<para>
An array describing which parameters are null.
An array describing which parameters are null. Must have same length as
the plan's number of arguments.
<literal>n</literal> indicates a null value (entry in
<parameter>values</> will be ignored); a space indicates a
nonnull value (entry in <parameter>values</> is valid).
@ -881,17 +1013,26 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<para>
If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
<function>SPI_execp</function> assumes that no parameters are
<function>SPI_execute_plan</function> assumes that no parameters are
null.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>bool <parameter>read_only</parameter></literal></term>
<listitem>
<para>
<literal>true</> for read-only execution
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>int <parameter>count</parameter></literal></term>
<listitem>
<para>
number of row for which plan is to be executed
maximum number of rows to process or return
</para>
</listitem>
</varlistentry>
@ -902,8 +1043,8 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<title>Return Value</title>
<para>
The return value is the same as for <function>SPI_exec</function>
or one of the following:
The return value is the same as for <function>SPI_execute</function>,
with the following additional possible error (negative) results:
<variablelist>
<varlistentry>
@ -931,7 +1072,7 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<para>
<varname>SPI_processed</varname> and
<varname>SPI_tuptable</varname> are set as in
<function>SPI_exec</function> if successful.
<function>SPI_execute</function> if successful.
</para>
</refsect1>
@ -941,7 +1082,106 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<para>
If one of the objects (a table, function, etc.) referenced by the
prepared plan is dropped during the session then the result of
<function>SPI_execp</function> for this plan will be unpredictable.
<function>SPI_execute_plan</function> for this plan will be unpredictable.
</para>
</refsect1>
</refentry>
<!-- *********************************************** -->
<refentry id="spi-spi-execp">
<refmeta>
<refentrytitle>SPI_execp</refentrytitle>
</refmeta>
<refnamediv>
<refname>SPI_execp</refname>
<refpurpose>executes a plan in read/write mode</refpurpose>
</refnamediv>
<indexterm><primary>SPI_execp</primary></indexterm>
<refsynopsisdiv>
<synopsis>
int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>, int <parameter>count</parameter>)
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<function>SPI_execp</function> is the same as
<function>SPI_execute_plan</function>, with the latter's
<parameter>read_only</parameter> parameter always taken as
<literal>false</>.
</para>
</refsect1>
<refsect1>
<title>Arguments</title>
<variablelist>
<varlistentry>
<term><literal>void * <parameter>plan</parameter></literal></term>
<listitem>
<para>
execution plan (returned by <function>SPI_prepare</function>)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Datum * <parameter>values</parameter></literal></term>
<listitem>
<para>
An array of actual parameter values. Must have same length as the
plan's number of arguments.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>const char * <parameter>nulls</parameter></literal></term>
<listitem>
<para>
An array describing which parameters are null. Must have same length as
the plan's number of arguments.
<literal>n</literal> indicates a null value (entry in
<parameter>values</> will be ignored); a space indicates a
nonnull value (entry in <parameter>values</> is valid).
</para>
<para>
If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
<function>SPI_execp</function> assumes that no parameters are
null.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>int <parameter>count</parameter></literal></term>
<listitem>
<para>
maximum number of rows to process or return
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>
See <function>SPI_execute_plan</function>.
</para>
<para>
<varname>SPI_processed</varname> and
<varname>SPI_tuptable</varname> are set as in
<function>SPI_execute</function> if successful.
</para>
</refsect1>
</refentry>
@ -962,7 +1202,9 @@ int SPI_execp(void * <parameter>plan</parameter>, Datum * <parameter>values</par
<refsynopsisdiv>
<synopsis>
Portal SPI_cursor_open(const char * <parameter>name</parameter>, void * <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>)
Portal SPI_cursor_open(const char * <parameter>name</parameter>, void * <parameter>plan</parameter>,
Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>,
bool <parameter>read_only</parameter>)
</synopsis>
</refsynopsisdiv>
@ -972,7 +1214,9 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, void * <paramet
<para>
<function>SPI_cursor_open</function> sets up a cursor (internally,
a portal) that will execute a plan prepared by
<function>SPI_prepare</function>.
<function>SPI_prepare</function>. The parameters have the same
meanings as the corresponding parameters to
<function>SPI_execute_plan</function>.
</para>
<para>
@ -1013,22 +1257,36 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, void * <paramet
<term><literal>Datum * <parameter>values</parameter></literal></term>
<listitem>
<para>
actual parameter values
An array of actual parameter values. Must have same length as the
plan's number of arguments.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>const char *<parameter>nulls</parameter></literal></term>
<term><literal>const char * <parameter>nulls</parameter></literal></term>
<listitem>
<para>
An array describing which parameters are null values.
An array describing which parameters are null. Must have same length as
the plan's number of arguments.
<literal>n</literal> indicates a null value (entry in
<parameter>values</> will be ignored); a space indicates a
nonnull value (entry in <parameter>values</> is valid). If
<parameter>nulls</parameter> is <symbol>NULL</> then
<function>SPI_cursor_open</function> assumes that no parameters
are null.
nonnull value (entry in <parameter>values</> is valid).
</para>
<para>
If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
<function>SPI_cursor_open</function> assumes that no parameters are
null.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>bool <parameter>read_only</parameter></literal></term>
<listitem>
<para>
<literal>true</> for read-only execution
</para>
</listitem>
</varlistentry>
@ -1168,7 +1426,7 @@ void SPI_cursor_fetch(Portal <parameter>portal</parameter>, bool <parameter>forw
<para>
<varname>SPI_processed</varname> and
<varname>SPI_tuptable</varname> are set as in
<function>SPI_exec</function> if successful.
<function>SPI_execute</function> if successful.
</para>
</refsect1>
</refentry>
@ -1320,7 +1578,7 @@ void * SPI_saveplan(void * <parameter>plan</parameter>)
your procedure in the current session. You may save the pointer
returned in a local variable. Always check if this pointer is
<symbol>NULL</symbol> or not either when preparing a plan or using
an already prepared plan in <function>SPI_execp</function>.
an already prepared plan in <function>SPI_execute_plan</function>.
</para>
</refsect1>
@ -1374,7 +1632,7 @@ void * SPI_saveplan(void * <parameter>plan</parameter>)
<para>
If one of the objects (a table, function, etc.) referenced by the
prepared plan is dropped during the session then the results of
<function>SPI_execp</function> for this plan will be unpredictable.
<function>SPI_execute_plan</function> for this plan will be unpredictable.
</para>
</refsect1>
</refentry>
@ -1386,7 +1644,7 @@ void * SPI_saveplan(void * <parameter>plan</parameter>)
<para>
The functions described here provide an interface for extracting
information from result sets returned by <function>SPI_exec</> and
information from result sets returned by <function>SPI_execute</> and
other SPI functions.
</para>
@ -2360,7 +2618,8 @@ HeapTuple SPI_modifytuple(Relation <parameter>rel</parameter>, HeapTuple <parame
<term><literal>const char * <parameter>Nulls</parameter></literal></term>
<listitem>
<para>
which new values are null, if any (see <function>SPI_execp</function> for the format)
which new values are null, if any (see
<function>SPI_execute_plan</function> for the format)
</para>
</listitem>
</varlistentry>
@ -2466,7 +2725,8 @@ void SPI_freetuple(HeapTuple <parameter>row</parameter>)
<refnamediv>
<refname>SPI_freetuptable</refname>
<refpurpose>free a row set created by <function>SPI_exec</> or a similar function</refpurpose>
<refpurpose>free a row set created by <function>SPI_execute</> or a similar
function</refpurpose>
</refnamediv>
<indexterm><primary>SPI_freetuptable</primary></indexterm>
@ -2483,7 +2743,7 @@ void SPI_freetuptable(SPITupleTable * <parameter>tuptable</parameter>)
<para>
<function>SPI_freetuptable</function> frees a row set created by a
prior SPI command execution function, such as
<function>SPI_exec</>. Therefore, this function is usually called
<function>SPI_execute</>. Therefore, this function is usually called
with the global variable <varname>SPI_tupletable</varname> as
argument.
</para>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.86 2004/08/24 00:06:50 neilc Exp $
$PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.87 2004/09/13 20:05:25 tgl Exp $
-->
<sect1 id="xfunc">
@ -2404,14 +2404,6 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray
number of arguments, up to a finite maximum number.
</para>
<para>
A function may also have the same name as an attribute. (Recall
that <literal>attribute(table)</literal> is equivalent to
<literal>table.attribute</literal>.) In the case that there is an
ambiguity between a function on a complex type and an attribute of
the complex type, the attribute will always be used.
</para>
<para>
When creating a family of overloaded functions, one should be
careful not to create ambiguities. For instance, given the
@ -2427,6 +2419,18 @@ CREATE FUNCTION test(smallint, double precision) RETURNS ...
relies on this behavior.
</para>
<para>
A function that takes a single argument of a composite type should
generally not have the same name as any attribute (field) of that type.
Recall that <literal>attribute(table)</literal> is considered equivalent
to <literal>table.attribute</literal>. In the case that there is an
ambiguity between a function on a composite type and an attribute of
the composite type, the attribute will always be used. It is possible
to override that choice by schema-qualifying the function name
(that is, <literal>schema.func(table)</literal>) but it's better to
avoid the problem by not choosing conflicting names.
</para>
<para>
When overloading C-language functions, there is an additional
constraint: The C name of each function in the family of
@ -2437,7 +2441,7 @@ CREATE FUNCTION test(smallint, double precision) RETURNS ...
(usually the internal one). The alternative form of the
<literal>AS</> clause for the SQL <command>CREATE
FUNCTION</command> command decouples the SQL function name from
the function name in the C source code. E.g.,
the function name in the C source code. For instance,
<programlisting>
CREATE FUNCTION test(int) RETURNS int
AS '<replaceable>filename</>', 'test_1arg'
@ -2450,6 +2454,128 @@ CREATE FUNCTION test(int, int) RETURNS int
</para>
</sect1>
<sect1 id="xfunc-volatility">
<title>Function Volatility Categories</title>
<indexterm zone="xfunc-volatility">
<primary>volatility</primary>
<secondary>functions</secondary>
</indexterm>
<para>
Every function has a <firstterm>volatility</> classification, with
the possibilities being <literal>VOLATILE</>, <literal>STABLE</>, or
<literal>IMMUTABLE</>. <literal>VOLATILE</> is the default if the
<command>CREATE FUNCTION</command> command does not specify a category.
The volatility category is a promise to the optimizer about the behavior
of the function:
<itemizedlist>
<listitem>
<para>
A <literal>VOLATILE</> function can do anything, including modifying
the database. It can return different results on successive calls with
the same arguments. The optimizer makes no assumptions about the
behavior of such functions. A query using a volatile function will
re-evaluate the function at every row where its value is needed.
</para>
</listitem>
<listitem>
<para>
A <literal>STABLE</> function cannot modify the database and is
guaranteed to return the same results given the same arguments
for all calls within a single surrounding query. This category
allows the optimizer to optimize away multiple calls of the function
within a single query. In particular, it is safe to use an expression
containing such a function in an indexscan condition. (Since an
indexscan will evaluate the comparison value only once, not once at
each row, it is not valid to use a <literal>VOLATILE</> function in
an indexscan condition.)
</para>
</listitem>
<listitem>
<para>
An <literal>IMMUTABLE</> function cannot modify the database and is
guaranteed to return the same results given the same arguments forever.
This category allows the optimizer to pre-evaluate the function when
a query calls it with constant arguments. For example, a query like
<literal>SELECT ... WHERE x = 2 + 2</> can be simplified on sight to
<literal>SELECT ... WHERE x = 4</>, because the function underlying
the integer addition operator is marked <literal>IMMUTABLE</>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
For best optimization results, you should label your functions with the
strictest volatility category that is valid for them.
</para>
<para>
Any function with side-effects <emphasis>must</> be labeled
<literal>VOLATILE</>, so that calls to it cannot be optimized away.
Even a function with no side-effects needs to be labeled
<literal>VOLATILE</> if its value can change within a single query;
some examples are <literal>random()</>, <literal>currval()</>,
<literal>timeofday()</>.
</para>
<para>
There is relatively little difference between <literal>STABLE</> and
<literal>IMMUTABLE</> categories when considering simple interactive
queries that are planned and immediately executed: it doesn't matter
a lot whether a function is executed once during planning or once during
query execution startup. But there is a big difference if the plan is
saved and reused later. Labeling a function <literal>IMMUTABLE</> when
it really isn't may allow it to be prematurely folded to a constant during
planning, resulting in a stale value being re-used during subsequent uses
of the plan. This is a hazard when using prepared statements or when
using function languages that cache plans (such as
<application>PL/pgSQL</>).
</para>
<para>
Because of the snapshotting behavior of MVCC (see <xref linkend="mvcc">)
a function containing only <command>SELECT</> commands can safely be
marked <literal>STABLE</>, even if it selects from tables that might be
undergoing modifications by concurrent queries.
<productname>PostgreSQL</productname> will execute a <literal>STABLE</>
function using the snapshot established for the calling query, and so it
will see a fixed view of the database throughout that query.
Also note
that the <function>current_timestamp</> family of functions qualify
as stable, since their values do not change within a transaction.
</para>
<para>
The same snapshotting behavior is used for <command>SELECT</> commands
within <literal>IMMUTABLE</> functions. It is generally unwise to select
from database tables within an <literal>IMMUTABLE</> function at all,
since the immutability will be broken if the table contents ever change.
However, <productname>PostgreSQL</productname> does not enforce that you
do not do that.
</para>
<para>
A common error is to label a function <literal>IMMUTABLE</> when its
results depend on a configuration parameter. For example, a function
that manipulates timestamps might well have results that depend on the
<xref linkend="guc-timezone"> setting. For safety, such functions should
be labeled <literal>STABLE</> instead.
</para>
<note>
<para>
Before <productname>PostgreSQL</productname> release 8.0, the requirement
that <literal>STABLE</> and <literal>IMMUTABLE</> functions cannot modify
the database was not enforced by the system. Release 8.0 enforces it
by requiring SQL functions and procedural language functions of these
categories to contain no SQL commands other than <command>SELECT</>.
</para>
</note>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode:sgml