aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-06-20 22:51:49 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-06-20 22:51:49 +0000
commit7d32f099d7ce64d08f458d2e33bce7b28e1293b5 (patch)
tree273e0a290df9a639a997a6c58b6c60a796111dbb /src
parentc541ca6403f02c695bfeb85b6733cbf2c561943c (diff)
downloadpostgresql-7d32f099d7ce64d08f458d2e33bce7b28e1293b5.tar.gz
postgresql-7d32f099d7ce64d08f458d2e33bce7b28e1293b5.zip
exec_eval_datum leaks memory when dealing with ROW or REC values.
It never leaked memory before PG 8.0, so none of the callers are expecting this. Cleanest fix seems to be to make it allocate the needed memory in estate->eval_econtext, where it will be cleaned up by the next exec_eval_cleanup. Per report from Bill Rugolsky.
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpgsql/src/pl_exec.c57
1 files changed, 28 insertions, 29 deletions
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index facdbe3e8af..0470a14f999 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.2 2005/06/20 20:44:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.3 2005/06/20 22:51:49 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -2003,11 +2003,30 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
estate->eval_tuptable = NULL;
estate->eval_processed = 0;
estate->eval_lastoid = InvalidOid;
- estate->eval_econtext = NULL;
estate->err_func = func;
estate->err_stmt = NULL;
estate->err_text = NULL;
+
+ /*
+ * Create an EState for evaluation of simple expressions, if there's
+ * not one already in the current transaction. The EState is made a
+ * child of TopTransactionContext so it will have the right lifespan.
+ */
+ if (simple_eval_estate == NULL)
+ {
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(TopTransactionContext);
+ simple_eval_estate = CreateExecutorState();
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /*
+ * Create an expression context for simple expressions.
+ * This must be a child of simple_eval_estate.
+ */
+ estate->eval_econtext = CreateExprContext(simple_eval_estate);
}
/* ----------
@@ -3238,6 +3257,8 @@ exec_eval_datum(PLpgSQL_execstate *estate,
Datum *value,
bool *isnull)
{
+ MemoryContext oldcontext;
+
switch (datum->dtype)
{
case PLPGSQL_DTYPE_VAR:
@@ -3264,9 +3285,11 @@ exec_eval_datum(PLpgSQL_execstate *estate,
elog(ERROR, "row variable has no tupdesc");
/* Make sure we have a valid type/typmod setting */
BlessTupleDesc(row->rowtupdesc);
+ oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
tup = make_tuple_from_row(estate, row, row->rowtupdesc);
if (tup == NULL) /* should not happen */
elog(ERROR, "row not compatible with its own tupdesc");
+ MemoryContextSwitchTo(oldcontext);
*typeid = row->rowtupdesc->tdtypeid;
*value = HeapTupleGetDatum(tup);
*isnull = false;
@@ -3299,10 +3322,12 @@ exec_eval_datum(PLpgSQL_execstate *estate,
* fields. Copy the tuple body and insert the right
* values.
*/
+ oldcontext = MemoryContextSwitchTo(estate->eval_econtext->ecxt_per_tuple_memory);
heap_copytuple_with_tuple(rec->tup, &worktup);
HeapTupleHeaderSetDatumLength(worktup.t_data, worktup.t_len);
HeapTupleHeaderSetTypeId(worktup.t_data, rec->tupdesc->tdtypeid);
HeapTupleHeaderSetTypMod(worktup.t_data, rec->tupdesc->tdtypmod);
+ MemoryContextSwitchTo(oldcontext);
*typeid = rec->tupdesc->tdtypeid;
*value = HeapTupleGetDatum(&worktup);
*isnull = false;
@@ -3579,7 +3604,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
Oid *rettype)
{
Datum retval;
- ExprContext * volatile econtext;
+ ExprContext *econtext = estate->eval_econtext;
ParamListInfo paramLI;
int i;
Snapshot saveActiveSnapshot;
@@ -3590,20 +3615,6 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
*rettype = expr->expr_simple_type;
/*
- * Create an EState for evaluation of simple expressions, if there's
- * not one already in the current transaction. The EState is made a
- * child of TopTransactionContext so it will have the right lifespan.
- */
- if (simple_eval_estate == NULL)
- {
- MemoryContext oldcontext;
-
- oldcontext = MemoryContextSwitchTo(TopTransactionContext);
- simple_eval_estate = CreateExecutorState();
- MemoryContextSwitchTo(oldcontext);
- }
-
- /*
* Prepare the expression for execution, if it's not been done already
* in the current transaction.
*/
@@ -3617,18 +3628,6 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
}
/*
- * Create an expression context for simple expressions, if there's not
- * one already in the current function call. This must be a child of
- * simple_eval_estate.
- */
- econtext = estate->eval_econtext;
- if (econtext == NULL)
- {
- econtext = CreateExprContext(simple_eval_estate);
- estate->eval_econtext = econtext;
- }
-
- /*
* Param list can live in econtext's temporary memory context.
*
* XXX think about avoiding repeated palloc's for param lists? Beware