From 1424c7abc44fcb61f6a2a63f7d163670ba3250be Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 20 Jun 2024 14:21:36 -0400 Subject: Don't throw an error if a queued AFTER trigger no longer exists. afterTriggerInvokeEvents and AfterTriggerExecute have always treated it as an error if the trigger OID mentioned in a queued after-trigger event can't be found. However, that fails to account for the edge case where the trigger's been dropped in the current transaction since queueing the event. There seems no very good reason to disallow that case, so instead silently do nothing if the trigger OID can't be found. This does give up a little bit of bug-detection ability, but I don't recall that these error messages have ever actually revealed a bug, so it seems mostly theoretical. Alternatives such as marking pending events DONE at the time of dropping a trigger would be complicated and perhaps introduce bugs of their own. Per bug #18517 from Alexander Lakhin. Back-patch to all supported branches. Discussion: https://postgr.es/m/18517-af2d19882240902c@postgresql.org --- src/backend/commands/trigger.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/backend/commands/trigger.c') diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 72b113476e5..a7f49a6731d 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -4390,8 +4390,12 @@ AfterTriggerExecute(EState *estate, bool should_free_new = false; /* - * Locate trigger in trigdesc. + * Locate trigger in trigdesc. It might not be present, and in fact the + * trigdesc could be NULL, if the trigger was dropped since the event was + * queued. In that case, silently do nothing. */ + if (trigdesc == NULL) + return; for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++) { if (trigdesc->triggers[tgindx].tgoid == tgoid) @@ -4401,7 +4405,7 @@ AfterTriggerExecute(EState *estate, } } if (LocTriggerData.tg_trigger == NULL) - elog(ERROR, "could not find trigger %u", tgoid); + return; /* * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want @@ -4782,6 +4786,7 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events, /* Catch calls with insufficient relcache refcounting */ Assert(!RelationHasReferenceCountZero(rel)); trigdesc = rInfo->ri_TrigDesc; + /* caution: trigdesc could be NULL here */ finfo = rInfo->ri_TrigFunctions; instr = rInfo->ri_TrigInstrument; if (slot1 != NULL) @@ -4797,9 +4802,6 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events, slot2 = MakeSingleTupleTableSlot(rel->rd_att, &TTSOpsMinimalTuple); } - if (trigdesc == NULL) /* should not happen */ - elog(ERROR, "relation %u has no triggers", - evtshared->ats_relid); } /* -- cgit v1.2.3