diff options
Diffstat (limited to 'src/pl/plpython/plpython.c')
| -rw-r--r-- | src/pl/plpython/plpython.c | 28 | 
1 files changed, 20 insertions, 8 deletions
| diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 1446f0d4558..ea47067a855 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -984,7 +984,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) @@ -999,14 +1002,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; @@ -1063,11 +1062,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; | 
