summaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-11-08 17:39:45 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2016-11-08 17:39:57 -0500
commit1833f1a1c3b0e12b3ea40d49bf11898eedae5248 (patch)
treeb389300c6fea37b0caf54025e1a7213b3d41f0d5 /doc/src
parent577f0bdd2b8904cbdfde6c98f4bda6fd93a05ffc (diff)
Simplify code by getting rid of SPI_push, SPI_pop, SPI_restore_connection.
The idea behind SPI_push was to allow transitioning back into an "unconnected" state when a SPI-using procedure calls unrelated code that might or might not invoke SPI. That sounds good, but in practice the only thing it does for us is to catch cases where a called SPI-using function forgets to call SPI_connect --- which is a highly improbable failure mode, since it would be exposed immediately by direct testing of said function. As against that, we've had multiple bugs induced by forgetting to call SPI_push/SPI_pop around code that might invoke SPI-using functions; these are much harder to catch and indeed have gone undetected for years in some cases. And we've had to band-aid around some problems of this ilk by introducing conditional push/pop pairs in some places, which really kind of defeats the purpose altogether; if we can't draw bright lines between connected and unconnected code, what's the point? Hence, get rid of SPI_push[_conditional], SPI_pop[_conditional], and the underlying state variable _SPI_curid. It turns out SPI_restore_connection can go away too, which is a nice side benefit since it was never more than a kluge. Provide no-op macros for the deleted functions so as to avoid an API break for external modules. A side effect of this removal is that SPI_palloc and allied functions no longer permit being called when unconnected; they'll throw an error instead. The apparent usefulness of the previous behavior was a mirage as well, because it was depended on by only a few places (which I fixed in preceding commits), and it posed a risk of allocations being unexpectedly long-lived if someone forgot a SPI_push call. Discussion: <20808.1478481403@sss.pgh.pa.us>
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/spi.sgml180
1 files changed, 45 insertions, 135 deletions
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index 39133c90385..836ce0822f3 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -90,21 +90,6 @@ int SPI_connect(void)
function if you want to execute commands through SPI. Some utility
SPI functions can be called from unconnected procedures.
</para>
-
- <para>
- If your procedure is already connected,
- <function>SPI_connect</function> will return the error code
- <returnvalue>SPI_ERROR_CONNECT</returnvalue>. This could happen if
- a procedure that has called <function>SPI_connect</function>
- directly calls another procedure that calls
- <function>SPI_connect</function>. While recursive calls to the
- <acronym>SPI</acronym> manager are permitted when an SQL command
- called through SPI invokes another function that uses
- <acronym>SPI</acronym>, directly nested calls to
- <function>SPI_connect</function> and
- <function>SPI_finish</function> are forbidden.
- (But see <function>SPI_push</function> and <function>SPI_pop</function>.)
- </para>
</refsect1>
<refsect1>
@@ -164,13 +149,6 @@ int SPI_finish(void)
abort the transaction via <literal>elog(ERROR)</literal>. In that
case SPI will clean itself up automatically.
</para>
-
- <para>
- If <function>SPI_finish</function> is called without having a valid
- connection, it will return <symbol>SPI_ERROR_UNCONNECTED</symbol>.
- There is no fundamental problem with this; it means that the SPI
- manager has nothing to do.
- </para>
</refsect1>
<refsect1>
@@ -200,86 +178,6 @@ int SPI_finish(void)
<!-- *********************************************** -->
-<refentry id="spi-spi-push">
- <indexterm><primary>SPI_push</primary></indexterm>
-
- <refmeta>
- <refentrytitle>SPI_push</refentrytitle>
- <manvolnum>3</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>SPI_push</refname>
- <refpurpose>push SPI stack to allow recursive SPI usage</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
-<synopsis>
-void SPI_push(void)
-</synopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <function>SPI_push</function> should be called before executing another
- procedure that might itself wish to use SPI.
- After <function>SPI_push</function>, SPI is no longer in a
- <quote>connected</> state, and SPI function calls will be rejected unless
- a fresh <function>SPI_connect</function> is done. This ensures a clean
- separation between your procedure's SPI state and that of another procedure
- you call. After the other procedure returns, call
- <function>SPI_pop</function> to restore access to your own SPI state.
- </para>
-
- <para>
- Note that <function>SPI_execute</function> and related functions
- automatically do the equivalent of <function>SPI_push</function> before
- passing control back to the SQL execution engine, so it is not necessary
- for you to worry about this when using those functions.
- Only when you are directly calling arbitrary code that might contain
- <function>SPI_connect</function> calls do you need to issue
- <function>SPI_push</function> and <function>SPI_pop</function>.
- </para>
- </refsect1>
-
-</refentry>
-
-<!-- *********************************************** -->
-
-<refentry id="spi-spi-pop">
- <indexterm><primary>SPI_pop</primary></indexterm>
-
- <refmeta>
- <refentrytitle>SPI_pop</refentrytitle>
- <manvolnum>3</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>SPI_pop</refname>
- <refpurpose>pop SPI stack to return from recursive SPI usage</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
-<synopsis>
-void SPI_pop(void)
-</synopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <function>SPI_pop</function> pops the previous environment from the
- SPI call stack. See <function>SPI_push</function>.
- </para>
- </refsect1>
-
-</refentry>
-
-<!-- *********************************************** -->
-
<refentry id="spi-spi-execute">
<indexterm><primary>SPI_execute</primary></indexterm>
@@ -3361,17 +3259,8 @@ char * SPI_getnspname(Relation <parameter>rel</parameter>)
<quote>upper executor context</quote>, that is, the memory context
that was current when <function>SPI_connect</function> was called,
which is precisely the right context for a value returned from your
- procedure.
- </para>
-
- <para>
- If <function>SPI_palloc</function> is called while the procedure is
- not connected to SPI, then it acts the same as a normal
- <function>palloc</function>. Before a procedure connects to the
- SPI manager, the current memory context is the upper executor
- context, so all allocations made by the procedure via
- <function>palloc</function> or by SPI utility functions are made in
- this context.
+ procedure. Several of the other utility procedures described in
+ this section also return objects created in the upper executor context.
</para>
<para>
@@ -3379,25 +3268,14 @@ char * SPI_getnspname(Relation <parameter>rel</parameter>)
context of the procedure, which is created by
<function>SPI_connect</function>, is made the current context. All
allocations made by <function>palloc</function>,
- <function>repalloc</function>, or SPI utility functions (except for
- <function>SPI_copytuple</function>,
- <function>SPI_returntuple</function>,
- <function>SPI_modifytuple</function>,
- <function>SPI_palloc</function>, and
- <function>SPI_datumTransfer</function>) are made in this context. When a
+ <function>repalloc</function>, or SPI utility functions (except as
+ described in this section) are made in this context. When a
procedure disconnects from the SPI manager (via
<function>SPI_finish</function>) the current context is restored to
the upper executor context, and all allocations made in the
procedure memory context are freed and cannot be used any more.
</para>
- <para>
- All functions described in this section can be used by both
- connected and unconnected procedures. In an unconnected procedure,
- they act the same as the underlying ordinary server functions
- (<function>palloc</>, etc.).
- </para>
-
<!-- *********************************************** -->
<refentry id="spi-spi-palloc">
@@ -3426,6 +3304,11 @@ void * SPI_palloc(Size <parameter>size</parameter>)
<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>
@@ -3605,6 +3488,12 @@ HeapTuple SPI_copytuple(HeapTuple <parameter>row</parameter>)
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>
@@ -3626,8 +3515,8 @@ HeapTuple SPI_copytuple(HeapTuple <parameter>row</parameter>)
<title>Return Value</title>
<para>
- the copied row; <symbol>NULL</symbol> only if
- <parameter>tuple</parameter> is <symbol>NULL</symbol>
+ the copied row, or <symbol>NULL</symbol> on error
+ (see <varname>SPI_result</varname> for an error indication)
</para>
</refsect1>
</refentry>
@@ -3664,6 +3553,12 @@ HeapTupleHeader SPI_returntuple(HeapTuple <parameter>row</parameter>, TupleDesc
</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</> for returning a modified row in a trigger.
@@ -3699,10 +3594,9 @@ HeapTupleHeader SPI_returntuple(HeapTuple <parameter>row</parameter>, TupleDesc
<title>Return Value</title>
<para>
- <type>HeapTupleHeader</type> pointing to copied row;
- <symbol>NULL</symbol> only if
- <parameter>row</parameter> or <parameter>rowdesc</parameter> is
- <symbol>NULL</symbol>
+ <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>
@@ -3736,6 +3630,13 @@ HeapTuple SPI_modifytuple(Relation <parameter>rel</parameter>, HeapTuple <parame
<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>
@@ -3821,8 +3722,8 @@ HeapTuple SPI_modifytuple(Relation <parameter>rel</parameter>, HeapTuple <parame
<para>
new row with modifications, allocated in the upper executor
- context; <symbol>NULL</symbol> only if <parameter>row</parameter>
- is <symbol>NULL</symbol>
+ context, or <symbol>NULL</symbol> on error
+ (see <varname>SPI_result</varname> for an error indication)
</para>
<para>
@@ -3845,11 +3746,20 @@ HeapTuple SPI_modifytuple(Relation <parameter>rel</parameter>, HeapTuple <parame
<listitem>
<para>
if <parameter>colnum</> contains an invalid column number (less
- than or equal to 0 or greater than the number of column in
+ than or equal to 0 or greater than the number of columns in
<parameter>row</>)
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><symbol>SPI_ERROR_UNCONNECTED</symbol></term>
+ <listitem>
+ <para>
+ if SPI is not active
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
</refsect1>