]> granicus.if.org Git - postgresql/commitdiff
Fix relcache leak when row triggers on partitions are fired by COPY.
authorRobert Haas <rhaas@postgresql.org>
Tue, 16 May 2017 16:46:32 +0000 (12:46 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 16 May 2017 16:46:32 +0000 (12:46 -0400)
Thomas Munro, reviewed by Amit Langote

Discussion: http://postgr.es/m/CAEepm=15Jss-yhFApuKzxcoCuFnb8TR8iQiWMjG=CLYPx48QLw@mail.gmail.com

src/backend/commands/copy.c
src/backend/commands/trigger.c
src/backend/executor/execMain.c
src/include/executor/executor.h
src/test/regress/expected/triggers.out
src/test/regress/sql/triggers.sql

index f22d0a079872ecf5d0735bbd77b35175a61940d4..137b1ef42d9662bd65007156020c2e0711629bb5 100644 (file)
@@ -2773,6 +2773,9 @@ CopyFrom(CopyState cstate)
                ExecDropSingleTupleTableSlot(cstate->partition_tuple_slot);
        }
 
+       /* Close any trigger target relations */
+       ExecCleanUpTriggerState(estate);
+
        FreeExecutorState(estate);
 
        /*
index 819395a9678ae88352a1d7bc790aa21a3675b97a..1566fb46074a16509859eaeb7a8c0481306cca19 100644 (file)
@@ -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);
        }
 
index 2535d2ee69587a0b00d27d890994f2254082d0e5..fb2ba3302c0a5c5a38ae3ad6f5ad7274a34d68ac 100644 (file)
@@ -1446,6 +1446,24 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
        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
  *
@@ -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);
 
index 3107cf5b89e9b481fd86ec60f9313340c3278187..4f19579ee0b701d27adead35b47224c464453d75 100644 (file)
@@ -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);
index c300449f3aaa978537db532dd5b6b9f8a046a9d0..0d560fb3eed3519f09fbe77d00b20faabefa9c2d 100644 (file)
@@ -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;
index e5dbcaeea36f9df9edf68a6d64e4fcf71393a64f..5581fcb16485ac7ccee7fd79a936e5695841b15e 100644 (file)
@@ -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;