diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index c3af96989ba..d8bbe467a70 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1642,6 +1642,22 @@ ExecCloseResultRelations(EState *estate) } } + /* + * Now close any relations that we opened for trigger target + * ResultRelInfos. + */ + ExecCloseTrigTargetRelations(estate); +} + +/* + * Close any relations that have been opened for ResultRelInfos opened + * specifically for trigger target relations. + */ +void +ExecCloseTrigTargetRelations(EState *estate) +{ + ListCell *l; + /* Close any relations that have been opened by ExecGetTriggerResultRel(). */ foreach(l, estate->es_trig_target_relations) { diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index b3cdbce8d10..52c6cc8c596 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -945,12 +945,16 @@ finish_edata(ApplyExecutionData *edata) ExecCleanupTupleRouting(edata->mtstate, edata->proute); /* - * Cleanup. It might seem that we should call ExecCloseResultRelations() - * here, but we intentionally don't. It would close the rel we added to + * Close relations opened specifically for trigger targets. It might seem + * that we should call ExecCloseResultRelations() here, but we + * intentionally don't as that would close the rel we added to * es_opened_result_relations above, which is wrong because we took no - * corresponding refcount. We rely on ExecCleanupTupleRouting() to close - * any other relations opened during execution. + * corresponding refcount. ExecCleanupTupleRouting() closes relations + * opened for tuple routing, while ExecCloseTrigTargetRelations() closes + * any relations we opened for AFTER triggers. */ + ExecCloseTrigTargetRelations(estate); + ExecResetTupleTable(estate->es_tupleTable, false); FreeExecutorState(estate); pfree(edata); diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 1798e6027d4..190e8a4897a 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -703,6 +703,7 @@ extern void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos Bitmapset *unpruned_relids); extern void ExecCloseRangeTableRelations(EState *estate); extern void ExecCloseResultRelations(EState *estate); +extern void ExecCloseTrigTargetRelations(EState *estate); static inline RangeTblEntry * exec_rt_fetch(Index rti, EState *estate) diff --git a/src/test/subscription/t/013_partition.pl b/src/test/subscription/t/013_partition.pl index 234d4f003b7..21c3a9e261b 100644 --- a/src/test/subscription/t/013_partition.pl +++ b/src/test/subscription/t/013_partition.pl @@ -897,4 +897,11 @@ $result = $node_subscriber2->safe_psql('postgres', "SELECT a, b, c FROM tab5_1 ORDER BY 1"); is($result, qq(4||1), 'updates of tab5 replicated correctly'); +# Validate we didn't neglect to cleanup any resources on either subscriber. +foreach my $node ($node_subscriber1, $node_subscriber2) +{ + ok(!$node->log_contains(qr/resource was not closed/), + 'check for resource leaks on ' . $node->name); +} + done_testing();