提交 638feae2 编写于 作者: T Tom Lane

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.
上级 59ee9448
......@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.145 2005/06/20 20:44:44 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.146 2005/06/20 22:51:29 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -2012,11 +2012,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);
}
/* ----------
......@@ -3264,6 +3283,8 @@ exec_eval_datum(PLpgSQL_execstate *estate,
Datum *value,
bool *isnull)
{
MemoryContext oldcontext;
switch (datum->dtype)
{
case PLPGSQL_DTYPE_VAR:
......@@ -3290,9 +3311,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;
......@@ -3325,10 +3348,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;
......@@ -3605,7 +3630,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;
......@@ -3615,20 +3640,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.
......@@ -3642,18 +3653,6 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
active_simple_exprs = expr;
}
/*
* 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.
*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册