diff options
-rw-r--r-- | src/backend/commands/trigger.c | 12 | ||||
-rw-r--r-- | src/test/regress/expected/triggers.out | 11 | ||||
-rw-r--r-- | src/test/regress/sql/triggers.sql | 14 |
3 files changed, 32 insertions, 5 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 7362e99fa50..c852b137f06 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -3997,8 +3997,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) @@ -4008,7 +4012,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 @@ -4332,6 +4336,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) @@ -4347,9 +4352,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); } /* diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index 45562bd35c4..8a203a34ed1 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -3286,6 +3286,17 @@ select * from trig_table; drop table refd_table, trig_table; -- +-- Test that we can drop a not-yet-fired deferred trigger +-- +create table refd_table (id int primary key); +create table trig_table (fk int references refd_table initially deferred); +begin; +insert into trig_table values (1); +drop table refd_table cascade; +NOTICE: drop cascades to constraint trig_table_fk_fkey on table trig_table +commit; +drop table trig_table; +-- -- self-referential FKs are even more fun -- create table self_ref (a int primary key, diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index a1aa52521e7..c841f8f17c5 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -2407,6 +2407,20 @@ select * from trig_table; drop table refd_table, trig_table; -- +-- Test that we can drop a not-yet-fired deferred trigger +-- + +create table refd_table (id int primary key); +create table trig_table (fk int references refd_table initially deferred); + +begin; +insert into trig_table values (1); +drop table refd_table cascade; +commit; + +drop table trig_table; + +-- -- self-referential FKs are even more fun -- |