diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 8 | ||||
-rw-r--r-- | src/backend/utils/adt/lockfuncs.c | 41 | ||||
-rw-r--r-- | src/backend/utils/fmgr/funcapi.c | 21 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 8 | ||||
-rw-r--r-- | src/include/funcapi.h | 22 |
5 files changed, 57 insertions, 43 deletions
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 381b6047bf0..d58d312238e 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.6 2002/08/29 00:17:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.7 2002/08/29 17:14:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -429,6 +429,12 @@ function_getonetuple(FunctionScanState *scanstate, TupleTableSlot *slot = scanstate->csstate.css_ScanTupleSlot; /* + * reset per-tuple memory context before each call of the function. + * This cleans up any local memory the function may leak when called. + */ + ResetExprContext(econtext); + + /* * get the next Datum from the function */ retDatum = ExecEvalExprSwitchContext(expr, econtext, isNull, isDone); 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 */ diff --git a/src/include/funcapi.h b/src/include/funcapi.h index 27dbdf20e62..fcfb6acb694 100644 --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -9,7 +9,7 @@ * * Copyright (c) 2002, PostgreSQL Global Development Group * - * $Id: funcapi.h,v 1.5 2002/08/29 00:17:06 tgl Exp $ + * $Id: funcapi.h,v 1.6 2002/08/29 17:14:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -101,13 +101,14 @@ typedef struct FuncCallContext AttInMetadata *attinmeta; /* - * memory context used to initialize structure + * memory context used for structures which must live for multiple calls * - * fmctx is set by SRF_FIRSTCALL_INIT() for you, and used by - * SRF_RETURN_DONE() for cleanup. It is primarily for internal use - * by the API. + * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used + * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory + * context for any memory that is to be re-used across multiple calls + * of the SRF. */ - MemoryContext fmctx; + MemoryContext multi_call_memory_ctx; } FuncCallContext; @@ -160,17 +161,22 @@ extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) * { * FuncCallContext *funcctx; * Datum result; + * MemoryContext oldcontext; * <user defined declarations> * - * if(SRF_IS_FIRSTCALL()) + * if (SRF_IS_FIRSTCALL()) * { - * <user defined code> * funcctx = SRF_FIRSTCALL_INIT(); + * // switch context when allocating stuff to be used in later calls + * oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + * <user defined code> * <if returning composite> * <obtain slot> * funcctx->slot = slot; * <endif returning composite> * <user defined code> + * // return to original context when allocating transient memory + * MemoryContextSwitchTo(oldcontext); * } * <user defined code> * funcctx = SRF_PERCALL_SETUP(); |