mirror of
https://github.com/postgres/postgres.git
synced 2025-11-06 07:49:08 +03:00
In the initial implementation of plan caching, we saved the active search_path when a plan was first cached, then reinstalled that path anytime we needed to reparse or replan. The idea of that was to try to reselect the same referenced objects, in somewhat the same way that views continue to refer to the same objects in the face of schema or name changes. Of course, that analogy doesn't bear close inspection, since holding the search_path fixed doesn't cope with object drops or renames. Moreover sticking with the old path seems to create more surprises than it avoids. So instead of doing that, consider that the cached plan depends on search_path, and force reparse/replan if the active search_path is different than it was when we last saved the plan. This gets us fairly close to having "transparency" of plan caching, in the sense that the cached statement acts the same as if you'd just resubmitted the original query text for another execution. There are still some corner cases where this fails though: a new object added in the search path schema(s) might capture a reference in the query text, but we'd not realize that and force a reparse. We might try to fix that in the future, but for the moment it looks too expensive and complicated.
4214 lines
112 KiB
Plaintext
4214 lines
112 KiB
Plaintext
<!-- doc/src/sgml/spi.sgml -->
|
|
|
|
<chapter id="spi">
|
|
<title>Server Programming Interface</title>
|
|
|
|
<indexterm zone="spi">
|
|
<primary>SPI</primary>
|
|
</indexterm>
|
|
|
|
<para>
|
|
The <firstterm>Server Programming Interface</firstterm>
|
|
(<acronym>SPI</acronym>) gives writers of user-defined
|
|
<acronym>C</acronym> functions the ability to run
|
|
<acronym>SQL</acronym> commands inside their functions.
|
|
<acronym>SPI</acronym> is a set of
|
|
interface functions to simplify access to the parser, planner,
|
|
and executor. <acronym>SPI</acronym> also does some
|
|
memory management.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The available procedural languages provide various means to
|
|
execute SQL commands from procedures. Most of these facilities are
|
|
based on SPI, so this documentation might be of use for users
|
|
of those languages as well.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
To avoid misunderstanding we'll use the term <quote>function</quote>
|
|
when we speak of <acronym>SPI</acronym> interface functions and
|
|
<quote>procedure</quote> for a user-defined C-function that is
|
|
using <acronym>SPI</acronym>.
|
|
</para>
|
|
|
|
<para>
|
|
Note that if a command invoked via SPI fails, then control will not be
|
|
returned to your procedure. Rather, the
|
|
transaction or subtransaction in which your procedure executes will be
|
|
rolled back. (This might seem surprising given that the SPI functions mostly
|
|
have documented error-return conventions. Those conventions only apply
|
|
for errors detected within the SPI functions themselves, however.)
|
|
It is possible to recover control after an error by establishing your own
|
|
subtransaction surrounding SPI calls that might fail. This is not currently
|
|
documented because the mechanisms required are still in flux.
|
|
</para>
|
|
|
|
<para>
|
|
<acronym>SPI</acronym> functions return a nonnegative result on
|
|
success (either via a returned integer value or in the global
|
|
variable <varname>SPI_result</varname>, as described below). On
|
|
error, a negative result or <symbol>NULL</symbol> will be returned.
|
|
</para>
|
|
|
|
<para>
|
|
Source code files that use SPI must include the header file
|
|
<filename>executor/spi.h</filename>.
|
|
</para>
|
|
|
|
|
|
<sect1 id="spi-interface">
|
|
<title>Interface Functions</title>
|
|
|
|
<refentry id="spi-spi-connect">
|
|
<refmeta>
|
|
<refentrytitle>SPI_connect</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_connect</refname>
|
|
<refpurpose>connect a procedure to the SPI manager</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_connect</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_connect(void)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_connect</function> opens a connection from a
|
|
procedure invocation to the SPI manager. You must call this
|
|
function if you want to execute commands through SPI. Some utility
|
|
SPI functions can be called from unconnected procedures.
|
|
</para>
|
|
|
|
<para>
|
|
If your procedure is already connected,
|
|
<function>SPI_connect</function> will return the error code
|
|
<returnvalue>SPI_ERROR_CONNECT</returnvalue>. This could happen if
|
|
a procedure that has called <function>SPI_connect</function>
|
|
directly calls another procedure that calls
|
|
<function>SPI_connect</function>. While recursive calls to the
|
|
<acronym>SPI</acronym> manager are permitted when an SQL command
|
|
called through SPI invokes another function that uses
|
|
<acronym>SPI</acronym>, directly nested calls to
|
|
<function>SPI_connect</function> and
|
|
<function>SPI_finish</function> are forbidden.
|
|
(But see <function>SPI_push</function> and <function>SPI_pop</function>.)
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_CONNECT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
on success
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_CONNECT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
on error
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-finish">
|
|
<refmeta>
|
|
<refentrytitle>SPI_finish</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_finish</refname>
|
|
<refpurpose>disconnect a procedure from the SPI manager</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_finish</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_finish(void)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_finish</function> closes an existing connection to
|
|
the SPI manager. You must call this function after completing the
|
|
SPI operations needed during your procedure's current invocation.
|
|
You do not need to worry about making this happen, however, if you
|
|
abort the transaction via <literal>elog(ERROR)</literal>. In that
|
|
case SPI will clean itself up automatically.
|
|
</para>
|
|
|
|
<para>
|
|
If <function>SPI_finish</function> is called without having a valid
|
|
connection, it will return <symbol>SPI_ERROR_UNCONNECTED</symbol>.
|
|
There is no fundamental problem with this; it means that the SPI
|
|
manager has nothing to do.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_FINISH</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if properly disconnected
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_UNCONNECTED</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if called from an unconnected procedure
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-push">
|
|
<refmeta>
|
|
<refentrytitle>SPI_push</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_push</refname>
|
|
<refpurpose>push SPI stack to allow recursive SPI usage</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_push</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_push(void)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<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>
|
|
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-pop">
|
|
<refmeta>
|
|
<refentrytitle>SPI_pop</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_pop</refname>
|
|
<refpurpose>pop SPI stack to return from recursive SPI usage</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_pop</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_pop(void)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_pop</function> pops the previous environment from the
|
|
SPI call stack. See <function>SPI_push</function>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-execute">
|
|
<refmeta>
|
|
<refentrytitle>SPI_execute</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_execute</refname>
|
|
<refpurpose>execute a command</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_execute</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_execute(const char * <parameter>command</parameter>, bool <parameter>read_only</parameter>, long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<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 can 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 zero, then no more than <parameter>count</parameter> rows
|
|
will be retrieved; execution stops when the count is reached, much like
|
|
adding a <literal>LIMIT</literal> clause to the query. For example,
|
|
<programlisting>
|
|
SPI_execute("SELECT * FROM foo", true, 5);
|
|
</programlisting>
|
|
will retrieve at most 5 rows from the table. Note that such a limit
|
|
is only effective when the command actually returns rows. For example,
|
|
<programlisting>
|
|
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
|
|
</programlisting>
|
|
inserts all rows from <structname>bar</>, ignoring the
|
|
<parameter>count</parameter> parameter. However, with
|
|
<programlisting>
|
|
SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5);
|
|
</programlisting>
|
|
at most 5 rows would be inserted, since execution would stop after the
|
|
fifth <literal>RETURNING</> result row is retrieved.
|
|
</para>
|
|
|
|
<para>
|
|
You can pass multiple commands in one string;
|
|
<function>SPI_execute</function> returns the
|
|
result for the command executed last. The <parameter>count</parameter>
|
|
limit applies to each command separately (even though only the last
|
|
result will actually be returned). The limit is not applied to any
|
|
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</> or <literal>REPEATABLE READ</>, 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>
|
|
The actual number of rows for which the (last) command was executed
|
|
is returned in the global variable <varname>SPI_processed</varname>.
|
|
If the return value of the function is <symbol>SPI_OK_SELECT</symbol>,
|
|
<symbol>SPI_OK_INSERT_RETURNING</symbol>,
|
|
<symbol>SPI_OK_DELETE_RETURNING</symbol>, or
|
|
<symbol>SPI_OK_UPDATE_RETURNING</symbol>,
|
|
then you can use the
|
|
global pointer <literal>SPITupleTable *SPI_tuptable</literal> to
|
|
access the result rows. Some utility commands (such as
|
|
<command>EXPLAIN</>) also return row sets, and <literal>SPI_tuptable</>
|
|
will contain the result in these cases too. Some utility commands
|
|
(<command>COPY</>, <command>CREATE TABLE AS</>) don't return a row set, so
|
|
<literal>SPI_tuptable</> is NULL, but they still return the number of
|
|
rows processed in <varname>SPI_processed</>.
|
|
</para>
|
|
|
|
<para>
|
|
The structure <structname>SPITupleTable</structname> is defined
|
|
thus:
|
|
<programlisting>
|
|
typedef struct
|
|
{
|
|
MemoryContext tuptabcxt; /* memory context of result table */
|
|
uint32 alloced; /* number of alloced vals */
|
|
uint32 free; /* number of free vals */
|
|
TupleDesc tupdesc; /* row descriptor */
|
|
HeapTuple *vals; /* rows */
|
|
} SPITupleTable;
|
|
</programlisting>
|
|
<structfield>vals</> is an array of pointers to rows. (The number
|
|
of valid entries is given by <varname>SPI_processed</varname>.)
|
|
<structfield>tupdesc</> is a row descriptor which you can pass to
|
|
SPI functions dealing with rows. <structfield>tuptabcxt</>,
|
|
<structfield>alloced</>, and <structfield>free</> are internal
|
|
fields not intended for use by SPI callers.
|
|
</para>
|
|
|
|
<para>
|
|
<function>SPI_finish</function> frees all
|
|
<structname>SPITupleTable</>s allocated during the current
|
|
procedure. You can free a particular result table earlier, if you
|
|
are done with it, by calling <function>SPI_freetuptable</function>.
|
|
</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>bool <parameter>read_only</parameter></literal></term>
|
|
<listitem>
|
|
<para><literal>true</> for read-only execution</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to return,
|
|
or <literal>0</> for no limit
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
If the execution of the command was successful then one of the
|
|
following (nonnegative) values will be returned:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_SELECT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if a <command>SELECT</command> (but not <command>SELECT
|
|
INTO</>) was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_SELINTO</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if a <command>SELECT INTO</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_INSERT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if an <command>INSERT</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_DELETE</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if a <command>DELETE</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_UPDATE</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if an <command>UPDATE</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_INSERT_RETURNING</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if an <command>INSERT RETURNING</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_DELETE_RETURNING</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if a <command>DELETE RETURNING</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_UPDATE_RETURNING</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if an <command>UPDATE RETURNING</command> was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_UTILITY</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if a utility command (e.g., <command>CREATE TABLE</command>)
|
|
was executed
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_OK_REWRITTEN</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if the command was rewritten into another kind of command (e.g.,
|
|
<command>UPDATE</command> became an <command>INSERT</command>) by a <link linkend="rules">rule</link>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<para>
|
|
On error, one of the following negative values is returned:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_ARGUMENT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <parameter>command</parameter> is <symbol>NULL</symbol> or
|
|
<parameter>count</parameter> is less than 0
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_COPY</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <command>COPY TO stdout</> or <command>COPY FROM stdin</>
|
|
was attempted
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_TRANSACTION</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if a transaction manipulation command was attempted
|
|
(<command>BEGIN</>,
|
|
<command>COMMIT</>,
|
|
<command>ROLLBACK</>,
|
|
<command>SAVEPOINT</>,
|
|
<command>PREPARE TRANSACTION</>,
|
|
<command>COMMIT PREPARED</>,
|
|
<command>ROLLBACK PREPARED</>,
|
|
or any variant thereof)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_OPUNKNOWN</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if the command type is unknown (shouldn't happen)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_UNCONNECTED</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if called from an unconnected procedure
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
All SPI query-execution functions set 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 table of
|
|
<function>SPI_execute</function> or another query-execution function
|
|
across later calls.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-exec">
|
|
<refmeta>
|
|
<refentrytitle>SPI_exec</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</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>, long <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>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to return,
|
|
or <literal>0</> for no limit
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
See <function>SPI_execute</function>.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-execute-with-args">
|
|
<refmeta>
|
|
<refentrytitle>SPI_execute_with_args</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_execute_with_args</refname>
|
|
<refpurpose>execute a command with out-of-line parameters</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_execute_with_args</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_execute_with_args(const char *<parameter>command</parameter>,
|
|
int <parameter>nargs</parameter>, Oid *<parameter>argtypes</parameter>,
|
|
Datum *<parameter>values</parameter>, const char *<parameter>nulls</parameter>,
|
|
bool <parameter>read_only</parameter>, long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_execute_with_args</function> executes a command that might
|
|
include references to externally supplied parameters. The command text
|
|
refers to a parameter as <literal>$<replaceable>n</></literal>, and
|
|
the call specifies data types and values for each such symbol.
|
|
<parameter>read_only</parameter> and <parameter>count</parameter> have
|
|
the same interpretation as in <function>SPI_execute</function>.
|
|
</para>
|
|
|
|
<para>
|
|
The main advantage of this routine compared to
|
|
<function>SPI_execute</function> is that data values can be inserted
|
|
into the command without tedious quoting/escaping, and thus with much
|
|
less risk of SQL-injection attacks.
|
|
</para>
|
|
|
|
<para>
|
|
Similar results can be achieved with <function>SPI_prepare</> followed by
|
|
<function>SPI_execute_plan</function>; however, when using this function
|
|
the query plan is always customized to the specific parameter values
|
|
provided.
|
|
For one-time query execution, this function should be preferred.
|
|
If the same command is to be executed with many different parameters,
|
|
either method might be faster, depending on the cost of re-planning
|
|
versus the benefit of custom plans.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>command</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
command string
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>nargs</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of input parameters (<literal>$1</>, <literal>$2</>, etc.)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Oid * <parameter>argtypes</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
an array containing the <acronym>OID</acronym>s of
|
|
the data types of the parameters
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Datum * <parameter>values</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
an array of actual parameter values
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>nulls</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
an array describing which parameters are null
|
|
</para>
|
|
|
|
<para>
|
|
If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
|
|
<function>SPI_execute_with_args</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>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to return,
|
|
or <literal>0</> for no limit
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The return value is the same as for <function>SPI_execute</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>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-prepare">
|
|
<refmeta>
|
|
<refentrytitle>SPI_prepare</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_prepare</refname>
|
|
<refpurpose>prepare a statement, without executing it yet</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_prepare</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>, Oid * <parameter>argtypes</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_prepare</function> creates and returns a prepared
|
|
statement for the specified command, but doesn't execute the command.
|
|
The prepared statement can later be executed repeatedly using
|
|
<function>SPI_execute_plan</function>.
|
|
</para>
|
|
|
|
<para>
|
|
When the same or a similar command is to be executed repeatedly, it
|
|
is generally advantageous to perform parse analysis only once, and
|
|
might furthermore be advantageous to re-use an execution plan for the
|
|
command.
|
|
<function>SPI_prepare</function> converts a command string into a
|
|
prepared statement that encapsulates the results of parse analysis.
|
|
The prepared statement also provides a place for caching an execution plan
|
|
if it is found that generating a custom plan for each execution is not
|
|
helpful.
|
|
</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_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>
|
|
|
|
<para>
|
|
The statement returned by <function>SPI_prepare</function> can be used
|
|
only in the current invocation of the procedure, since
|
|
<function>SPI_finish</function> frees memory allocated for such a
|
|
statement. But the statement can be saved for longer using the functions
|
|
<function>SPI_keepplan</function> or <function>SPI_saveplan</function>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>command</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
command string
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>nargs</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of input parameters (<literal>$1</>, <literal>$2</>, etc.)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Oid * <parameter>argtypes</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
pointer to an array containing the <acronym>OID</acronym>s of
|
|
the data types of the parameters
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<function>SPI_prepare</function> returns a non-null pointer to an
|
|
<type>SPIPlan</>, which is an opaque struct representing a prepared
|
|
statement. 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
|
|
greater than 0 and <parameter>argtypes</> is <symbol>NULL</symbol>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
If no parameters are defined, a generic plan will be created at the
|
|
first use of <function>SPI_execute_plan</function>, and used for all
|
|
subsequent executions as well. If there are parameters, the first few uses
|
|
of <function>SPI_execute_plan</function> will generate custom plans
|
|
that are specific to the supplied parameter values. After enough uses
|
|
of the same prepared statement, <function>SPI_execute_plan</function> will
|
|
build a generic plan, and if that is not too much more expensive than the
|
|
custom plans, it will start using the generic plan instead of re-planning
|
|
each time. If this default behavior is unsuitable, you can alter it by
|
|
passing the <literal>CURSOR_OPT_GENERIC_PLAN</> or
|
|
<literal>CURSOR_OPT_CUSTOM_PLAN</> flag to
|
|
<function>SPI_prepare_cursor</function>, to force use of generic or custom
|
|
plans respectively.
|
|
</para>
|
|
|
|
<para>
|
|
Although the main point of a prepared statement is to avoid repeated parse
|
|
analysis and planning of the statement, <productname>PostgreSQL</> will
|
|
force re-analysis and re-planning of the statement before using it
|
|
whenever database objects used in the statement have undergone
|
|
definitional (DDL) changes since the previous use of the prepared
|
|
statement. Also, if the value of <xref linkend="guc-search-path"> changes
|
|
from one use to the next, the statement will be re-parsed using the new
|
|
<varname>search_path</>. (This latter behavior is new as of
|
|
<productname>PostgreSQL</productname> 9.3.) See <xref
|
|
linkend="sql-prepare"> for more information about the behavior of prepared
|
|
statements.
|
|
</para>
|
|
|
|
<para>
|
|
This function should only be called from a connected procedure.
|
|
</para>
|
|
|
|
<para>
|
|
<type>SPIPlanPtr</> is declared as a pointer to an opaque struct type in
|
|
<filename>spi.h</>. It is unwise to try to access its contents
|
|
directly, as that makes your code much more likely to break in
|
|
future revisions of <productname>PostgreSQL</productname>.
|
|
</para>
|
|
|
|
<para>
|
|
The name <type>SPIPlanPtr</> is somewhat historical, since the data
|
|
structure no longer necessarily contains an execution plan.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-prepare-cursor">
|
|
<refmeta>
|
|
<refentrytitle>SPI_prepare_cursor</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_prepare_cursor</refname>
|
|
<refpurpose>prepare a statement, without executing it yet</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_prepare_cursor</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>,
|
|
Oid * <parameter>argtypes</parameter>, int <parameter>cursorOptions</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_prepare_cursor</function> is identical to
|
|
<function>SPI_prepare</function>, except that it also allows specification
|
|
of the planner's <quote>cursor options</> parameter. This is a bit mask
|
|
having the values shown in <filename>nodes/parsenodes.h</filename>
|
|
for the <structfield>options</> field of <structname>DeclareCursorStmt</>.
|
|
<function>SPI_prepare</function> always takes the cursor options as zero.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>command</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
command string
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>nargs</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of input parameters (<literal>$1</>, <literal>$2</>, etc.)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Oid * <parameter>argtypes</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
pointer to an array containing the <acronym>OID</acronym>s of
|
|
the data types of the parameters
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>cursorOptions</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
integer bit mask of cursor options; zero produces default behavior
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<function>SPI_prepare_cursor</function> has the same return conventions as
|
|
<function>SPI_prepare</function>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
Useful bits to set in <parameter>cursorOptions</> include
|
|
<symbol>CURSOR_OPT_SCROLL</symbol>,
|
|
<symbol>CURSOR_OPT_NO_SCROLL</symbol>,
|
|
<symbol>CURSOR_OPT_FAST_PLAN</symbol>,
|
|
<symbol>CURSOR_OPT_GENERIC_PLAN</symbol>, and
|
|
<symbol>CURSOR_OPT_CUSTOM_PLAN</symbol>. Note in particular that
|
|
<symbol>CURSOR_OPT_HOLD</symbol> is ignored.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-prepare-params">
|
|
<refmeta>
|
|
<refentrytitle>SPI_prepare_params</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_prepare_params</refname>
|
|
<refpurpose>prepare a statement, without executing it yet</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_prepare_params</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
SPIPlanPtr SPI_prepare_params(const char * <parameter>command</parameter>,
|
|
ParserSetupHook <parameter>parserSetup</parameter>,
|
|
void * <parameter>parserSetupArg</parameter>,
|
|
int <parameter>cursorOptions</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_prepare_params</function> creates and returns a prepared
|
|
statement for the specified command, but doesn't execute the command.
|
|
This function is equivalent to <function>SPI_prepare_cursor</function>,
|
|
with the addition that the caller can specify parser hook functions
|
|
to control the parsing of external parameter references.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>command</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
command string
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>ParserSetupHook <parameter>parserSetup</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
Parser hook setup function
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>void * <parameter>parserSetupArg</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
passthrough argument for <parameter>parserSetup</parameter>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>cursorOptions</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
integer bit mask of cursor options; zero produces default behavior
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<function>SPI_prepare_params</function> has the same return conventions as
|
|
<function>SPI_prepare</function>.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-getargcount">
|
|
<refmeta>
|
|
<refentrytitle>SPI_getargcount</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_getargcount</refname>
|
|
<refpurpose>return the number of arguments needed by a statement
|
|
prepared by <function>SPI_prepare</function></refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_getargcount</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_getargcount(SPIPlanPtr <parameter>plan</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_getargcount</function> returns the number of arguments needed
|
|
to execute a statement prepared by <function>SPI_prepare</function>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (returned by <function>SPI_prepare</function>)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
<para>
|
|
The count of expected arguments for the <parameter>plan</parameter>.
|
|
If the <parameter>plan</parameter> is <symbol>NULL</symbol> or invalid,
|
|
<varname>SPI_result</varname> is set to <symbol>SPI_ERROR_ARGUMENT</symbol>
|
|
and -1 is returned.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-getargtypeid">
|
|
<refmeta>
|
|
<refentrytitle>SPI_getargtypeid</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_getargtypeid</refname>
|
|
<refpurpose>return the data type OID for an argument of
|
|
a statement prepared by <function>SPI_prepare</function></refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_getargtypeid</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Oid SPI_getargtypeid(SPIPlanPtr <parameter>plan</parameter>, int <parameter>argIndex</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_getargtypeid</function> returns the OID representing the type
|
|
for the <parameter>argIndex</parameter>'th argument of a statement prepared by
|
|
<function>SPI_prepare</function>. First argument is at index zero.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (returned by <function>SPI_prepare</function>)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>argIndex</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
zero based index of the argument
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
<para>
|
|
The type OID of the argument at the given index.
|
|
If the <parameter>plan</parameter> is <symbol>NULL</symbol> or invalid,
|
|
or <parameter>argIndex</parameter> is less than 0 or
|
|
not less than the number of arguments declared for the
|
|
<parameter>plan</parameter>,
|
|
<varname>SPI_result</varname> is set to <symbol>SPI_ERROR_ARGUMENT</symbol>
|
|
and <symbol>InvalidOid</symbol> is returned.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-is-cursor-plan">
|
|
<refmeta>
|
|
<refentrytitle>SPI_is_cursor_plan</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_is_cursor_plan</refname>
|
|
<refpurpose>return <symbol>true</symbol> if a statement
|
|
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>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
bool SPI_is_cursor_plan(SPIPlanPtr <parameter>plan</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_is_cursor_plan</function> returns <symbol>true</symbol>
|
|
if a statement prepared by <function>SPI_prepare</function> can be passed
|
|
as an argument to <function>SPI_cursor_open</function>, or
|
|
<symbol>false</symbol> if that is not the case. The criteria are that the
|
|
<parameter>plan</parameter> represents one single command and that this
|
|
command returns tuples to the caller; for example, <command>SELECT</>
|
|
is allowed unless it contains an <literal>INTO</> clause, and
|
|
<command>UPDATE</> is allowed only if it contains a <literal>RETURNING</>
|
|
clause.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (returned by <function>SPI_prepare</function>)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
<para>
|
|
<symbol>true</symbol> or <symbol>false</symbol> to indicate if the
|
|
<parameter>plan</parameter> can produce a cursor or not, with
|
|
<varname>SPI_result</varname> set to zero.
|
|
If it is not possible to determine the answer (for example,
|
|
if the <parameter>plan</parameter> is <symbol>NULL</symbol> or invalid,
|
|
or if called when not connected to SPI), then
|
|
<varname>SPI_result</varname> is set to a suitable error code
|
|
and <symbol>false</symbol> is returned.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-execute-plan">
|
|
<refmeta>
|
|
<refentrytitle>SPI_execute_plan</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_execute_plan</refname>
|
|
<refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_execute_plan</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>,
|
|
bool <parameter>read_only</parameter>, long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_execute_plan</function> executes a statement prepared by
|
|
<function>SPI_prepare</function> or one of its siblings.
|
|
<parameter>read_only</parameter> and
|
|
<parameter>count</parameter> have the same interpretation as in
|
|
<function>SPI_execute</function>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (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
|
|
statement'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 statement'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_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>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to return,
|
|
or <literal>0</> for no limit
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The return value is the same as for <function>SPI_execute</function>,
|
|
with the following additional possible error (negative) results:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_ARGUMENT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <parameter>plan</parameter> is <symbol>NULL</symbol> or invalid,
|
|
or <parameter>count</parameter> is less than 0
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_PARAM</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <parameter>values</parameter> is <symbol>NULL</symbol> and
|
|
<parameter>plan</parameter> was prepared with some parameters
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<para>
|
|
<varname>SPI_processed</varname> and
|
|
<varname>SPI_tuptable</varname> are set as in
|
|
<function>SPI_execute</function> if successful.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-execute-plan-with-paramlist">
|
|
<refmeta>
|
|
<refentrytitle>SPI_execute_plan_with_paramlist</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_execute_plan_with_paramlist</refname>
|
|
<refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_execute_plan_with_paramlist</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
|
|
ParamListInfo <parameter>params</parameter>,
|
|
bool <parameter>read_only</parameter>,
|
|
long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_execute_plan_with_paramlist</function> executes a statement
|
|
prepared by <function>SPI_prepare</function>.
|
|
This function is equivalent to <function>SPI_execute_plan</function>
|
|
except that information about the parameter values to be passed to the
|
|
query is presented differently. The <literal>ParamListInfo</>
|
|
representation can be convenient for passing down values that are
|
|
already available in that format. It also supports use of dynamic
|
|
parameter sets via hook functions specified in <literal>ParamListInfo</>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (returned by <function>SPI_prepare</function>)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>ParamListInfo <parameter>params</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
data structure containing parameter types and values; NULL if none
|
|
</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>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to return,
|
|
or <literal>0</> for no limit
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The return value is the same as for <function>SPI_execute_plan</function>.
|
|
</para>
|
|
|
|
<para>
|
|
<varname>SPI_processed</varname> and
|
|
<varname>SPI_tuptable</varname> are set as in
|
|
<function>SPI_execute_plan</function> if successful.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-execp">
|
|
<refmeta>
|
|
<refentrytitle>SPI_execp</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_execp</refname>
|
|
<refpurpose>execute a statement in read/write mode</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_execp</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_execp(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>, long <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>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (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
|
|
statement'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 statement'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>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to return,
|
|
or <literal>0</> for no limit
|
|
</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>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-open">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_open</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_open</refname>
|
|
<refpurpose>set up a cursor using a statement created with <function>SPI_prepare</function></refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_open</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <parameter>plan</parameter>,
|
|
Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>,
|
|
bool <parameter>read_only</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_open</function> sets up a cursor (internally,
|
|
a portal) that will execute a statement prepared by
|
|
<function>SPI_prepare</function>. The parameters have the same
|
|
meanings as the corresponding parameters to
|
|
<function>SPI_execute_plan</function>.
|
|
</para>
|
|
|
|
<para>
|
|
Using a cursor instead of executing the statement directly has two
|
|
benefits. First, the result rows can be retrieved a few at a time,
|
|
avoiding memory overrun for queries that return many rows. Second,
|
|
a portal can outlive the current procedure (it can, in fact, live
|
|
to the end of the current transaction). Returning the portal name
|
|
to the procedure's caller provides a way of returning a row set as
|
|
result.
|
|
</para>
|
|
|
|
<para>
|
|
The passed-in parameter data will be copied into the cursor's portal, so it
|
|
can be freed while the cursor still exists.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>name</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
name for portal, or <symbol>NULL</symbol> to let the system
|
|
select a name
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (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
|
|
statement'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 statement'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_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>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
Pointer to portal containing the cursor. Note there is no error
|
|
return convention; any error will be reported via <function>elog</>.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-open-with-args">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_open_with_args</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_open_with_args</refname>
|
|
<refpurpose>set up a cursor using a query and parameters</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_open_with_args</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Portal SPI_cursor_open_with_args(const char *<parameter>name</parameter>,
|
|
const char *<parameter>command</parameter>,
|
|
int <parameter>nargs</parameter>, Oid *<parameter>argtypes</parameter>,
|
|
Datum *<parameter>values</parameter>, const char *<parameter>nulls</parameter>,
|
|
bool <parameter>read_only</parameter>, int <parameter>cursorOptions</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_open_with_args</function> sets up a cursor
|
|
(internally, a portal) that will execute the specified query.
|
|
Most of the parameters have the same meanings as the corresponding
|
|
parameters to <function>SPI_prepare_cursor</function>
|
|
and <function>SPI_cursor_open</function>.
|
|
</para>
|
|
|
|
<para>
|
|
For one-time query execution, this function should be preferred
|
|
over <function>SPI_prepare_cursor</function> followed by
|
|
<function>SPI_cursor_open</function>.
|
|
If the same command is to be executed with many different parameters,
|
|
either method might be faster, depending on the cost of re-planning
|
|
versus the benefit of custom plans.
|
|
</para>
|
|
|
|
<para>
|
|
The passed-in parameter data will be copied into the cursor's portal, so it
|
|
can be freed while the cursor still exists.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>name</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
name for portal, or <symbol>NULL</symbol> to let the system
|
|
select a name
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>command</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
command string
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>nargs</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of input parameters (<literal>$1</>, <literal>$2</>, etc.)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Oid * <parameter>argtypes</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
an array containing the <acronym>OID</acronym>s of
|
|
the data types of the parameters
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Datum * <parameter>values</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
an array of actual parameter values
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>nulls</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
an array describing which parameters are null
|
|
</para>
|
|
|
|
<para>
|
|
If <parameter>nulls</parameter> is <symbol>NULL</symbol> then
|
|
<function>SPI_cursor_open_with_args</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>cursorOptions</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
integer bit mask of cursor options; zero produces default behavior
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
Pointer to portal containing the cursor. Note there is no error
|
|
return convention; any error will be reported via <function>elog</>.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-open-with-paramlist">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_open_with_paramlist</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_open_with_paramlist</refname>
|
|
<refpurpose>set up a cursor using parameters</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_open_with_paramlist</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Portal SPI_cursor_open_with_paramlist(const char *<parameter>name</parameter>,
|
|
SPIPlanPtr <parameter>plan</parameter>,
|
|
ParamListInfo <parameter>params</parameter>,
|
|
bool <parameter>read_only</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_open_with_paramlist</function> sets up a cursor
|
|
(internally, a portal) that will execute a statement prepared by
|
|
<function>SPI_prepare</function>.
|
|
This function is equivalent to <function>SPI_cursor_open</function>
|
|
except that information about the parameter values to be passed to the
|
|
query is presented differently. The <literal>ParamListInfo</>
|
|
representation can be convenient for passing down values that are
|
|
already available in that format. It also supports use of dynamic
|
|
parameter sets via hook functions specified in <literal>ParamListInfo</>.
|
|
</para>
|
|
|
|
<para>
|
|
The passed-in parameter data will be copied into the cursor's portal, so it
|
|
can be freed while the cursor still exists.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>name</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
name for portal, or <symbol>NULL</symbol> to let the system
|
|
select a name
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
prepared statement (returned by <function>SPI_prepare</function>)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>ParamListInfo <parameter>params</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
data structure containing parameter types and values; NULL if none
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>bool <parameter>read_only</parameter></literal></term>
|
|
<listitem>
|
|
<para><literal>true</> for read-only execution</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
Pointer to portal containing the cursor. Note there is no error
|
|
return convention; any error will be reported via <function>elog</>.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-find">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_find</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_find</refname>
|
|
<refpurpose>find an existing cursor by name</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_find</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Portal SPI_cursor_find(const char * <parameter>name</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_find</function> finds an existing portal by
|
|
name. This is primarily useful to resolve a cursor name returned
|
|
as text by some other function.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>name</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
name of the portal
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
pointer to the portal with the specified name, or
|
|
<symbol>NULL</symbol> if none was found
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-fetch">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_fetch</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_fetch</refname>
|
|
<refpurpose>fetch some rows from a cursor</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_fetch</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_cursor_fetch(Portal <parameter>portal</parameter>, bool <parameter>forward</parameter>, long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_fetch</function> fetches some rows from a
|
|
cursor. This is equivalent to a subset of the SQL command
|
|
<command>FETCH</> (see <function>SPI_scroll_cursor_fetch</function>
|
|
for more functionality).
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
portal containing the cursor
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>bool <parameter>forward</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
true for fetch forward, false for fetch backward
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to fetch
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<varname>SPI_processed</varname> and
|
|
<varname>SPI_tuptable</varname> are set as in
|
|
<function>SPI_execute</function> if successful.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
Fetching backward may fail if the cursor's plan was not created
|
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-move">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_move</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_move</refname>
|
|
<refpurpose>move a cursor</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_move</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_cursor_move(Portal <parameter>portal</parameter>, bool <parameter>forward</parameter>, long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_move</function> skips over some number of rows
|
|
in a cursor. This is equivalent to a subset of the SQL command
|
|
<command>MOVE</> (see <function>SPI_scroll_cursor_move</function>
|
|
for more functionality).
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
portal containing the cursor
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>bool <parameter>forward</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
true for move forward, false for move backward
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
maximum number of rows to move
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
Moving backward may fail if the cursor's plan was not created
|
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-scroll-cursor-fetch">
|
|
<refmeta>
|
|
<refentrytitle>SPI_scroll_cursor_fetch</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_scroll_cursor_fetch</refname>
|
|
<refpurpose>fetch some rows from a cursor</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_scroll_cursor_fetch</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_scroll_cursor_fetch(Portal <parameter>portal</parameter>, FetchDirection <parameter>direction</parameter>,
|
|
long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_scroll_cursor_fetch</function> fetches some rows from a
|
|
cursor. This is equivalent to the SQL command <command>FETCH</>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
portal containing the cursor
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>FetchDirection <parameter>direction</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
one of <symbol>FETCH_FORWARD</symbol>,
|
|
<symbol>FETCH_BACKWARD</symbol>,
|
|
<symbol>FETCH_ABSOLUTE</symbol> or
|
|
<symbol>FETCH_RELATIVE</symbol>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of rows to fetch for
|
|
<symbol>FETCH_FORWARD</symbol> or
|
|
<symbol>FETCH_BACKWARD</symbol>; absolute row number to fetch for
|
|
<symbol>FETCH_ABSOLUTE</symbol>; or relative row number to fetch for
|
|
<symbol>FETCH_RELATIVE</symbol>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<varname>SPI_processed</varname> and
|
|
<varname>SPI_tuptable</varname> are set as in
|
|
<function>SPI_execute</function> if successful.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
See the SQL <xref linkend="sql-fetch"> command
|
|
for details of the interpretation of the
|
|
<parameter>direction</parameter> and
|
|
<parameter>count</parameter> parameters.
|
|
</para>
|
|
|
|
<para>
|
|
Direction values other than <symbol>FETCH_FORWARD</symbol>
|
|
may fail if the cursor's plan was not created
|
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-scroll-cursor-move">
|
|
<refmeta>
|
|
<refentrytitle>SPI_scroll_cursor_move</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_scroll_cursor_move</refname>
|
|
<refpurpose>move a cursor</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_scroll_cursor_move</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_scroll_cursor_move(Portal <parameter>portal</parameter>, FetchDirection <parameter>direction</parameter>,
|
|
long <parameter>count</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_scroll_cursor_move</function> skips over some number of rows
|
|
in a cursor. This is equivalent to the SQL command
|
|
<command>MOVE</>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
portal containing the cursor
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>FetchDirection <parameter>direction</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
one of <symbol>FETCH_FORWARD</symbol>,
|
|
<symbol>FETCH_BACKWARD</symbol>,
|
|
<symbol>FETCH_ABSOLUTE</symbol> or
|
|
<symbol>FETCH_RELATIVE</symbol>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>long <parameter>count</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of rows to move for
|
|
<symbol>FETCH_FORWARD</symbol> or
|
|
<symbol>FETCH_BACKWARD</symbol>; absolute row number to move to for
|
|
<symbol>FETCH_ABSOLUTE</symbol>; or relative row number to move to for
|
|
<symbol>FETCH_RELATIVE</symbol>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<varname>SPI_processed</varname> is set as in
|
|
<function>SPI_execute</function> if successful.
|
|
<varname>SPI_tuptable</varname> is set to <symbol>NULL</>, since
|
|
no rows are returned by this function.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
See the SQL <xref linkend="sql-fetch"> command
|
|
for details of the interpretation of the
|
|
<parameter>direction</parameter> and
|
|
<parameter>count</parameter> parameters.
|
|
</para>
|
|
|
|
<para>
|
|
Direction values other than <symbol>FETCH_FORWARD</symbol>
|
|
may fail if the cursor's plan was not created
|
|
with the <symbol>CURSOR_OPT_SCROLL</symbol> option.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-cursor-close">
|
|
<refmeta>
|
|
<refentrytitle>SPI_cursor_close</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_cursor_close</refname>
|
|
<refpurpose>close a cursor</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_cursor_close</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_cursor_close(Portal <parameter>portal</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_cursor_close</function> closes a previously created
|
|
cursor and releases its portal storage.
|
|
</para>
|
|
|
|
<para>
|
|
All open cursors are closed automatically at the end of a
|
|
transaction. <function>SPI_cursor_close</function> need only be
|
|
invoked if it is desirable to release resources sooner.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Portal <parameter>portal</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
portal containing the cursor
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-keepplan">
|
|
<refmeta>
|
|
<refentrytitle>SPI_keepplan</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_keepplan</refname>
|
|
<refpurpose>save a prepared statement</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_keepplan</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_keepplan(SPIPlanPtr <parameter>plan</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_keepplan</function> saves a passed statement (prepared by
|
|
<function>SPI_prepare</function>) so that it will not be freed
|
|
by <function>SPI_finish</function> nor by the transaction manager.
|
|
This gives you the ability to reuse prepared statements in the subsequent
|
|
invocations of your procedure in the current session.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
the prepared statement to be saved
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
0 on success;
|
|
<symbol>SPI_ERROR_ARGUMENT</symbol> if <parameter>plan</parameter>
|
|
is <symbol>NULL</symbol> or invalid
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
The passed-in statement is relocated to permanent storage by means
|
|
of pointer adjustment (no data copying is required). If you later
|
|
wish to delete it, use <function>SPI_freeplan</function> on it.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-saveplan">
|
|
<refmeta>
|
|
<refentrytitle>SPI_saveplan</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_saveplan</refname>
|
|
<refpurpose>save a prepared statement</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_saveplan</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
SPIPlanPtr SPI_saveplan(SPIPlanPtr <parameter>plan</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_saveplan</function> copies a passed statement (prepared by
|
|
<function>SPI_prepare</function>) into memory that will not be freed
|
|
by <function>SPI_finish</function> nor by the transaction manager,
|
|
and returns a pointer to the copied statement. This gives you the
|
|
ability to reuse prepared statements in the subsequent invocations of
|
|
your procedure in the current session.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
the prepared statement to be saved
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
Pointer to the copied statement; or <symbol>NULL</symbol> if unsuccessful.
|
|
On error, <varname>SPI_result</varname> is set thus:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_ARGUMENT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <parameter>plan</parameter> is <symbol>NULL</symbol> or invalid
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_UNCONNECTED</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if called from an unconnected procedure
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Notes</title>
|
|
|
|
<para>
|
|
The originally passed-in statement is not freed, so you might wish to do
|
|
<function>SPI_freeplan</function> on it to avoid leaking memory
|
|
until <function>SPI_finish</>.
|
|
</para>
|
|
|
|
<para>
|
|
In most cases, <function>SPI_keepplan</function> is preferred to this
|
|
function, since it accomplishes largely the same result without needing
|
|
to physically copy the prepared statement's data structures.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="spi-interface-support">
|
|
<title>Interface Support Functions</title>
|
|
|
|
<para>
|
|
The functions described here provide an interface for extracting
|
|
information from result sets returned by <function>SPI_execute</> and
|
|
other SPI functions.
|
|
</para>
|
|
|
|
<para>
|
|
All functions described in this section can be used by both
|
|
connected and unconnected procedures.
|
|
</para>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-fname">
|
|
<refmeta>
|
|
<refentrytitle>SPI_fname</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_fname</refname>
|
|
<refpurpose>determine the column name for the specified column number</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_fname</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
char * SPI_fname(TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_fname</function> returns a copy of the column name of the
|
|
specified column. (You can use <function>pfree</function> to
|
|
release the copy of the name when you don't need it anymore.)
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row description
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>colnumber</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
column number (count starts at 1)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The column name; <symbol>NULL</symbol> if
|
|
<parameter>colnumber</parameter> is out of range.
|
|
<varname>SPI_result</varname> set to
|
|
<symbol>SPI_ERROR_NOATTRIBUTE</symbol> on error.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-fnumber">
|
|
<refmeta>
|
|
<refentrytitle>SPI_fnumber</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_fnumber</refname>
|
|
<refpurpose>determine the column number for the specified column name</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_fnumber</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_fnumber(TupleDesc <parameter>rowdesc</parameter>, const char * <parameter>colname</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_fnumber</function> returns the column number for the
|
|
column with the specified name.
|
|
</para>
|
|
|
|
<para>
|
|
If <parameter>colname</parameter> refers to a system column (e.g.,
|
|
<literal>oid</>) then the appropriate negative column number will
|
|
be returned. The caller should be careful to test the return value
|
|
for exact equality to <symbol>SPI_ERROR_NOATTRIBUTE</symbol> to
|
|
detect an error; testing the result for less than or equal to 0 is
|
|
not correct unless system columns should be rejected.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row description
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>colname</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
column name
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
Column number (count starts at 1), or
|
|
<symbol>SPI_ERROR_NOATTRIBUTE</symbol> if the named column was not
|
|
found.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-getvalue">
|
|
<refmeta>
|
|
<refentrytitle>SPI_getvalue</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_getvalue</refname>
|
|
<refpurpose>return the string value of the specified column</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_getvalue</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
char * SPI_getvalue(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_getvalue</function> returns the string representation
|
|
of the value of the specified column.
|
|
</para>
|
|
|
|
<para>
|
|
The result is returned in memory allocated using
|
|
<function>palloc</function>. (You can use
|
|
<function>pfree</function> to release the memory when you don't
|
|
need it anymore.)
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>HeapTuple <parameter>row</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row to be examined
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row description
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>colnumber</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
column number (count starts at 1)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
Column value, or <symbol>NULL</symbol> if the column is null,
|
|
<parameter>colnumber</parameter> is out of range
|
|
(<varname>SPI_result</varname> is set to
|
|
<symbol>SPI_ERROR_NOATTRIBUTE</symbol>), or no output function is
|
|
available (<varname>SPI_result</varname> is set to
|
|
<symbol>SPI_ERROR_NOOUTFUNC</symbol>).
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-getbinval">
|
|
<refmeta>
|
|
<refentrytitle>SPI_getbinval</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_getbinval</refname>
|
|
<refpurpose>return the binary value of the specified column</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_getbinval</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Datum SPI_getbinval(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>,
|
|
bool * <parameter>isnull</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_getbinval</function> returns the value of the
|
|
specified column in the internal form (as type <type>Datum</type>).
|
|
</para>
|
|
|
|
<para>
|
|
This function does not allocate new space for the datum. In the
|
|
case of a pass-by-reference data type, the return value will be a
|
|
pointer into the passed row.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>HeapTuple <parameter>row</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row to be examined
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row description
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>colnumber</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
column number (count starts at 1)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>bool * <parameter>isnull</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
flag for a null value in the column
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The binary value of the column is returned. The variable pointed
|
|
to by <parameter>isnull</parameter> is set to true if the column is
|
|
null, else to false.
|
|
</para>
|
|
|
|
<para>
|
|
<varname>SPI_result</varname> is set to
|
|
<symbol>SPI_ERROR_NOATTRIBUTE</symbol> on error.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-gettype">
|
|
<refmeta>
|
|
<refentrytitle>SPI_gettype</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_gettype</refname>
|
|
<refpurpose>return the data type name of the specified column</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_gettype</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
char * SPI_gettype(TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_gettype</function> returns a copy of the data type name of the
|
|
specified column. (You can use <function>pfree</function> to
|
|
release the copy of the name when you don't need it anymore.)
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row description
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>colnumber</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
column number (count starts at 1)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The data type name of the specified column, or
|
|
<symbol>NULL</symbol> on error. <varname>SPI_result</varname> is
|
|
set to <symbol>SPI_ERROR_NOATTRIBUTE</symbol> on error.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-gettypeid">
|
|
<refmeta>
|
|
<refentrytitle>SPI_gettypeid</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_gettypeid</refname>
|
|
<refpurpose>return the data type <acronym>OID</acronym> of the specified column</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_gettypeid</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
Oid SPI_gettypeid(TupleDesc <parameter>rowdesc</parameter>, int <parameter>colnumber</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_gettypeid</function> returns the
|
|
<acronym>OID</acronym> of the data type of the specified column.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input row description
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>colnumber</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
column number (count starts at 1)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The <acronym>OID</acronym> of the data type of the specified column
|
|
or <symbol>InvalidOid</symbol> on error. On error,
|
|
<varname>SPI_result</varname> is set to
|
|
<symbol>SPI_ERROR_NOATTRIBUTE</symbol>.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-getrelname">
|
|
<refmeta>
|
|
<refentrytitle>SPI_getrelname</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_getrelname</refname>
|
|
<refpurpose>return the name of the specified relation</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_getrelname</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
char * SPI_getrelname(Relation <parameter>rel</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_getrelname</function> returns a copy of the name of the
|
|
specified relation. (You can use <function>pfree</function> to
|
|
release the copy of the name when you don't need it anymore.)
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Relation <parameter>rel</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input relation
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The name of the specified relation.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<refentry id="spi-spi-getnspname">
|
|
<refmeta>
|
|
<refentrytitle>SPI_getnspname</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_getnspname</refname>
|
|
<refpurpose>return the namespace of the specified relation</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_getnspname</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
char * SPI_getnspname(Relation <parameter>rel</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_getnspname</function> returns a copy of the name of
|
|
the namespace that the specified <structname>Relation</structname>
|
|
belongs to. This is equivalent to the relation's schema. You should
|
|
<function>pfree</function> the return value of this function when
|
|
you are finished with it.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Relation <parameter>rel</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
input relation
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
The name of the specified relation's namespace.
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="spi-memory">
|
|
<title>Memory Management</title>
|
|
|
|
<para>
|
|
<indexterm>
|
|
<primary>memory context</primary>
|
|
<secondary>in SPI</secondary>
|
|
</indexterm>
|
|
<productname>PostgreSQL</productname> allocates memory within
|
|
<firstterm>memory contexts</firstterm>, which provide a convenient method of
|
|
managing allocations made in many different places that need to
|
|
live for differing amounts of time. Destroying a context releases
|
|
all the memory that was allocated in it. Thus, it is not necessary
|
|
to keep track of individual objects to avoid memory leaks; instead
|
|
only a relatively small number of contexts have to be managed.
|
|
<function>palloc</function> and related functions allocate memory
|
|
from the <quote>current</> context.
|
|
</para>
|
|
|
|
<para>
|
|
<function>SPI_connect</function> creates a new memory context and
|
|
makes it current. <function>SPI_finish</function> restores the
|
|
previous current memory context and destroys the context created by
|
|
<function>SPI_connect</function>. These actions ensure that
|
|
transient memory allocations made inside your procedure are
|
|
reclaimed at procedure exit, avoiding memory leakage.
|
|
</para>
|
|
|
|
<para>
|
|
However, if your procedure needs to return an object in allocated
|
|
memory (such as a value of a pass-by-reference data type), you
|
|
cannot allocate that memory using <function>palloc</function>, at
|
|
least not while you are connected to SPI. If you try, the object
|
|
will be deallocated by <function>SPI_finish</function>, and your
|
|
procedure will not work reliably. To solve this problem, use
|
|
<function>SPI_palloc</function> to allocate memory for your return
|
|
object. <function>SPI_palloc</function> allocates memory in the
|
|
<quote>upper executor context</quote>, that is, the memory context
|
|
that was current when <function>SPI_connect</function> was called,
|
|
which is precisely the right context for a value returned from your
|
|
procedure.
|
|
</para>
|
|
|
|
<para>
|
|
If <function>SPI_palloc</function> is called while the procedure is
|
|
not connected to SPI, then it acts the same as a normal
|
|
<function>palloc</function>. Before a procedure connects to the
|
|
SPI manager, the current memory context is the upper executor
|
|
context, so all allocations made by the procedure via
|
|
<function>palloc</function> or by SPI utility functions are made in
|
|
this context.
|
|
</para>
|
|
|
|
<para>
|
|
When <function>SPI_connect</function> is called, the private
|
|
context of the procedure, which is created by
|
|
<function>SPI_connect</function>, is made the current context. All
|
|
allocations made by <function>palloc</function>,
|
|
<function>repalloc</function>, or SPI utility functions (except for
|
|
<function>SPI_copytuple</function>,
|
|
<function>SPI_returntuple</function>,
|
|
<function>SPI_modifytuple</function>, and
|
|
<function>SPI_palloc</function>) are made in this context. When a
|
|
procedure disconnects from the SPI manager (via
|
|
<function>SPI_finish</function>) the current context is restored to
|
|
the upper executor context, and all allocations made in the
|
|
procedure memory context are freed and cannot be used any more.
|
|
</para>
|
|
|
|
<para>
|
|
All functions described in this section can be used by both
|
|
connected and unconnected procedures. In an unconnected procedure,
|
|
they act the same as the underlying ordinary server functions
|
|
(<function>palloc</>, etc.).
|
|
</para>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-palloc">
|
|
<refmeta>
|
|
<refentrytitle>SPI_palloc</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_palloc</refname>
|
|
<refpurpose>allocate memory in the upper executor context</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_palloc</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void * SPI_palloc(Size <parameter>size</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_palloc</function> allocates memory in the upper
|
|
executor context.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Size <parameter>size</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
size in bytes of storage to allocate
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
pointer to new storage space of the specified size
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-realloc">
|
|
<refmeta>
|
|
<refentrytitle>SPI_repalloc</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_repalloc</refname>
|
|
<refpurpose>reallocate memory in the upper executor context</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_repalloc</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void * SPI_repalloc(void * <parameter>pointer</parameter>, Size <parameter>size</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_repalloc</function> changes the size of a memory
|
|
segment previously allocated using <function>SPI_palloc</function>.
|
|
</para>
|
|
|
|
<para>
|
|
This function is no longer different from plain
|
|
<function>repalloc</function>. It's kept just for backward
|
|
compatibility of existing code.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>void * <parameter>pointer</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
pointer to existing storage to change
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Size <parameter>size</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
size in bytes of storage to allocate
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
pointer to new storage space of specified size with the contents
|
|
copied from the existing area
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-pfree">
|
|
<refmeta>
|
|
<refentrytitle>SPI_pfree</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_pfree</refname>
|
|
<refpurpose>free memory in the upper executor context</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_pfree</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_pfree(void * <parameter>pointer</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_pfree</function> frees memory previously allocated
|
|
using <function>SPI_palloc</function> or
|
|
<function>SPI_repalloc</function>.
|
|
</para>
|
|
|
|
<para>
|
|
This function is no longer different from plain
|
|
<function>pfree</function>. It's kept just for backward
|
|
compatibility of existing code.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>void * <parameter>pointer</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
pointer to existing storage to free
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-copytuple">
|
|
<refmeta>
|
|
<refentrytitle>SPI_copytuple</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_copytuple</refname>
|
|
<refpurpose>make a copy of a row in the upper executor context</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_copytuple</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
HeapTuple SPI_copytuple(HeapTuple <parameter>row</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_copytuple</function> makes a copy of a row in the
|
|
upper executor context. This is normally used to return a modified
|
|
row from a trigger. In a function declared to return a composite
|
|
type, use <function>SPI_returntuple</function> instead.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>HeapTuple <parameter>row</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
row to be copied
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
the copied row; <symbol>NULL</symbol> only if
|
|
<parameter>tuple</parameter> is <symbol>NULL</symbol>
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-returntuple">
|
|
<refmeta>
|
|
<refentrytitle>SPI_returntuple</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_returntuple</refname>
|
|
<refpurpose>prepare to return a tuple as a Datum</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_returntuple</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
HeapTupleHeader SPI_returntuple(HeapTuple <parameter>row</parameter>, TupleDesc <parameter>rowdesc</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_returntuple</function> makes a copy of a row in
|
|
the upper executor context, returning it in the form of a row type <type>Datum</type>.
|
|
The returned pointer need only be converted to <type>Datum</type> via <function>PointerGetDatum</function>
|
|
before returning.
|
|
</para>
|
|
|
|
<para>
|
|
Note that this should be used for functions that are declared to return
|
|
composite types. It is not used for triggers; use
|
|
<function>SPI_copytuple</> for returning a modified row in a trigger.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>HeapTuple <parameter>row</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
row to be copied
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>TupleDesc <parameter>rowdesc</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
descriptor for row (pass the same descriptor each time for most
|
|
effective caching)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
<type>HeapTupleHeader</type> pointing to copied row;
|
|
<symbol>NULL</symbol> only if
|
|
<parameter>row</parameter> or <parameter>rowdesc</parameter> is
|
|
<symbol>NULL</symbol>
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-modifytuple">
|
|
<refmeta>
|
|
<refentrytitle>SPI_modifytuple</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_modifytuple</refname>
|
|
<refpurpose>create a row by replacing selected fields of a given row</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_modifytuple</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
HeapTuple SPI_modifytuple(Relation <parameter>rel</parameter>, HeapTuple <parameter>row</parameter>, int <parameter>ncols</parameter>,
|
|
int * <parameter>colnum</parameter>, Datum * <parameter>values</parameter>, const char * <parameter>nulls</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_modifytuple</function> creates a new row by
|
|
substituting new values for selected columns, copying the original
|
|
row's columns at other positions. The input row is not modified.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>Relation <parameter>rel</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
Used only as the source of the row descriptor for the row.
|
|
(Passing a relation rather than a row descriptor is a
|
|
misfeature.)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>HeapTuple <parameter>row</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
row to be modified
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int <parameter>ncols</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
number of column numbers in the array
|
|
<parameter>colnum</parameter>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>int * <parameter>colnum</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
array of the numbers of the columns that are to be changed
|
|
(column numbers start at 1)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>Datum * <parameter>values</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
new values for the specified columns
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>const char * <parameter>Nulls</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
which new values are null, if any (see
|
|
<function>SPI_execute_plan</function> for the format)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
new row with modifications, allocated in the upper executor
|
|
context; <symbol>NULL</symbol> only if <parameter>row</parameter>
|
|
is <symbol>NULL</symbol>
|
|
</para>
|
|
|
|
<para>
|
|
On error, <varname>SPI_result</varname> is set as follows:
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_ARGUMENT</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <parameter>rel</> is <symbol>NULL</>, or if
|
|
<parameter>row</> is <symbol>NULL</>, or if <parameter>ncols</>
|
|
is less than or equal to 0, or if <parameter>colnum</> is
|
|
<symbol>NULL</>, or if <parameter>values</> is <symbol>NULL</>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><symbol>SPI_ERROR_NOATTRIBUTE</symbol></term>
|
|
<listitem>
|
|
<para>
|
|
if <parameter>colnum</> contains an invalid column number (less
|
|
than or equal to 0 or greater than the number of column in
|
|
<parameter>row</>)
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-freetuple">
|
|
<refmeta>
|
|
<refentrytitle>SPI_freetuple</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_freetuple</refname>
|
|
<refpurpose>free a row allocated in the upper executor context</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_freetuple</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_freetuple(HeapTuple <parameter>row</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_freetuple</function> frees a row previously allocated
|
|
in the upper executor context.
|
|
</para>
|
|
|
|
<para>
|
|
This function is no longer different from plain
|
|
<function>heap_freetuple</function>. It's kept just for backward
|
|
compatibility of existing code.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>HeapTuple <parameter>row</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
row to free
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-freetupletable">
|
|
<refmeta>
|
|
<refentrytitle>SPI_freetuptable</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_freetuptable</refname>
|
|
<refpurpose>free a row set created by <function>SPI_execute</> or a similar
|
|
function</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_freetuptable</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
void SPI_freetuptable(SPITupleTable * <parameter>tuptable</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_freetuptable</function> frees a row set created by a
|
|
prior SPI command execution function, such as
|
|
<function>SPI_execute</>. Therefore, this function is usually called
|
|
with the global variable <varname>SPI_tupletable</varname> as
|
|
argument.
|
|
</para>
|
|
|
|
<para>
|
|
This function is useful if a SPI procedure needs to execute
|
|
multiple commands and does not want to keep the results of earlier
|
|
commands around until it ends. Note that any unfreed row sets will
|
|
be freed anyway at <function>SPI_finish</>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPITupleTable * <parameter>tuptable</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
pointer to row set to free
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- *********************************************** -->
|
|
|
|
<refentry id="spi-spi-freeplan">
|
|
<refmeta>
|
|
<refentrytitle>SPI_freeplan</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>SPI_freeplan</refname>
|
|
<refpurpose>free a previously saved prepared statement</refpurpose>
|
|
</refnamediv>
|
|
|
|
<indexterm><primary>SPI_freeplan</primary></indexterm>
|
|
|
|
<refsynopsisdiv>
|
|
<synopsis>
|
|
int SPI_freeplan(SPIPlanPtr <parameter>plan</parameter>)
|
|
</synopsis>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1>
|
|
<title>Description</title>
|
|
|
|
<para>
|
|
<function>SPI_freeplan</function> releases a prepared statement
|
|
previously returned by <function>SPI_prepare</function> or saved by
|
|
<function>SPI_keepplan</function> or <function>SPI_saveplan</function>.
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Arguments</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>SPIPlanPtr <parameter>plan</parameter></literal></term>
|
|
<listitem>
|
|
<para>
|
|
pointer to statement to free
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Return Value</title>
|
|
|
|
<para>
|
|
0 on success;
|
|
<symbol>SPI_ERROR_ARGUMENT</symbol> if <parameter>plan</parameter>
|
|
is <symbol>NULL</symbol> or invalid
|
|
</para>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="spi-visibility">
|
|
<title>Visibility of Data Changes</title>
|
|
|
|
<para>
|
|
The following rules govern the visibility of data changes in
|
|
functions that use SPI (or any other C function):
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
During the execution of an SQL command, any data changes made by
|
|
the command are invisible to the command itself. For
|
|
example, in:
|
|
<programlisting>
|
|
INSERT INTO a SELECT * FROM a;
|
|
</programlisting>
|
|
the inserted rows are invisible to the <command>SELECT</command>
|
|
part.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Changes made by a command C are visible to all commands that are
|
|
started after C, no matter whether they are started inside C
|
|
(during the execution of C) or after C is done.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Commands executed via SPI inside a function called by an SQL command
|
|
(either an ordinary function or a trigger) follow one or the
|
|
other of the above rules depending on the read/write flag passed
|
|
to SPI. Commands executed in read-only mode follow the first
|
|
rule: they cannot see changes of the calling command. Commands executed
|
|
in read-write mode follow the second rule: they can see all changes made
|
|
so far.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
All standard procedural languages set the SPI read-write mode
|
|
depending on the volatility attribute of the function. Commands of
|
|
<literal>STABLE</> and <literal>IMMUTABLE</> functions are done in
|
|
read-only mode, while commands of <literal>VOLATILE</> functions are
|
|
done in read-write mode. While authors of C functions are able to
|
|
violate this convention, it's unlikely to be a good idea to do so.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
|
|
<para>
|
|
The next section contains an example that illustrates the
|
|
application of these rules.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="spi-examples">
|
|
<title>Examples</title>
|
|
|
|
<para>
|
|
This section contains a very simple example of SPI usage. The
|
|
procedure <function>execq</function> takes an SQL command as its
|
|
first argument and a row count as its second, executes the command
|
|
using <function>SPI_exec</function> and returns the number of rows
|
|
that were processed by the command. You can find more complex
|
|
examples for SPI in the source tree in
|
|
<filename>src/test/regress/regress.c</filename> and in the
|
|
<xref linkend="contrib-spi"> module.
|
|
</para>
|
|
|
|
<programlisting>
|
|
#include "postgres.h"
|
|
|
|
#include "executor/spi.h"
|
|
#include "utils/builtins.h"
|
|
|
|
#ifdef PG_MODULE_MAGIC
|
|
PG_MODULE_MAGIC;
|
|
#endif
|
|
|
|
int execq(text *sql, int cnt);
|
|
|
|
int
|
|
execq(text *sql, int cnt)
|
|
{
|
|
char *command;
|
|
int ret;
|
|
int proc;
|
|
|
|
/* Convert given text object to a C string */
|
|
command = text_to_cstring(sql);
|
|
|
|
SPI_connect();
|
|
|
|
ret = SPI_exec(command, cnt);
|
|
|
|
proc = SPI_processed;
|
|
/*
|
|
* If some rows were fetched, print them via elog(INFO).
|
|
*/
|
|
if (ret > 0 && SPI_tuptable != NULL)
|
|
{
|
|
TupleDesc tupdesc = SPI_tuptable->tupdesc;
|
|
SPITupleTable *tuptable = SPI_tuptable;
|
|
char buf[8192];
|
|
int i, j;
|
|
|
|
for (j = 0; j < proc; j++)
|
|
{
|
|
HeapTuple tuple = tuptable->vals[j];
|
|
|
|
for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++)
|
|
snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s",
|
|
SPI_getvalue(tuple, tupdesc, i),
|
|
(i == tupdesc->natts) ? " " : " |");
|
|
elog(INFO, "EXECQ: %s", buf);
|
|
}
|
|
}
|
|
|
|
SPI_finish();
|
|
pfree(command);
|
|
|
|
return (proc);
|
|
}
|
|
</programlisting>
|
|
|
|
<para>
|
|
(This function uses call convention version 0, to make the example
|
|
easier to understand. In real applications you should use the new
|
|
version 1 interface.)
|
|
</para>
|
|
|
|
<para>
|
|
This is how you declare the function after having compiled it into
|
|
a shared library (details are in <xref linkend="dfunc">.):
|
|
|
|
<programlisting>
|
|
CREATE FUNCTION execq(text, integer) RETURNS integer
|
|
AS '<replaceable>filename</replaceable>'
|
|
LANGUAGE C;
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Here is a sample session:
|
|
|
|
<programlisting>
|
|
=> SELECT execq('CREATE TABLE a (x integer)', 0);
|
|
execq
|
|
-------
|
|
0
|
|
(1 row)
|
|
|
|
=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0));
|
|
INSERT 0 1
|
|
=> SELECT execq('SELECT * FROM a', 0);
|
|
INFO: EXECQ: 0 -- inserted by execq
|
|
INFO: EXECQ: 1 -- returned by execq and inserted by upper INSERT
|
|
|
|
execq
|
|
-------
|
|
2
|
|
(1 row)
|
|
|
|
=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a', 1);
|
|
execq
|
|
-------
|
|
1
|
|
(1 row)
|
|
|
|
=> SELECT execq('SELECT * FROM a', 10);
|
|
INFO: EXECQ: 0
|
|
INFO: EXECQ: 1
|
|
INFO: EXECQ: 2 -- 0 + 2, only one row inserted - as specified
|
|
|
|
execq
|
|
-------
|
|
3 -- 10 is the max value only, 3 is the real number of rows
|
|
(1 row)
|
|
|
|
=> DELETE FROM a;
|
|
DELETE 3
|
|
=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
|
|
INSERT 0 1
|
|
=> SELECT * FROM a;
|
|
x
|
|
---
|
|
1 -- no rows in a (0) + 1
|
|
(1 row)
|
|
|
|
=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1);
|
|
INFO: EXECQ: 1
|
|
INSERT 0 1
|
|
=> SELECT * FROM a;
|
|
x
|
|
---
|
|
1
|
|
2 -- there was one row in a + 1
|
|
(2 rows)
|
|
|
|
-- This demonstrates the data changes visibility rule:
|
|
|
|
=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a;
|
|
INFO: EXECQ: 1
|
|
INFO: EXECQ: 2
|
|
INFO: EXECQ: 1
|
|
INFO: EXECQ: 2
|
|
INFO: EXECQ: 2
|
|
INSERT 0 2
|
|
=> SELECT * FROM a;
|
|
x
|
|
---
|
|
1
|
|
2
|
|
2 -- 2 rows * 1 (x in first row)
|
|
6 -- 3 rows (2 + 1 just inserted) * 2 (x in second row)
|
|
(4 rows) ^^^^^^
|
|
rows visible to execq() in different invocations
|
|
</programlisting>
|
|
</para>
|
|
</sect1>
|
|
</chapter>
|