*
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.45 2008/01/01 19:45:49 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.45.2.1 2008/02/29 02:49:43 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
         * do it always.
         */
        if (funcTupdesc)
+       {
            tupledesc_match(node->tupdesc, funcTupdesc);
+
+           /*
+            * If it is a dynamically-allocated TupleDesc, free it: it is
+            * typically allocated in the EState's per-query context, so we
+            * must avoid leaking it on rescan.
+            */
+           if (funcTupdesc->tdrefcount == -1)
+               FreeTupleDesc(funcTupdesc);
+       }
    }
 
    /*
 
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.37 2008/01/01 19:45:53 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.37.2.1 2008/02/29 02:49:43 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
+#include "utils/memutils.h"
 #include "utils/syscache.h"
 #include "utils/typcache.h"
 
        /*
         * First call
         */
-       ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
+       ReturnSetInfo  *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
+       MemoryContext   multi_call_ctx;
+
+       /*
+        * Create a suitably long-lived context to hold cross-call data
+        */
+       multi_call_ctx = AllocSetContextCreate(fcinfo->flinfo->fn_mcxt,
+                                              "SRF multi-call context",
+                                              ALLOCSET_SMALL_MINSIZE,
+                                              ALLOCSET_SMALL_INITSIZE,
+                                              ALLOCSET_SMALL_MAXSIZE);
 
        /*
         * Allocate suitably long-lived space and zero it
         */
        retval = (FuncCallContext *)
-           MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
+           MemoryContextAllocZero(multi_call_ctx,
                                   sizeof(FuncCallContext));
 
        /*
        retval->user_fctx = NULL;
        retval->attinmeta = NULL;
        retval->tuple_desc = NULL;
-       retval->multi_call_memory_ctx = fcinfo->flinfo->fn_mcxt;
+       retval->multi_call_memory_ctx = multi_call_ctx;
 
        /*
         * save the pointer for cross-call use
    flinfo->fn_extra = NULL;
 
    /*
-    * Caller is responsible to free up memory for individual struct elements
-    * other than att_in_funcinfo and elements.
+    * Delete context that holds all multi-call data, including the
+    * FuncCallContext itself
     */
-   if (funcctx->attinmeta != NULL)
-       pfree(funcctx->attinmeta);
-
-   pfree(funcctx);
+   MemoryContextSwitchTo(flinfo->fn_mcxt);
+   MemoryContextDelete(funcctx->multi_call_memory_ctx);
 }