Use a shutdown callback to ensure proper clean up when rescanning
partially-evaluated SRFs. Per report found here: http://archives.postgresql.org/pgsql-general/2003-12/msg00851.php
This commit is contained in:
parent
e0cd175212
commit
edc7f146e3
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.12 2003/11/29 19:52:01 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.13 2003/12/19 00:02:11 joe Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -17,6 +17,7 @@
|
||||
#include "catalog/pg_type.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
static void shutdown_MultiFuncCall(Datum arg);
|
||||
|
||||
/*
|
||||
* init_MultiFuncCall
|
||||
@ -41,7 +42,10 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/*
|
||||
* First call
|
||||
*
|
||||
*/
|
||||
ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
|
||||
/*
|
||||
* Allocate suitably long-lived space and zero it
|
||||
*/
|
||||
retval = (FuncCallContext *)
|
||||
@ -63,6 +67,14 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
|
||||
* save the pointer for cross-call use
|
||||
*/
|
||||
fcinfo->flinfo->fn_extra = retval;
|
||||
|
||||
/*
|
||||
* Ensure we will get shut down cleanly if the exprcontext is not
|
||||
* run to completion.
|
||||
*/
|
||||
RegisterExprContextCallback(rsi->econtext,
|
||||
shutdown_MultiFuncCall,
|
||||
PointerGetDatum(fcinfo->flinfo));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -108,8 +120,29 @@ per_MultiFuncCall(PG_FUNCTION_ARGS)
|
||||
void
|
||||
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
|
||||
{
|
||||
/* unbind from fcinfo */
|
||||
fcinfo->flinfo->fn_extra = NULL;
|
||||
ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
|
||||
/* Deregister the shutdown callback */
|
||||
UnregisterExprContextCallback(rsi->econtext,
|
||||
shutdown_MultiFuncCall,
|
||||
PointerGetDatum(fcinfo->flinfo));
|
||||
|
||||
/* But use it to do the real work */
|
||||
shutdown_MultiFuncCall(PointerGetDatum(fcinfo->flinfo));
|
||||
}
|
||||
|
||||
/*
|
||||
* shutdown_MultiFuncCall
|
||||
* Shutdown function to clean up after init_MultiFuncCall
|
||||
*/
|
||||
static void
|
||||
shutdown_MultiFuncCall(Datum arg)
|
||||
{
|
||||
FmgrInfo *flinfo = (FmgrInfo *) DatumGetPointer(arg);
|
||||
FuncCallContext *funcctx = (FuncCallContext *) flinfo->fn_extra;
|
||||
|
||||
/* unbind from flinfo */
|
||||
flinfo->fn_extra = NULL;
|
||||
|
||||
/*
|
||||
* Caller is responsible to free up memory for individual struct
|
||||
|
Loading…
x
Reference in New Issue
Block a user