aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-08-29 17:14:33 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-08-29 17:14:33 +0000
commite4186762ffaa4188e16702e8f4f299ea70988b96 (patch)
tree2ee78b84ead113ad17b029743432c24a37a362f9 /src/backend/utils
parent0201dac1c319599aad3feb752d7ee5162200e2c7 (diff)
downloadpostgresql-e4186762ffaa4188e16702e8f4f299ea70988b96.tar.gz
postgresql-e4186762ffaa4188e16702e8f4f299ea70988b96.zip
Adjust nodeFunctionscan.c to reset transient memory context between calls
to the table function, thus preventing memory leakage accumulation across calls. This means that SRFs need to be careful to distinguish permanent and local storage; adjust code and documentation accordingly. Patch by Joe Conway, very minor tweaks by Tom Lane.
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/lockfuncs.c41
-rw-r--r--src/backend/utils/fmgr/funcapi.c21
-rw-r--r--src/backend/utils/misc/guc.c8
3 files changed, 36 insertions, 34 deletions
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 83d0d1051df..199efbacd26 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -5,7 +5,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.3 2002/08/29 00:17:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.4 2002/08/29 17:14:33 tgl Exp $
*/
#include "postgres.h"
@@ -24,15 +24,20 @@ static int next_lock(int locks[]);
Datum
pg_lock_status(PG_FUNCTION_ARGS)
{
- FuncCallContext *funccxt;
- LockData *lockData;
+ FuncCallContext *funcctx;
+ LockData *lockData;
+ MemoryContext oldcontext;
if (SRF_IS_FIRSTCALL())
{
- MemoryContext oldcxt;
TupleDesc tupdesc;
- funccxt = SRF_FIRSTCALL_INIT();
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
tupdesc = CreateTemplateTupleDesc(5, WITHOUTOID);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
OIDOID, -1, 0, false);
@@ -45,10 +50,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "isgranted",
BOOLOID, -1, 0, false);
- funccxt->slot = TupleDescGetSlot(tupdesc);
- funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc);
-
- oldcxt = MemoryContextSwitchTo(funccxt->fmctx);
+ funcctx->slot = TupleDescGetSlot(tupdesc);
+ funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
/*
* Preload all the locking information that we will eventually format
@@ -56,15 +59,15 @@ pg_lock_status(PG_FUNCTION_ARGS)
* MemoryContext is reset when the SRF finishes, we don't need to
* free it ourselves.
*/
- funccxt->user_fctx = (LockData *) palloc(sizeof(LockData));
+ funcctx->user_fctx = (LockData *) palloc(sizeof(LockData));
- GetLockStatusData(funccxt->user_fctx);
+ GetLockStatusData(funcctx->user_fctx);
- MemoryContextSwitchTo(oldcxt);
+ MemoryContextSwitchTo(oldcontext);
}
- funccxt = SRF_PERCALL_SETUP();
- lockData = (LockData *) funccxt->user_fctx;
+ funcctx = SRF_PERCALL_SETUP();
+ lockData = (LockData *) funcctx->user_fctx;
while (lockData->currIdx < lockData->nelements)
{
@@ -82,7 +85,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
holder = &(lockData->holders[currIdx]);
lock = &(lockData->locks[currIdx]);
proc = &(lockData->procs[currIdx]);
- num_attrs = funccxt->attinmeta->tupdesc->natts;
+ num_attrs = funcctx->attinmeta->tupdesc->natts;
values = (char **) palloc(sizeof(*values) * num_attrs);
@@ -133,12 +136,12 @@ pg_lock_status(PG_FUNCTION_ARGS)
strncpy(values[3], GetLockmodeName(mode), 32);
- tuple = BuildTupleFromCStrings(funccxt->attinmeta, values);
- result = TupleGetDatum(funccxt->slot, tuple);
- SRF_RETURN_NEXT(funccxt, result);
+ tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+ result = TupleGetDatum(funcctx->slot, tuple);
+ SRF_RETURN_NEXT(funcctx, result);
}
- SRF_RETURN_DONE(funccxt);
+ SRF_RETURN_DONE(funcctx);
}
static LOCKMODE
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 28311c26b7b..35ba972fe12 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.3 2002/08/29 00:17:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.4 2002/08/29 17:14:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,16 +39,12 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
{
/*
* First call
+ *
+ * Allocate suitably long-lived space and zero it
*/
- MemoryContext oldcontext;
-
- /* switch to the appropriate memory context */
- oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-
- /*
- * allocate space and zero it
- */
- retval = (FuncCallContext *) palloc(sizeof(FuncCallContext));
+ retval = (FuncCallContext *)
+ MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+ sizeof(FuncCallContext));
MemSet(retval, 0, sizeof(FuncCallContext));
/*
@@ -59,15 +55,12 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
retval->slot = NULL;
retval->user_fctx = NULL;
retval->attinmeta = NULL;
- retval->fmctx = fcinfo->flinfo->fn_mcxt;
+ retval->multi_call_memory_ctx = fcinfo->flinfo->fn_mcxt;
/*
* save the pointer for cross-call use
*/
fcinfo->flinfo->fn_extra = retval;
-
- /* back to the original memory context */
- MemoryContextSwitchTo(oldcontext);
}
else /* second and subsequent calls */
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 660cd124ba9..5114fcc38f2 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5,7 +5,7 @@
* command, configuration file, and command line options.
* See src/backend/utils/misc/README for more information.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.85 2002/08/29 00:17:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.86 2002/08/29 17:14:33 tgl Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -2421,6 +2421,7 @@ show_all_settings(PG_FUNCTION_ARGS)
int max_calls;
TupleTableSlot *slot;
AttInMetadata *attinmeta;
+ MemoryContext oldcontext;
/* stuff done only on the first call of the function */
if(SRF_IS_FIRSTCALL())
@@ -2428,6 +2429,9 @@ show_all_settings(PG_FUNCTION_ARGS)
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
/* need a tuple descriptor representing two TEXT columns */
tupdesc = CreateTemplateTupleDesc(2, WITHOUTOID);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
@@ -2450,6 +2454,8 @@ show_all_settings(PG_FUNCTION_ARGS)
/* total number of tuples to be returned */
funcctx->max_calls = GetNumConfigOptions();
+
+ MemoryContextSwitchTo(oldcontext);
}
/* stuff done on every call of the function */