aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/spi.sgml15
-rw-r--r--src/backend/executor/spi.c20
2 files changed, 28 insertions, 7 deletions
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index fca48caec04..d488c203d3d 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.59 2007/09/14 04:18:27 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.60 2008/02/12 04:09:44 tgl Exp $ -->
<chapter id="spi">
<title>Server Programming Interface</title>
@@ -1077,9 +1077,12 @@ bool SPI_is_cursor_plan(SPIPlanPtr <parameter>plan</parameter>)
<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.
- If the <parameter>plan</parameter> is <symbol>NULL</symbol> or invalid,
- <varname>SPI_result</varname> is set to <symbol>SPI_ERROR_ARGUMENT</symbol>
+ <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>
@@ -1442,8 +1445,8 @@ Portal SPI_cursor_open(const char * <parameter>name</parameter>, SPIPlanPtr <par
<title>Return Value</title>
<para>
- pointer to portal containing the cursor, or <symbol>NULL</symbol>
- on error
+ Pointer to portal containing the cursor. Note there is no error
+ return convention; any error will be reported via <function>elog</>.
</para>
</refsect1>
</refentry>
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index ae083f7225d..a23c4d017a8 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.187 2008/01/01 19:45:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.188 2008/02/12 04:09:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -886,6 +886,10 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
Assert(list_length(plan->plancache_list) == 1);
plansource = (CachedPlanSource *) linitial(plan->plancache_list);
+ /* Push the SPI stack */
+ if (_SPI_begin_call(false) < 0)
+ elog(ERROR, "SPI_cursor_open called while not connected");
+
/* Reset SPI result (note we deliberately don't touch lastoid) */
SPI_processed = 0;
SPI_tuptable = NULL;
@@ -1041,6 +1045,9 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
Assert(portal->strategy != PORTAL_MULTI_QUERY);
+ /* Pop the SPI stack */
+ _SPI_end_call(false);
+
/* Return the created portal */
return portal;
}
@@ -1180,9 +1187,17 @@ SPI_is_cursor_plan(SPIPlanPtr plan)
}
if (list_length(plan->plancache_list) != 1)
+ {
+ SPI_result = 0;
return false; /* not exactly 1 pre-rewrite command */
+ }
plansource = (CachedPlanSource *) linitial(plan->plancache_list);
+ /* Need _SPI_begin_call in case replanning invokes SPI-using functions */
+ SPI_result = _SPI_begin_call(false);
+ if (SPI_result < 0)
+ return false;
+
if (plan->saved)
{
/* Make sure the plan is up to date */
@@ -1190,6 +1205,9 @@ SPI_is_cursor_plan(SPIPlanPtr plan)
ReleaseCachedPlan(cplan, true);
}
+ _SPI_end_call(false);
+ SPI_result = 0;
+
/* Does it return tuples? */
if (plansource->resultDesc)
return true;