1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Close relations opened specifically for AFTER triggers

39dcfda2d fixed an incorrect reuse of ResultRelInfos for AFTER triggers
when the ResultRelInfo needed to have a different ri_RootResultRelInfo.
That caused an issue in logical replication apply workers as
finish_edata() neglects to call ExecCloseResultRelations() and instead
relies on ExecCleanupTupleRouting() to close relations opened during
partitioning's tuple routing.  Since 39dcfda2d, because we may have done
some additional table_opens() calls due to having to create an additional
ResultRelInfo because of requirements to have a different
ri_RootResultRelInfo, we should now be explicitly closing any relations
opened on ResultRelInfos in EState's es_trig_target_relations.

Since finish_edate() seems to want to avoid calling
ExecCloseResultRelations(), add a new external function named
ExecCloseTrigTargetRelations().

Reported-by: Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com>
Author: Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com>
Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com>
Discussion: https://postgr.es/m/OS9PR01MB121491E7E05950D108AF9A6D8F5A72@OS9PR01MB12149.jpnprd01.prod.outlook.com
Backpatch-through: 15
This commit is contained in:
David Rowley
2026-08-27 02:41:21 +12:00
parent b259ece92a
commit 4f0af2635b
4 changed files with 32 additions and 4 deletions

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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)

View File

@@ -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();