Commit edc7f146 authored by Joe Conway's avatar Joe Conway

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
parent e0cd1752
...@@ -7,7 +7,7 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment