77 * Copyright (c) 2002-2003, PostgreSQL Global Development Group
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.12 2003/11/29 19:52:01 pgsql Exp $
10+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.13 2003/12/19 00:02:11 joe Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
1717#include "catalog/pg_type.h"
1818#include "utils/syscache.h"
1919
20+ static void shutdown_MultiFuncCall (Datum arg );
2021
2122/*
2223 * init_MultiFuncCall
@@ -41,7 +42,10 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
4142{
4243/*
4344 * First call
44- *
45+ */
46+ ReturnSetInfo * rsi = (ReturnSetInfo * )fcinfo -> resultinfo ;
47+
48+ /*
4549 * Allocate suitably long-lived space and zero it
4650 */
4751retval = (FuncCallContext * )
@@ -63,6 +67,14 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
6367 * save the pointer for cross-call use
6468 */
6569fcinfo -> flinfo -> fn_extra = retval ;
70+
71+ /*
72+ * Ensure we will get shut down cleanly if the exprcontext is not
73+ * run to completion.
74+ */
75+ RegisterExprContextCallback (rsi -> econtext ,
76+ shutdown_MultiFuncCall ,
77+ PointerGetDatum (fcinfo -> flinfo ));
6678}
6779else
6880{
@@ -108,8 +120,29 @@ per_MultiFuncCall(PG_FUNCTION_ARGS)
108120void
109121end_MultiFuncCall (PG_FUNCTION_ARGS ,FuncCallContext * funcctx )
110122{
111- /* unbind from fcinfo */
112- fcinfo -> flinfo -> fn_extra = NULL ;
123+ ReturnSetInfo * rsi = (ReturnSetInfo * )fcinfo -> resultinfo ;
124+
125+ /* Deregister the shutdown callback */
126+ UnregisterExprContextCallback (rsi -> econtext ,
127+ shutdown_MultiFuncCall ,
128+ PointerGetDatum (fcinfo -> flinfo ));
129+
130+ /* But use it to do the real work */
131+ shutdown_MultiFuncCall (PointerGetDatum (fcinfo -> flinfo ));
132+ }
133+
134+ /*
135+ * shutdown_MultiFuncCall
136+ * Shutdown function to clean up after init_MultiFuncCall
137+ */
138+ static void
139+ shutdown_MultiFuncCall (Datum arg )
140+ {
141+ FmgrInfo * flinfo = (FmgrInfo * )DatumGetPointer (arg );
142+ FuncCallContext * funcctx = (FuncCallContext * )flinfo -> fn_extra ;
143+
144+ /* unbind from flinfo */
145+ flinfo -> fn_extra = NULL ;
113146
114147/*
115148 * Caller is responsible to free up memory for individual struct