aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/nodeFunctionscan.c12
-rw-r--r--src/backend/utils/fmgr/funcapi.c29
2 files changed, 30 insertions, 11 deletions
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 81b9c69e9a2..6bbb5b139b6 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* 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.46 2008/02/29 02:49:39 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -77,7 +77,17 @@ FunctionNext(FunctionScanState *node)
* 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);
+ }
}
/*
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 8c6609de62c..4bb230a3f36 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
* 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.38 2008/02/29 02:49:39 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,6 +23,7 @@
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
+#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
@@ -63,13 +64,23 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
/*
* 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));
/*
@@ -81,7 +92,7 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
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
@@ -168,13 +179,11 @@ shutdown_MultiFuncCall(Datum arg)
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);
}