Skip to content

Commit 1424c7a

Browse files
committed
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
1 parent 27c6242 commit 1424c7a

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

src/backend/commands/trigger.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,8 +4390,12 @@ AfterTriggerExecute(EState *estate,
43904390
bool should_free_new = false;
43914391

43924392
/*
4393-
* Locate trigger in trigdesc.
4393+
* Locate trigger in trigdesc. It might not be present, and in fact the
4394+
* trigdesc could be NULL, if the trigger was dropped since the event was
4395+
* queued. In that case, silently do nothing.
43944396
*/
4397+
if (trigdesc == NULL)
4398+
return;
43954399
for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
43964400
{
43974401
if (trigdesc->triggers[tgindx].tgoid == tgoid)
@@ -4401,7 +4405,7 @@ AfterTriggerExecute(EState *estate,
44014405
}
44024406
}
44034407
if (LocTriggerData.tg_trigger == NULL)
4404-
elog(ERROR, "could not find trigger %u", tgoid);
4408+
return;
44054409

44064410
/*
44074411
* If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
@@ -4782,6 +4786,7 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
47824786
/* Catch calls with insufficient relcache refcounting */
47834787
Assert(!RelationHasReferenceCountZero(rel));
47844788
trigdesc = rInfo->ri_TrigDesc;
4789+
/* caution: trigdesc could be NULL here */
47854790
finfo = rInfo->ri_TrigFunctions;
47864791
instr = rInfo->ri_TrigInstrument;
47874792
if (slot1 != NULL)
@@ -4797,9 +4802,6 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
47974802
slot2 = MakeSingleTupleTableSlot(rel->rd_att,
47984803
&TTSOpsMinimalTuple);
47994804
}
4800-
if (trigdesc == NULL) /* should not happen */
4801-
elog(ERROR, "relation %u has no triggers",
4802-
evtshared->ats_relid);
48034805
}
48044806

48054807
/*

src/test/regress/expected/triggers.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3372,6 +3372,17 @@ select * from trig_table;
33723372

33733373
drop table refd_table, trig_table;
33743374
--
3375+
-- Test that we can drop a not-yet-fired deferred trigger
3376+
--
3377+
create table refd_table (id int primary key);
3378+
create table trig_table (fk int references refd_table initially deferred);
3379+
begin;
3380+
insert into trig_table values (1);
3381+
drop table refd_table cascade;
3382+
NOTICE: drop cascades to constraint trig_table_fk_fkey on table trig_table
3383+
commit;
3384+
drop table trig_table;
3385+
--
33753386
-- self-referential FKs are even more fun
33763387
--
33773388
create table self_ref (a int primary key,

src/test/regress/sql/triggers.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,6 +2478,20 @@ select * from trig_table;
24782478

24792479
drop table refd_table, trig_table;
24802480

2481+
--
2482+
-- Test that we can drop a not-yet-fired deferred trigger
2483+
--
2484+
2485+
create table refd_table (id int primary key);
2486+
create table trig_table (fk int references refd_table initially deferred);
2487+
2488+
begin;
2489+
insert into trig_table values (1);
2490+
drop table refd_table cascade;
2491+
commit;
2492+
2493+
drop table trig_table;
2494+
24812495
--
24822496
-- self-referential FKs are even more fun
24832497
--

0 commit comments

Comments
 (0)