diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 3ab193cb14..3164b9923f 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 efb33a0a10..ac8ef5482a 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); }