diff options
Diffstat (limited to '')
-rw-r--r-- | doc/src/sgml/spi.sgml | 5413 |
1 files changed, 5413 insertions, 0 deletions
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml new file mode 100644 index 0000000..47f4b5b --- /dev/null +++ b/doc/src/sgml/spi.sgml @@ -0,0 +1,5413 @@ +<!-- 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 or procedures. + <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 functions. 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> + Note that if a command invoked via SPI fails, then control will not be + returned to your C function. Rather, the + transaction or subtransaction in which your C function 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. + </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"> + <indexterm><primary>SPI_connect</primary></indexterm> + <indexterm><primary>SPI_connect_ext</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_connect</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_connect</refname> + <refname>SPI_connect_ext</refname> + <refpurpose>connect a C function to the SPI manager</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +int SPI_connect(void) +</synopsis> + + <synopsis> +int SPI_connect_ext(int <parameter>options</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_connect</function> opens a connection from a + C function 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 C functions. + </para> + + <para> + <function>SPI_connect_ext</function> does the same but has an argument that + allows passing option flags. Currently, the following option values are + available: + <variablelist> + <varlistentry> + <term><symbol>SPI_OPT_NONATOMIC</symbol></term> + <listitem> + <para> + Sets the SPI connection to be <firstterm>nonatomic</firstterm>, which + means that transaction control calls (<function>SPI_commit</function>, + <function>SPI_rollback</function>) are allowed. Otherwise, + calling those functions will result in an immediate error. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + <literal>SPI_connect()</literal> is equivalent to + <literal>SPI_connect_ext(0)</literal>. + </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"> + <indexterm><primary>SPI_finish</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_finish</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_finish</refname> + <refpurpose>disconnect a C function from the SPI manager</refpurpose> + </refnamediv> + + <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 C function'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> + </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 C function + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-execute"> + <indexterm><primary>SPI_execute</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_execute</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_execute</refname> + <refpurpose>execute a command</refpurpose> + </refnamediv> + + <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</literal>, the command must be read-only, and execution overhead + is somewhat reduced. + </para> + + <para> + This function can only be called from a connected C function. + </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</structname>, 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</literal> 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</literal>, + <function>SPI_execute</function> increments the command + counter and computes a new <firstterm>snapshot</firstterm> before executing each + command in the string. The snapshot does not actually change if the + current transaction isolation level is <literal>SERIALIZABLE</literal> or <literal>REPEATABLE READ</literal>, but in + <literal>READ COMMITTED</literal> 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</literal>, + <function>SPI_execute</function> does not update either the snapshot + or the command counter, and it allows only plain <command>SELECT</command> + 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</firstterm> 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</command>) also return row sets, and <literal>SPI_tuptable</literal> + will contain the result in these cases too. Some utility commands + (<command>COPY</command>, <command>CREATE TABLE AS</command>) don't return a row set, so + <literal>SPI_tuptable</literal> is NULL, but they still return the number of + rows processed in <varname>SPI_processed</varname>. + </para> + + <para> + The structure <structname>SPITupleTable</structname> is defined + thus: +<programlisting> +typedef struct SPITupleTable +{ + /* Public members */ + TupleDesc tupdesc; /* tuple descriptor */ + HeapTuple *vals; /* array of tuples */ + uint64 numvals; /* number of valid tuples */ + + /* Private members, not intended for external callers */ + uint64 alloced; /* allocated length of vals array */ + MemoryContext tuptabcxt; /* memory context of result table */ + slist_node next; /* link for internal bookkeeping */ + SubTransactionId subid; /* subxact in which tuptable was created */ +} SPITupleTable; +</programlisting> + The fields <structfield>tupdesc</structfield>, + <structfield>vals</structfield>, and + <structfield>numvals</structfield> + can be used by SPI callers; the remaining fields are internal. + <structfield>vals</structfield> is an array of pointers to rows. + The number of rows is given by <structfield>numvals</structfield> + (for somewhat historical reasons, this count is also returned + in <varname>SPI_processed</varname>). + <structfield>tupdesc</structfield> is a row descriptor which you can pass to + SPI functions dealing with rows. + </para> + + <para> + <function>SPI_finish</function> frees all + <structname>SPITupleTable</structname>s allocated during the current + C function. 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</literal> 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</literal> 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</command>) 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_MERGE</symbol></term> + <listitem> + <para> + if a <command>MERGE</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</command> or <command>COPY FROM stdin</command> + 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>, + <command>COMMIT</command>, + <command>ROLLBACK</command>, + <command>SAVEPOINT</command>, + <command>PREPARE TRANSACTION</command>, + <command>COMMIT PREPARED</command>, + <command>ROLLBACK PREPARED</command>, + 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 C function + </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 + C function 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"> + <indexterm><primary>SPI_exec</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_exec</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_exec</refname> + <refpurpose>execute a read/write command</refpurpose> + </refnamediv> + + <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</literal>. + </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</literal> 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-extended"> + <indexterm><primary>SPI_execute_extended</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_execute_extended</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_execute_extended</refname> + <refpurpose>execute a command with out-of-line parameters</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +int SPI_execute_extended(const char *<parameter>command</parameter>, + const SPIExecuteOptions * <parameter>options</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_execute_extended</function> executes a command that might + include references to externally supplied parameters. The command text + refers to a parameter as <literal>$<replaceable>n</replaceable></literal>, + and the <parameter>options->params</parameter> object (if supplied) + provides values and type information for each such symbol. + Various execution options can be specified + in the <parameter>options</parameter> struct, too. + </para> + + <para> + The <parameter>options->params</parameter> object should normally + mark each parameter with the <literal>PARAM_FLAG_CONST</literal> flag, + since a one-shot plan is always used for the query. + </para> + + <para> + If <parameter>options->dest</parameter> is not NULL, then result + tuples are passed to that object as they are generated by the executor, + instead of being accumulated in <varname>SPI_tuptable</varname>. Using + a caller-supplied <literal>DestReceiver</literal> object is particularly + helpful for queries that might generate many tuples, since the data can + be processed on-the-fly instead of being accumulated in memory. + </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>const SPIExecuteOptions * <parameter>options</parameter></literal></term> + <listitem> + <para> + struct containing optional arguments + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Callers should always zero out the entire <parameter>options</parameter> + struct, then fill whichever fields they want to set. This ensures forward + compatibility of code, since any fields that are added to the struct in + future will be defined to behave backwards-compatibly if they are zero. + The currently available <parameter>options</parameter> fields are: + </para> + + <variablelist> + <varlistentry> + <term><literal>ParamListInfo <parameter>params</parameter></literal></term> + <listitem> + <para> + data structure containing query parameter types and values; NULL if none + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> for read-only execution</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>allow_nonatomic</parameter></literal></term> + <listitem> + <para> + <literal>true</literal> allows non-atomic execution of CALL and DO + statements + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>must_return_tuples</parameter></literal></term> + <listitem> + <para> + if <literal>true</literal>, raise error if the query is not of a kind + that returns tuples (this does not forbid the case where it happens to + return zero tuples) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>uint64 <parameter>tcount</parameter></literal></term> + <listitem> + <para> + maximum number of rows to return, + or <literal>0</literal> for no limit + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DestReceiver * <parameter>dest</parameter></literal></term> + <listitem> + <para> + <literal>DestReceiver</literal> object that will receive any tuples + emitted by the query; if NULL, result tuples are accumulated into + a <varname>SPI_tuptable</varname> structure, as + in <function>SPI_execute</function> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>ResourceOwner <parameter>owner</parameter></literal></term> + <listitem> + <para> + This field is present for consistency + with <function>SPI_execute_plan_extended</function>, but it is + ignored, since the plan used + by <function>SPI_execute_extended</function> is never saved. + </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> + When <parameter>options->dest</parameter> is NULL, + <varname>SPI_processed</varname> and + <varname>SPI_tuptable</varname> are set as in + <function>SPI_execute</function>. + When <parameter>options->dest</parameter> is not NULL, + <varname>SPI_processed</varname> is set to zero and + <varname>SPI_tuptable</varname> is set to NULL. If a tuple count + is required, the caller's <literal>DestReceiver</literal> object must + calculate it. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-execute-with-args"> + <indexterm><primary>SPI_execute_with_args</primary></indexterm> + + <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> + + <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</replaceable></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</function> 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>, <literal>$2</literal>, etc.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Oid * <parameter>argtypes</parameter></literal></term> + <listitem> + <para> + an array of length <parameter>nargs</parameter>, 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 length <parameter>nargs</parameter>, containing the actual + parameter values + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char * <parameter>nulls</parameter></literal></term> + <listitem> + <para> + an array of length <parameter>nargs</parameter>, 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. Otherwise, each entry of the <parameter>nulls</parameter> + array should be <literal>' '</literal> if the corresponding parameter + value is non-null, or <literal>'n'</literal> if the corresponding parameter + value is null. (In the latter case, the actual value in the + corresponding <parameter>values</parameter> entry doesn't matter.) Note + that <parameter>nulls</parameter> is not a text string, just an array: + it does not need a <literal>'\0'</literal> terminator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> 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</literal> 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"> + <indexterm><primary>SPI_prepare</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_prepare</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_prepare</refname> + <refpurpose>prepare a statement, without executing it yet</refpurpose> + </refnamediv> + + <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>, <literal>$2</literal>, 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 C function, 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>, <literal>$2</literal>, 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</type>, 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</parameter> is less than 0, or if <parameter>nargs</parameter> is + greater than 0 and <parameter>argtypes</parameter> 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</literal> or + <literal>CURSOR_OPT_CUSTOM_PLAN</literal> 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</productname> 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</varname>. (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 C function. + </para> + + <para> + <type>SPIPlanPtr</type> is declared as a pointer to an opaque struct type in + <filename>spi.h</filename>. 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</type> is somewhat historical, since the data + structure no longer necessarily contains an execution plan. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-prepare-cursor"> + <indexterm><primary>SPI_prepare_cursor</primary></indexterm> + + <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> + + <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</quote> parameter. This is a bit mask + having the values shown in <filename>nodes/parsenodes.h</filename> + for the <structfield>options</structfield> field of <structname>DeclareCursorStmt</structname>. + <function>SPI_prepare</function> always takes the cursor options as zero. + </para> + + <para> + This function is now deprecated in favor + of <function>SPI_prepare_extended</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>, <literal>$2</literal>, 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</parameter> 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-extended"> + <indexterm><primary>SPI_prepare_extended</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_prepare_extended</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_prepare_extended</refname> + <refpurpose>prepare a statement, without executing it yet</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +SPIPlanPtr SPI_prepare_extended(const char * <parameter>command</parameter>, + const SPIPrepareOptions * <parameter>options</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_prepare_extended</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</function>, + with the addition that the caller can specify options to control + the parsing of external parameter references, as well as other facets + of query parsing and planning. + </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>const SPIPrepareOptions * <parameter>options</parameter></literal></term> + <listitem> + <para> + struct containing optional arguments + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Callers should always zero out the entire <parameter>options</parameter> + struct, then fill whichever fields they want to set. This ensures forward + compatibility of code, since any fields that are added to the struct in + future will be defined to behave backwards-compatibly if they are zero. + The currently available <parameter>options</parameter> fields are: + </para> + + <variablelist> + <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> + pass-through argument for <parameter>parserSetup</parameter> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>RawParseMode <parameter>parseMode</parameter></literal></term> + <listitem> + <para> + mode for raw parsing; <literal>RAW_PARSE_DEFAULT</literal> (zero) + produces default behavior + </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_extended</function> has the same return conventions as + <function>SPI_prepare</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-prepare-params"> + <indexterm><primary>SPI_prepare_params</primary></indexterm> + + <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> + + <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> + + <para> + This function is now deprecated in favor + of <function>SPI_prepare_extended</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>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> + pass-through 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"> + <indexterm><primary>SPI_getargcount</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_getargtypeid</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_is_cursor_plan</primary></indexterm> + + <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> + + <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</command> + is allowed unless it contains an <literal>INTO</literal> clause, and + <command>UPDATE</command> is allowed only if it contains a <literal>RETURNING</literal> + 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"> + <indexterm><primary>SPI_execute_plan</primary></indexterm> + + <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> + + <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. + </para> + + <para> + If <parameter>nulls</parameter> is <symbol>NULL</symbol> then + <function>SPI_execute_plan</function> assumes that no parameters + are null. Otherwise, each entry of the <parameter>nulls</parameter> + array should be <literal>' '</literal> if the corresponding parameter + value is non-null, or <literal>'n'</literal> if the corresponding parameter + value is null. (In the latter case, the actual value in the + corresponding <parameter>values</parameter> entry doesn't matter.) Note + that <parameter>nulls</parameter> is not a text string, just an array: + it does not need a <literal>'\0'</literal> terminator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> 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</literal> 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-extended"> + <indexterm><primary>SPI_execute_plan_extended</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_execute_plan_extended</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_execute_plan_extended</refname> + <refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +int SPI_execute_plan_extended(SPIPlanPtr <parameter>plan</parameter>, + const SPIExecuteOptions * <parameter>options</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_execute_plan_extended</function> executes a statement + prepared by <function>SPI_prepare</function> or one of its siblings. + 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, and additional execution-controlling + options can be passed. + </para> + + <para> + Query parameter values are represented by + a <literal>ParamListInfo</literal> struct, which is convenient for passing + down values that are already available in that format. Dynamic parameter + sets can also be used, via hook functions specified + in <literal>ParamListInfo</literal>. + </para> + + <para> + Also, instead of always accumulating the result tuples into a + <varname>SPI_tuptable</varname> structure, tuples can be passed to a + caller-supplied <literal>DestReceiver</literal> object as they are + generated by the executor. This is particularly helpful for queries + that might generate many tuples, since the data can be processed + on-the-fly instead of being accumulated in memory. + </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>const SPIExecuteOptions * <parameter>options</parameter></literal></term> + <listitem> + <para> + struct containing optional arguments + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Callers should always zero out the entire <parameter>options</parameter> + struct, then fill whichever fields they want to set. This ensures forward + compatibility of code, since any fields that are added to the struct in + future will be defined to behave backwards-compatibly if they are zero. + The currently available <parameter>options</parameter> fields are: + </para> + + <variablelist> + <varlistentry> + <term><literal>ParamListInfo <parameter>params</parameter></literal></term> + <listitem> + <para> + data structure containing query parameter types and values; NULL if none + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> for read-only execution</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>allow_nonatomic</parameter></literal></term> + <listitem> + <para> + <literal>true</literal> allows non-atomic execution of CALL and DO + statements + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>must_return_tuples</parameter></literal></term> + <listitem> + <para> + if <literal>true</literal>, raise error if the query is not of a kind + that returns tuples (this does not forbid the case where it happens to + return zero tuples) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>uint64 <parameter>tcount</parameter></literal></term> + <listitem> + <para> + maximum number of rows to return, + or <literal>0</literal> for no limit + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DestReceiver * <parameter>dest</parameter></literal></term> + <listitem> + <para> + <literal>DestReceiver</literal> object that will receive any tuples + emitted by the query; if NULL, result tuples are accumulated into + a <varname>SPI_tuptable</varname> structure, as + in <function>SPI_execute_plan</function> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>ResourceOwner <parameter>owner</parameter></literal></term> + <listitem> + <para> + The resource owner that will hold a reference count on the plan while + it is executed. If NULL, CurrentResourceOwner is used. Ignored for + non-saved plans, as SPI does not acquire reference counts on those. + </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> + When <parameter>options->dest</parameter> is NULL, + <varname>SPI_processed</varname> and + <varname>SPI_tuptable</varname> are set as in + <function>SPI_execute_plan</function>. + When <parameter>options->dest</parameter> is not NULL, + <varname>SPI_processed</varname> is set to zero and + <varname>SPI_tuptable</varname> is set to NULL. If a tuple count + is required, the caller's <literal>DestReceiver</literal> object must + calculate it. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-execute-plan-with-paramlist"> + <indexterm><primary>SPI_execute_plan_with_paramlist</primary></indexterm> + + <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> + + <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</literal> + 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</literal>. + </para> + + <para> + This function is now deprecated in favor + of <function>SPI_execute_plan_extended</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>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</literal> 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</literal> 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"> + <indexterm><primary>SPI_execp</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_execp</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_execp</refname> + <refpurpose>execute a statement in read/write mode</refpurpose> + </refnamediv> + + <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</literal>. + </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. + </para> + + <para> + If <parameter>nulls</parameter> is <symbol>NULL</symbol> then + <function>SPI_execp</function> assumes that no parameters + are null. Otherwise, each entry of the <parameter>nulls</parameter> + array should be <literal>' '</literal> if the corresponding parameter + value is non-null, or <literal>'n'</literal> if the corresponding parameter + value is null. (In the latter case, the actual value in the + corresponding <parameter>values</parameter> entry doesn't matter.) Note + that <parameter>nulls</parameter> is not a text string, just an array: + it does not need a <literal>'\0'</literal> terminator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>long <parameter>count</parameter></literal></term> + <listitem> + <para> + maximum number of rows to return, + or <literal>0</literal> 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"> + <indexterm><primary>SPI_cursor_open</primary></indexterm> + + <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> + + <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 C function (it can, in fact, live + to the end of the current transaction). Returning the portal name + to the C function'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. + </para> + + <para> + If <parameter>nulls</parameter> is <symbol>NULL</symbol> then + <function>SPI_cursor_open</function> assumes that no parameters + are null. Otherwise, each entry of the <parameter>nulls</parameter> + array should be <literal>' '</literal> if the corresponding parameter + value is non-null, or <literal>'n'</literal> if the corresponding parameter + value is null. (In the latter case, the actual value in the + corresponding <parameter>values</parameter> entry doesn't matter.) Note + that <parameter>nulls</parameter> is not a text string, just an array: + it does not need a <literal>'\0'</literal> terminator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> 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</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-open-with-args"> + <indexterm><primary>SPI_cursor_open_with_args</primary></indexterm> + + <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> + + <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> + + <para> + This function is now deprecated in favor + of <function>SPI_cursor_parse_open</function>, which provides equivalent + functionality using a more modern API for handling query parameters. + </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>, <literal>$2</literal>, etc.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Oid * <parameter>argtypes</parameter></literal></term> + <listitem> + <para> + an array of length <parameter>nargs</parameter>, 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 length <parameter>nargs</parameter>, containing the actual + parameter values + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char * <parameter>nulls</parameter></literal></term> + <listitem> + <para> + an array of length <parameter>nargs</parameter>, 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. Otherwise, each entry of the <parameter>nulls</parameter> + array should be <literal>' '</literal> if the corresponding parameter + value is non-null, or <literal>'n'</literal> if the corresponding parameter + value is null. (In the latter case, the actual value in the + corresponding <parameter>values</parameter> entry doesn't matter.) Note + that <parameter>nulls</parameter> is not a text string, just an array: + it does not need a <literal>'\0'</literal> terminator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> 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</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-open-with-paramlist"> + <indexterm><primary>SPI_cursor_open_with_paramlist</primary></indexterm> + + <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> + + <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</literal> + 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</literal>. + </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</literal> 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</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-parse-open"> + <indexterm><primary>SPI_cursor_parse_open</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_cursor_parse_open</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_parse_open</refname> + <refpurpose>set up a cursor using a query string and parameters</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +Portal SPI_cursor_parse_open(const char *<parameter>name</parameter>, + const char *<parameter>command</parameter>, + const SPIParseOpenOptions * <parameter>options</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_cursor_parse_open</function> sets up a cursor + (internally, a portal) that will execute the specified query string. + This is comparable to <function>SPI_prepare_cursor</function> followed + by <function>SPI_cursor_open_with_paramlist</function>, except that + parameter references within the query string are handled entirely by + supplying a <literal>ParamListInfo</literal> object. + </para> + + <para> + For one-time query execution, this function should be preferred + over <function>SPI_prepare_cursor</function> followed by + <function>SPI_cursor_open_with_paramlist</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 <parameter>options->params</parameter> object should normally + mark each parameter with the <literal>PARAM_FLAG_CONST</literal> flag, + since a one-shot plan is always used for the query. + </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>const SPIParseOpenOptions * <parameter>options</parameter></literal></term> + <listitem> + <para> + struct containing optional arguments + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Callers should always zero out the entire <parameter>options</parameter> + struct, then fill whichever fields they want to set. This ensures forward + compatibility of code, since any fields that are added to the struct in + future will be defined to behave backwards-compatibly if they are zero. + The currently available <parameter>options</parameter> fields are: + </para> + + <variablelist> + <varlistentry> + <term><literal>ParamListInfo <parameter>params</parameter></literal></term> + <listitem> + <para> + data structure containing query parameter types and values; NULL if none + </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> + + <varlistentry> + <term><literal>bool <parameter>read_only</parameter></literal></term> + <listitem> + <para><literal>true</literal> 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</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-find"> + <indexterm><primary>SPI_cursor_find</primary></indexterm> + + <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> + + <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> + + <refsect1> + <title>Notes</title> + + <para> + Beware that this function can return a <type>Portal</type> object + that does not have cursor-like properties; for example it might not + return tuples. If you simply pass the <type>Portal</type> pointer + to other SPI functions, they can defend themselves against such + cases, but caution is appropriate when directly inspecting + the <type>Portal</type>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-cursor-fetch"> + <indexterm><primary>SPI_cursor_fetch</primary></indexterm> + + <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> + + <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</command> (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"> + <indexterm><primary>SPI_cursor_move</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_cursor_move</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_move</refname> + <refpurpose>move a cursor</refpurpose> + </refnamediv> + + <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</command> (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"> + <indexterm><primary>SPI_scroll_cursor_fetch</primary></indexterm> + + <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> + + <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</command>. + </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"> + <indexterm><primary>SPI_scroll_cursor_move</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_scroll_cursor_move</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_scroll_cursor_move</refname> + <refpurpose>move a cursor</refpurpose> + </refnamediv> + + <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</command>. + </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</symbol>, 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"> + <indexterm><primary>SPI_cursor_close</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_cursor_close</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_cursor_close</refname> + <refpurpose>close a cursor</refpurpose> + </refnamediv> + + <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"> + <indexterm><primary>SPI_keepplan</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_keepplan</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_keepplan</refname> + <refpurpose>save a prepared statement</refpurpose> + </refnamediv> + + <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 C function 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"> + <indexterm><primary>SPI_saveplan</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_saveplan</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_saveplan</refname> + <refpurpose>save a prepared statement</refpurpose> + </refnamediv> + + <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 C function 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 C function + </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</function>. + </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> + +<!-- *********************************************** --> + +<refentry id="spi-spi-register-relation"> + <indexterm><primary>SPI_register_relation</primary></indexterm> + + <indexterm> + <primary>ephemeral named relation</primary> + <secondary>registering with SPI</secondary> + </indexterm> + + <refmeta> + <refentrytitle>SPI_register_relation</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_register_relation</refname> + <refpurpose>make an ephemeral named relation available by name in SPI queries</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +int SPI_register_relation(EphemeralNamedRelation <parameter>enr</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_register_relation</function> makes an ephemeral named + relation, with associated information, available to queries planned and + executed through the current SPI connection. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>EphemeralNamedRelation <parameter>enr</parameter></literal></term> + <listitem> + <para> + the ephemeral named relation registry entry + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + If the execution of the command was successful then the following + (nonnegative) value will be returned: + + <variablelist> + <varlistentry> + <term><symbol>SPI_OK_REL_REGISTER</symbol></term> + <listitem> + <para> + if the relation has been successfully registered by name + </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>enr</parameter> is <symbol>NULL</symbol> or its + <varname>name</varname> field is <symbol>NULL</symbol> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if called from an unconnected C function + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_REL_DUPLICATE</symbol></term> + <listitem> + <para> + if the name specified in the <varname>name</varname> field of + <parameter>enr</parameter> is already registered for this connection + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-unregister-relation"> + <indexterm><primary>SPI_unregister_relation</primary></indexterm> + + <indexterm> + <primary>ephemeral named relation</primary> + <secondary>unregistering from SPI</secondary> + </indexterm> + + <refmeta> + <refentrytitle>SPI_unregister_relation</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_unregister_relation</refname> + <refpurpose>remove an ephemeral named relation from the registry</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +int SPI_unregister_relation(const char * <parameter>name</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_unregister_relation</function> removes an ephemeral named + relation from the registry for the current connection. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>const char * <parameter>name</parameter></literal></term> + <listitem> + <para> + the relation registry entry name + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + If the execution of the command was successful then the following + (nonnegative) value will be returned: + + <variablelist> + <varlistentry> + <term><symbol>SPI_OK_REL_UNREGISTER</symbol></term> + <listitem> + <para> + if the tuplestore has been successfully removed from the registry + </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>name</parameter> is <symbol>NULL</symbol> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if called from an unconnected C function + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_REL_NOT_FOUND</symbol></term> + <listitem> + <para> + if <parameter>name</parameter> is not found in the registry for the + current connection + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-register-trigger-data"> + <indexterm><primary>SPI_register_trigger_data</primary></indexterm> + + <indexterm> + <primary>ephemeral named relation</primary> + <secondary>registering with SPI</secondary> + </indexterm> + + <indexterm> + <primary>transition tables</primary> + <secondary>implementation in PLs</secondary> + </indexterm> + + <refmeta> + <refentrytitle>SPI_register_trigger_data</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_register_trigger_data</refname> + <refpurpose>make ephemeral trigger data available in SPI queries</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +int SPI_register_trigger_data(TriggerData *<parameter>tdata</parameter>) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_register_trigger_data</function> makes any ephemeral + relations captured by a trigger available to queries planned and executed + through the current SPI connection. Currently, this means the transition + tables captured by an <literal>AFTER</literal> trigger defined with a + <literal>REFERENCING OLD/NEW TABLE AS</literal> ... clause. This function + should be called by a PL trigger handler function after connecting. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>TriggerData *<parameter>tdata</parameter></literal></term> + <listitem> + <para> + the <structname>TriggerData</structname> object passed to a trigger + handler function as <literal>fcinfo->context</literal> + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + If the execution of the command was successful then the following + (nonnegative) value will be returned: + + <variablelist> + <varlistentry> + <term><symbol>SPI_OK_TD_REGISTER</symbol></term> + <listitem> + <para> + if the captured trigger data (if any) has been successfully registered + </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>tdata</parameter> is <symbol>NULL</symbol> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if called from an unconnected C function + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_REL_DUPLICATE</symbol></term> + <listitem> + <para> + if the name of any trigger data transient relation is already + registered for this connection + </para> + </listitem> + </varlistentry> + </variablelist> + </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</function> and + other SPI functions. + </para> + + <para> + All functions described in this section can be used by both + connected and unconnected C functions. + </para> + +<!-- *********************************************** --> + +<refentry id="spi-spi-fname"> + <indexterm><primary>SPI_fname</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_fnumber</primary></indexterm> + + <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> + + <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>ctid</literal>) 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 for user-defined columns), or + <symbol>SPI_ERROR_NOATTRIBUTE</symbol> if the named column was not + found. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-getvalue"> + <indexterm><primary>SPI_getvalue</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_getbinval</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_gettype</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_gettypeid</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_getrelname</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_getrelname</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_getrelname</refname> + <refpurpose>return the name of the specified relation</refpurpose> + </refnamediv> + + <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"> + <indexterm><primary>SPI_getnspname</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_getnspname</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_getnspname</refname> + <refpurpose>return the namespace of the specified relation</refpurpose> + </refnamediv> + + <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> + +<refentry id="spi-spi-result-code-string"> + <indexterm><primary>SPI_result_code_string</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_result_code_string</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_result_code_string</refname> + <refpurpose>return error code as string</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +const char * SPI_result_code_string(int <parameter>code</parameter>); +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_result_code_string</function> returns a string representation + of the result code returned by various SPI functions or stored + in <varname>SPI_result</varname>. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>int <parameter>code</parameter></literal></term> + <listitem> + <para> + result code + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + A string representation of the result code. + </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</quote> 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 C function are + reclaimed at C function exit, avoiding memory leakage. + </para> + + <para> + However, if your C function 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 + C function 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 + C function. Several of the other utility functions described in + this section also return objects created in the upper executor context. + </para> + + <para> + When <function>SPI_connect</function> is called, the private + context of the C function, 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 as + described in this section) are made in this context. When a + C function 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 + C function memory context are freed and cannot be used any more. + </para> + +<!-- *********************************************** --> + +<refentry id="spi-spi-palloc"> + <indexterm><primary>SPI_palloc</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_palloc</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_palloc</refname> + <refpurpose>allocate memory in the upper executor context</refpurpose> + </refnamediv> + + <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> + + <para> + This function can only be used while connected to SPI. + Otherwise, it throws an error. + </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"> + <indexterm><primary>SPI_repalloc</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_repalloc</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_repalloc</refname> + <refpurpose>reallocate memory in the upper executor context</refpurpose> + </refnamediv> + + <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"> + <indexterm><primary>SPI_pfree</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_pfree</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_pfree</refname> + <refpurpose>free memory in the upper executor context</refpurpose> + </refnamediv> + + <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"> + <indexterm><primary>SPI_copytuple</primary></indexterm> + + <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> + + <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> + + <para> + This function can only be used while connected to SPI. + Otherwise, it returns NULL and sets <varname>SPI_result</varname> to + <symbol>SPI_ERROR_UNCONNECTED</symbol>. + </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, or <symbol>NULL</symbol> on error + (see <varname>SPI_result</varname> for an error indication) + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-returntuple"> + <indexterm><primary>SPI_returntuple</primary></indexterm> + + <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> + + <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> + This function can only be used while connected to SPI. + Otherwise, it returns NULL and sets <varname>SPI_result</varname> to + <symbol>SPI_ERROR_UNCONNECTED</symbol>. + </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</function> 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, + or <symbol>NULL</symbol> on error + (see <varname>SPI_result</varname> for an error indication) + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-modifytuple"> + <indexterm><primary>SPI_modifytuple</primary></indexterm> + + <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> + + <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. + The new row is returned in the upper executor context. + </para> + + <para> + This function can only be used while connected to SPI. + Otherwise, it returns NULL and sets <varname>SPI_result</varname> to + <symbol>SPI_ERROR_UNCONNECTED</symbol>. + </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 columns to be changed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int * <parameter>colnum</parameter></literal></term> + <listitem> + <para> + an array of length <parameter>ncols</parameter>, containing 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> + an array of length <parameter>ncols</parameter>, containing the + new values for the specified columns + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>const char * <parameter>nulls</parameter></literal></term> + <listitem> + <para> + an array of length <parameter>ncols</parameter>, describing which + new values are null + </para> + + <para> + If <parameter>nulls</parameter> is <symbol>NULL</symbol> then + <function>SPI_modifytuple</function> assumes that no new values + are null. Otherwise, each entry of the <parameter>nulls</parameter> + array should be <literal>' '</literal> if the corresponding new value is + non-null, or <literal>'n'</literal> if the corresponding new value is + null. (In the latter case, the actual value in the corresponding + <parameter>values</parameter> entry doesn't matter.) Note that + <parameter>nulls</parameter> is not a text string, just an array: it + does not need a <literal>'\0'</literal> terminator. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Return Value</title> + + <para> + new row with modifications, allocated in the upper executor + context, or <symbol>NULL</symbol> on error + (see <varname>SPI_result</varname> for an error indication) + </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</parameter> is <symbol>NULL</symbol>, or if + <parameter>row</parameter> is <symbol>NULL</symbol>, or if <parameter>ncols</parameter> + is less than or equal to 0, or if <parameter>colnum</parameter> is + <symbol>NULL</symbol>, or if <parameter>values</parameter> is <symbol>NULL</symbol>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_NOATTRIBUTE</symbol></term> + <listitem> + <para> + if <parameter>colnum</parameter> contains an invalid column number (less + than or equal to 0 or greater than the number of columns in + <parameter>row</parameter>) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term> + <listitem> + <para> + if SPI is not active + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-freetuple"> + <indexterm><primary>SPI_freetuple</primary></indexterm> + + <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> + + <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"> + <indexterm><primary>SPI_freetuptable</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_freetuptable</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_freetuptable</refname> + <refpurpose>free a row set created by <function>SPI_execute</function> or a similar + function</refpurpose> + </refnamediv> + + <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</function>. Therefore, this function is often called + with the global variable <varname>SPI_tuptable</varname> as + argument. + </para> + + <para> + This function is useful if an SPI-using C function 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</function>. + Also, if a subtransaction is started and then aborted within execution + of an SPI-using C function, SPI automatically frees any row sets created while + the subtransaction was running. + </para> + + <para> + Beginning in <productname>PostgreSQL</productname> 9.3, + <function>SPI_freetuptable</function> contains guard logic to protect + against duplicate deletion requests for the same row set. In previous + releases, duplicate deletions would lead to crashes. + </para> + </refsect1> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><literal>SPITupleTable * <parameter>tuptable</parameter></literal></term> + <listitem> + <para> + pointer to row set to free, or NULL to do nothing + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-freeplan"> + <indexterm><primary>SPI_freeplan</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_freeplan</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_freeplan</refname> + <refpurpose>free a previously saved prepared statement</refpurpose> + </refnamediv> + + <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-transaction"> + <title>Transaction Management</title> + + <para> + It is not possible to run transaction control commands such + as <command>COMMIT</command> and <command>ROLLBACK</command> through SPI + functions such as <function>SPI_execute</function>. There are, however, + separate interface functions that allow transaction control through SPI. + </para> + + <para> + It is not generally safe and sensible to start and end transactions in + arbitrary user-defined SQL-callable functions without taking into account + the context in which they are called. For example, a transaction boundary + in the middle of a function that is part of a complex SQL expression that + is part of some SQL command will probably result in obscure internal errors + or crashes. The interface functions presented here are primarily intended + to be used by procedural language implementations to support transaction + management in SQL-level procedures that are invoked by the <command>CALL</command> + command, taking the context of the <command>CALL</command> invocation into + account. SPI-using procedures implemented in C can implement the same logic, but + the details of that are beyond the scope of this documentation. + </para> + +<!-- *********************************************** --> + +<refentry id="spi-spi-commit"> + <indexterm><primary>SPI_commit</primary></indexterm> + <indexterm><primary>SPI_commit_and_chain</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_commit</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_commit</refname> + <refname>SPI_commit_and_chain</refname> + <refpurpose>commit the current transaction</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +void SPI_commit(void) +</synopsis> + +<synopsis> +void SPI_commit_and_chain(void) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_commit</function> commits the current transaction. It is + approximately equivalent to running the SQL + command <command>COMMIT</command>. After the transaction is committed, a + new transaction is automatically started using default transaction + characteristics, so that the caller can continue using SPI facilities. + If there is a failure during commit, the current transaction is instead + rolled back and a new transaction is started, after which the error is + thrown in the usual way. + </para> + + <para> + <function>SPI_commit_and_chain</function> is the same, but the new + transaction is started with the same transaction + characteristics as the just finished one, like with the SQL command + <command>COMMIT AND CHAIN</command>. + </para> + + <para> + These functions can only be executed if the SPI connection has been set as + nonatomic in the call to <function>SPI_connect_ext</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-rollback"> + <indexterm><primary>SPI_rollback</primary></indexterm> + <indexterm><primary>SPI_rollback_and_chain</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_rollback</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_rollback</refname> + <refname>SPI_rollback_and_chain</refname> + <refpurpose>abort the current transaction</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +void SPI_rollback(void) +</synopsis> + +<synopsis> +void SPI_rollback_and_chain(void) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_rollback</function> rolls back the current transaction. It + is approximately equivalent to running the SQL + command <command>ROLLBACK</command>. After the transaction is rolled back, + a new transaction is automatically started using default transaction + characteristics, so that the caller can continue using SPI facilities. + </para> + <para> + <function>SPI_rollback_and_chain</function> is the same, but the new + transaction is started with the same transaction + characteristics as the just finished one, like with the SQL command + <command>ROLLBACK AND CHAIN</command>. + </para> + + <para> + These functions can only be executed if the SPI connection has been set as + nonatomic in the call to <function>SPI_connect_ext</function>. + </para> + </refsect1> +</refentry> + +<!-- *********************************************** --> + +<refentry id="spi-spi-start-transaction"> + <indexterm><primary>SPI_start_transaction</primary></indexterm> + + <refmeta> + <refentrytitle>SPI_start_transaction</refentrytitle> + <manvolnum>3</manvolnum> + </refmeta> + + <refnamediv> + <refname>SPI_start_transaction</refname> + <refpurpose>obsolete function</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +void SPI_start_transaction(void) +</synopsis> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para> + <function>SPI_start_transaction</function> does nothing, and exists + only for code compatibility with + earlier <productname>PostgreSQL</productname> releases. It used to + be required after calling <function>SPI_commit</function> + or <function>SPI_rollback</function>, but now those functions start + a new transaction automatically. + </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</literal> and <literal>IMMUTABLE</literal> functions are done in + read-only mode, while commands of <literal>VOLATILE</literal> 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 + C function <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" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(execq); + +Datum +execq(PG_FUNCTION_ARGS) +{ + char *command; + int cnt; + int ret; + uint64 proc; + + /* Convert given text object to a C string */ + command = text_to_cstring(PG_GETARG_TEXT_PP(0)); + cnt = PG_GETARG_INT32(1); + + 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) + { + SPITupleTable *tuptable = SPI_tuptable; + TupleDesc tupdesc = tuptable->tupdesc; + char buf[8192]; + uint64 j; + + for (j = 0; j < tuptable->numvals; j++) + { + HeapTuple tuple = tuptable->vals[j]; + int i; + + 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); + + PG_RETURN_INT64(proc); +} +</programlisting> + + <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 int8 + AS '<replaceable>filename</replaceable>' + LANGUAGE C STRICT; +</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 <lineannotation>-- inserted by execq</lineannotation> +INFO: EXECQ: 1 <lineannotation>-- returned by execq and inserted by upper INSERT</lineannotation> + + execq +------- + 2 +(1 row) + +=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a RETURNING *', 1); +INFO: EXECQ: 2 <lineannotation>-- 0 + 2, then execution was stopped by count</lineannotation> + execq +------- + 1 +(1 row) + +=> SELECT execq('SELECT * FROM a', 10); +INFO: EXECQ: 0 +INFO: EXECQ: 1 +INFO: EXECQ: 2 + + execq +------- + 3 <lineannotation>-- 10 is the max value only, 3 is the real number of rows</lineannotation> +(1 row) + +=> SELECT execq('INSERT INTO a SELECT x + 10 FROM a', 1); + execq +------- + 3 <lineannotation>-- all rows processed; count does not stop it, because nothing is returned</lineannotation> +(1 row) + +=> SELECT * FROM a; + x +---- + 0 + 1 + 2 + 10 + 11 + 12 +(6 rows) + +=> DELETE FROM a; +DELETE 6 +=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); +INSERT 0 1 +=> SELECT * FROM a; + x +--- + 1 <lineannotation>-- 0 (no rows in a) + 1</lineannotation> +(1 row) + +=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); +INFO: EXECQ: 1 +INSERT 0 1 +=> SELECT * FROM a; + x +--- + 1 + 2 <lineannotation>-- 1 (there was one row in a) + 1</lineannotation> +(2 rows) + +<lineannotation>-- This demonstrates the data changes visibility rule.</lineannotation> +<lineannotation>-- execq is called twice and sees different numbers of rows each time:</lineannotation> + +=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; +INFO: EXECQ: 1 <lineannotation>-- results from first execq</lineannotation> +INFO: EXECQ: 2 +INFO: EXECQ: 1 <lineannotation>-- results from second execq</lineannotation> +INFO: EXECQ: 2 +INFO: EXECQ: 2 +INSERT 0 2 +=> SELECT * FROM a; + x +--- + 1 + 2 + 2 <lineannotation>-- 2 rows * 1 (x in first row)</lineannotation> + 6 <lineannotation>-- 3 rows (2 + 1 just inserted) * 2 (x in second row)</lineannotation> +(4 rows) +</programlisting> + </para> + </sect1> +</chapter> |