Fix memory leak in ARRAY(SELECT ...) subqueries.

Repeated execution of an uncorrelated ARRAY_SUBLINK sub-select (which
I think can only happen if the sub-select is embedded in a larger,
correlated subquery) would leak memory for the duration of the query,
due to not reclaiming the array generated in the previous execution.
Per bug #6698 from Armando Miraglia.  Diagnosis and fix idea by Heikki,
patch itself by me.

This has been like this all along, so back-patch to all supported versions.
This commit is contained in:
Tom Lane 2012-06-21 17:26:07 -04:00
parent 68d0e3cbf9
commit d14241c2cf
2 changed files with 14 additions and 5 deletions

View File

@ -668,6 +668,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
* initialize my state
*/
sstate->curTuple = NULL;
sstate->curArray = PointerGetDatum(NULL);
sstate->projLeft = NULL;
sstate->projRight = NULL;
sstate->hashtable = NULL;
@ -994,16 +995,23 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
int paramid = linitial_int(subplan->setParam);
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
prm->execPlan = NULL;
/* We build the result in query context so it won't disappear */
/*
* We build the result array in query context so it won't disappear;
* to avoid leaking memory across repeated calls, we have to remember
* the latest value, much as for curTuple above.
*/
if (node->curArray != PointerGetDatum(NULL))
pfree(DatumGetPointer(node->curArray));
if (astate != NULL)
prm->value = makeArrayResult(astate,
econtext->ecxt_per_query_memory);
node->curArray = makeArrayResult(astate,
econtext->ecxt_per_query_memory);
else
{
MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
prm->value = PointerGetDatum(construct_empty_array(subplan->firstColType));
node->curArray = PointerGetDatum(construct_empty_array(subplan->firstColType));
}
prm->execPlan = NULL;
prm->value = node->curArray;
prm->isnull = false;
}
else if (!found)

View File

@ -708,6 +708,7 @@ typedef struct SubPlanState
ExprState *testexpr; /* state of combining expression */
List *args; /* states of argument expression(s) */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
Datum curArray; /* most recent array from ARRAY() subplan */
/* these are used when hashing the subselect's output: */
ProjectionInfo *projLeft; /* for projecting lefthand exprs */
ProjectionInfo *projRight; /* for projecting subselect output */