mirror of
https://github.com/postgres/postgres.git
synced 2025-06-08 22:02:03 +03:00
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:
parent
348f504317
commit
df83f0f61c
@ -668,6 +668,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
|
|||||||
* initialize my state
|
* initialize my state
|
||||||
*/
|
*/
|
||||||
sstate->curTuple = NULL;
|
sstate->curTuple = NULL;
|
||||||
|
sstate->curArray = PointerGetDatum(NULL);
|
||||||
sstate->projLeft = NULL;
|
sstate->projLeft = NULL;
|
||||||
sstate->projRight = NULL;
|
sstate->projRight = NULL;
|
||||||
sstate->hashtable = NULL;
|
sstate->hashtable = NULL;
|
||||||
@ -994,16 +995,23 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
|
|||||||
int paramid = linitial_int(subplan->setParam);
|
int paramid = linitial_int(subplan->setParam);
|
||||||
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
|
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)
|
if (astate != NULL)
|
||||||
prm->value = makeArrayResult(astate,
|
node->curArray = makeArrayResult(astate,
|
||||||
econtext->ecxt_per_query_memory);
|
econtext->ecxt_per_query_memory);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
|
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;
|
prm->isnull = false;
|
||||||
}
|
}
|
||||||
else if (!found)
|
else if (!found)
|
||||||
|
@ -717,6 +717,7 @@ typedef struct SubPlanState
|
|||||||
ExprState *testexpr; /* state of combining expression */
|
ExprState *testexpr; /* state of combining expression */
|
||||||
List *args; /* states of argument expression(s) */
|
List *args; /* states of argument expression(s) */
|
||||||
HeapTuple curTuple; /* copy of most recent tuple from subplan */
|
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: */
|
/* these are used when hashing the subselect's output: */
|
||||||
ProjectionInfo *projLeft; /* for projecting lefthand exprs */
|
ProjectionInfo *projLeft; /* for projecting lefthand exprs */
|
||||||
ProjectionInfo *projRight; /* for projecting subselect output */
|
ProjectionInfo *projRight; /* for projecting subselect output */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user