aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-05-16 12:46:32 -0400
committerRobert Haas <rhaas@postgresql.org>2017-05-16 12:46:32 -0400
commit59f40566cab95181ec132b3f0208f34e4c67f2b0 (patch)
tree322161ace2c1b3ae6bdde4e22cad90ad2c02eed0 /src
parent8e709a612f4c10cdc4b19a734cd67ac019d0a2ec (diff)
downloadpostgresql-59f40566cab95181ec132b3f0208f34e4c67f2b0.tar.gz
postgresql-59f40566cab95181ec132b3f0208f34e4c67f2b0.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/copy.c3
-rw-r--r--src/backend/commands/trigger.c11
-rw-r--r--src/backend/executor/execMain.c39
-rw-r--r--src/include/executor/executor.h1
-rw-r--r--src/test/regress/expected/triggers.out10
-rw-r--r--src/test/regress/sql/triggers.sql12
6 files changed, 48 insertions, 28 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index f22d0a07987..137b1ef42d9 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2773,6 +2773,9 @@ CopyFrom(CopyState cstate)
ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot);
}
+ /* Close any trigger target relations */
+ ExecCleanUpTriggerState(estate);
+
FreeExecutorState(estate);
/*
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 819395a9678..1566fb46074 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -4110,16 +4110,7 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
if (local_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);
- }
+ ExecCleanUpTriggerState(estate);
FreeExecutorState(estate);
}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 2535d2ee695..fb2ba3302c0 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1447,6 +1447,24 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
}
/*
+ * 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
*
* This is pretty grotty: when doing INSERT, UPDATE, or CREATE TABLE AS,
@@ -1610,16 +1628,8 @@ ExecEndPlan(PlanState *planstate, EState *estate)
resultRelInfo++;
}
- /*
- * likewise close any trigger target relations
- */
- 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);
- }
+ /* likewise close any trigger target relations */
+ ExecCleanUpTriggerState(estate);
/*
* close any relations selected FOR [KEY] UPDATE/SHARE, again keeping
@@ -3173,14 +3183,7 @@ EvalPlanQualEnd(EPQState *epqstate)
ExecResetTupleTable(estate->es_tupleTable, false);
/* close any trigger target relations attached to this 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);
- }
+ ExecCleanUpTriggerState(estate);
MemoryContextSwitchTo(oldcontext);
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 3107cf5b89e..4f19579ee0b 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -184,6 +184,7 @@ extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation partition_root,
int instrument_options);
extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
+extern void ExecCleanUpTriggerState(EState *estate);
extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate);
diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index c300449f3aa..0d560fb3eed 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -1882,4 +1882,14 @@ NOTICE: trigger on parted2_stmt_trig AFTER UPDATE for STATEMENT
delete from parted_stmt_trig;
NOTICE: trigger on parted_stmt_trig BEFORE 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;
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index e5dbcaeea36..5581fcb1648 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -1347,4 +1347,16 @@ with upd as (
) update parted_stmt_trig set a = a;
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;