aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 3ab193cb14a..3164b9923f7 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.40.2.1 2006/12/26 19:26:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.40.2.2 2008/02/29 02:49:47 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -78,7 +78,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 efb33a0a107..ac8ef5482ae 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2006, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.31 2006/07/11 16:35:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.31.2.1 2008/02/29 02:49:47 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);
}