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
|
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "catalog/pg_type.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
static void shutdown_MultiFuncCall(Datum arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* init_MultiFuncCall
|
* init_MultiFuncCall
|
||||||
@ -41,7 +42,10 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* First call
|
* First call
|
||||||
*
|
*/
|
||||||
|
ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||||
|
|
||||||
|
/*
|
||||||
* Allocate suitably long-lived space and zero it
|
* Allocate suitably long-lived space and zero it
|
||||||
*/
|
*/
|
||||||
retval = (FuncCallContext *)
|
retval = (FuncCallContext *)
|
||||||
@ -63,6 +67,14 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
|
|||||||
* save the pointer for cross-call use
|
* save the pointer for cross-call use
|
||||||
*/
|
*/
|
||||||
fcinfo->flinfo->fn_extra = retval;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -108,8 +120,29 @@ per_MultiFuncCall(PG_FUNCTION_ARGS)
|
|||||||
void
|
void
|
||||||
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
|
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
|
||||||
{
|
{
|
||||||
/* unbind from fcinfo */
|
ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||||
fcinfo->flinfo->fn_extra = NULL;
|
|
||||||
|
/* 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
|
* Caller is responsible to free up memory for individual struct
|
||||||
|
Loading…
x
Reference in New Issue
Block a user