1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Fix relcache leak when row triggers on partitions are fired by COPY.

Thomas Munro, reviewed by Amit Langote

Discussion: http://postgr.es/m/CAEepm=15Jss-yhFApuKzxcoCuFnb8TR8iQiWMjG=CLYPx48QLw@mail.gmail.com
This commit is contained in:
Robert Haas
2017-05-16 12:46:32 -04:00
parent 8e709a612f
commit 59f40566ca
6 changed files with 48 additions and 28 deletions

View File

@ -2773,6 +2773,9 @@ CopyFrom(CopyState cstate)
ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot); ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot);
} }
/* Close any trigger target relations */
ExecCleanUpTriggerState(estate);
FreeExecutorState(estate); FreeExecutorState(estate);
/* /*

View File

@ -4110,16 +4110,7 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
if (local_estate) if (local_estate)
{ {
ListCell *l; ExecCleanUpTriggerState(estate);
foreach(l, estate->es_trig_target_relations)
{
ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
/* Close indices and then the relation itself */
ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock);
}
FreeExecutorState(estate); FreeExecutorState(estate);
} }

View File

@ -1446,6 +1446,24 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
return rInfo; return rInfo;
} }
/*
* Close any relations that have been opened by ExecGetTriggerResultRel().
*/
void
ExecCleanUpTriggerState(EState *estate)
{
ListCell *l;
foreach(l, estate->es_trig_target_relations)
{
ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
/* Close indices and then the relation itself */
ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock);
}
}
/* /*
* ExecContextForcesOids * ExecContextForcesOids
* *
@ -1610,16 +1628,8 @@ ExecEndPlan(PlanState *planstate, EState *estate)
resultRelInfo++; resultRelInfo++;
} }
/* /* likewise close any trigger target relations */
* likewise close any trigger target relations ExecCleanUpTriggerState(estate);
*/
foreach(l, estate->es_trig_target_relations)
{
resultRelInfo = (ResultRelInfo *) lfirst(l);
/* Close indices and then the relation itself */
ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock);
}
/* /*
* close any relations selected FOR [KEY] UPDATE/SHARE, again keeping * close any relations selected FOR [KEY] UPDATE/SHARE, again keeping
@ -3173,14 +3183,7 @@ EvalPlanQualEnd(EPQState *epqstate)
ExecResetTupleTable(estate->es_tupleTable, false); ExecResetTupleTable(estate->es_tupleTable, false);
/* close any trigger target relations attached to this EState */ /* close any trigger target relations attached to this EState */
foreach(l, estate->es_trig_target_relations) ExecCleanUpTriggerState(estate);
{
ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
/* Close indices and then the relation itself */
ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock);
}
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);

View File

@ -184,6 +184,7 @@ extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation partition_root, Relation partition_root,
int instrument_options); int instrument_options);
extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid); extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
extern void ExecCleanUpTriggerState(EState *estate);
extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids); extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
extern void ExecConstraints(ResultRelInfo *resultRelInfo, extern void ExecConstraints(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate); TupleTableSlot *slot, EState *estate);

View File

@ -1882,4 +1882,14 @@ NOTICE: trigger on parted2_stmt_trig AFTER UPDATE for STATEMENT
delete from parted_stmt_trig; delete from parted_stmt_trig;
NOTICE: trigger on parted_stmt_trig BEFORE DELETE for STATEMENT NOTICE: trigger on parted_stmt_trig BEFORE DELETE for STATEMENT
NOTICE: trigger on parted_stmt_trig AFTER DELETE for STATEMENT NOTICE: trigger on parted_stmt_trig AFTER DELETE for STATEMENT
-- insert via copy on the parent
copy parted_stmt_trig(a) from stdin;
NOTICE: trigger on parted_stmt_trig BEFORE INSERT for STATEMENT
NOTICE: trigger on parted_stmt_trig1 BEFORE INSERT for ROW
NOTICE: trigger on parted_stmt_trig1 AFTER INSERT for ROW
NOTICE: trigger on parted_stmt_trig AFTER INSERT for STATEMENT
-- insert via copy on the first partition
copy parted_stmt_trig1(a) from stdin;
NOTICE: trigger on parted_stmt_trig1 BEFORE INSERT for ROW
NOTICE: trigger on parted_stmt_trig1 AFTER INSERT for ROW
drop table parted_stmt_trig, parted2_stmt_trig; drop table parted_stmt_trig, parted2_stmt_trig;

View File

@ -1347,4 +1347,16 @@ with upd as (
) update parted_stmt_trig set a = a; ) update parted_stmt_trig set a = a;
delete from parted_stmt_trig; delete from parted_stmt_trig;
-- insert via copy on the parent
copy parted_stmt_trig(a) from stdin;
1
2
\.
-- insert via copy on the first partition
copy parted_stmt_trig1(a) from stdin;
1
\.
drop table parted_stmt_trig, parted2_stmt_trig; drop table parted_stmt_trig, parted2_stmt_trig;