Tom Lane wrote:
You may not even need to add any fields to FuncCallContext --- consider
passing the fcinfo pointer to the callback, rather than passing the
FuncCallContext pointer.

Dept. of second thoughts: better pass the flinfo pointer, instead. fcinfo might point to temporary space on the stack.

OK -- this one is a good bit simpler. Any more comments?


Joe

Index: src/backend/utils/fmgr/funcapi.c
===================================================================
RCS file: /opt/src/cvs/pgsql-server/src/backend/utils/fmgr/funcapi.c,v
retrieving revision 1.12
diff -c -r1.12 funcapi.c
*** src/backend/utils/fmgr/funcapi.c    29 Nov 2003 19:52:01 -0000      1.12
--- src/backend/utils/fmgr/funcapi.c    19 Dec 2003 00:01:46 -0000
***************
*** 17,22 ****
--- 17,23 ----
  #include "catalog/pg_type.h"
  #include "utils/syscache.h"
  
+ static void shutdown_MultiFuncCall(Datum arg);
  
  /*
   * init_MultiFuncCall
***************
*** 41,47 ****
        {
                /*
                 * First call
!                *
                 * Allocate suitably long-lived space and zero it
                 */
                retval = (FuncCallContext *)
--- 42,51 ----
        {
                /*
                 * First call
!                */
!               ReturnSetInfo      *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
! 
!               /*
                 * Allocate suitably long-lived space and zero it
                 */
                retval = (FuncCallContext *)
***************
*** 63,68 ****
--- 67,80 ----
                 * 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,115 ****
  void
  end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
  {
!       /* unbind from fcinfo */
!       fcinfo->flinfo->fn_extra = NULL;
  
        /*
         * Caller is responsible to free up memory for individual struct
--- 120,148 ----
  void
  end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
  {
!       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
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to