summaryrefslogtreecommitdiff
path: root/src/pl/plpython/plpython.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pl/plpython/plpython.c')
-rw-r--r--src/pl/plpython/plpython.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index f3352b3bc6f..1ae12396a12 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -985,7 +985,10 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc)
{
if (!proc->is_setof || proc->setof == NULL)
{
- /* Simple type returning function or first time for SETOF function */
+ /*
+ * Simple type returning function or first time for SETOF function:
+ * actually execute the function.
+ */
plargs = PLy_function_build_args(fcinfo, proc);
plrv = PLy_procedure_call(proc, "args", plargs);
if (!proc->is_setof)
@@ -1000,14 +1003,10 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc)
}
/*
- * Disconnect from SPI manager and then create the return values datum
- * (if the input function does a palloc for it this must not be
- * allocated in the SPI memory context because SPI_finish would free
- * it).
+ * If it returns a set, call the iterator to get the next return item.
+ * We stay in the SPI context while doing this, because PyIter_Next()
+ * calls back into Python code which might contain SPI calls.
*/
- if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish failed");
-
if (proc->is_setof)
{
bool has_error = false;
@@ -1064,11 +1063,24 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc)
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("error fetching next item from iterator")));
+ /* Disconnect from the SPI manager before returning */
+ if (SPI_finish() != SPI_OK_FINISH)
+ elog(ERROR, "SPI_finish failed");
+
fcinfo->isnull = true;
return (Datum) NULL;
}
}
+ /*
+ * Disconnect from SPI manager and then create the return values datum
+ * (if the input function does a palloc for it this must not be
+ * allocated in the SPI memory context because SPI_finish would free
+ * it).
+ */
+ if (SPI_finish() != SPI_OK_FINISH)
+ elog(ERROR, "SPI_finish failed");
+
plerrcontext.callback = plpython_return_error_callback;
plerrcontext.previous = error_context_stack;
error_context_stack = &plerrcontext;