diff options
author | Tom Lane | 2012-06-20 00:07:08 +0000 |
---|---|---|
committer | Tom Lane | 2012-06-20 00:07:33 +0000 |
commit | cfa0f4255bb0f5550d37a01c4d8fe2966d20040c (patch) | |
tree | 8dc72f8c53b3c5eeed79bf566487cd95216331ac /src/backend/commands/trigger.c | |
parent | afe1c51c9d65c67c7474c60d64bceefe9953dde6 (diff) |
Improve tests for whether we can skip queueing RI enforcement triggers.
During an update of a PK row, we can skip firing the RI trigger if any old
key value is NULL, because then the row could not have had any matching
rows in the FK table. Conversely, during an update of an FK row, the
outcome is determined if any new key value is NULL. In either case it
becomes unnecessary to compare individual key values.
This patch was inspired by discussion of Vik Reykja's patch to use IS NOT
DISTINCT semantics for the key comparisons. In the event there is no need
for that and so this patch looks nothing like his, but he should still get
credit for having re-opened consideration of the trigger skip logic.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 57fcfbeefd9..834b694ec6b 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -4582,39 +4582,30 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, continue; /* - * If this is an UPDATE of a PK table or FK table that does not change - * the PK or FK respectively, we can skip queuing the event: there is - * no need to fire the trigger. + * If the trigger is a foreign key enforcement trigger, there are + * certain cases where we can skip queueing the event because we can + * tell by inspection that the FK constraint will still pass. */ if (TRIGGER_FIRED_BY_UPDATE(event)) { switch (RI_FKey_trigger_type(trigger->tgfoid)) { case RI_TRIGGER_PK: - /* Update on PK table */ - if (RI_FKey_keyequal_upd_pk(trigger, rel, oldtup, newtup)) + /* Update on trigger's PK table */ + if (!RI_FKey_pk_upd_check_required(trigger, rel, + oldtup, newtup)) { - /* key unchanged, so skip queuing this event */ + /* skip queuing this event */ continue; } break; case RI_TRIGGER_FK: - - /* - * Update on FK table - * - * There is one exception when updating FK tables: if the - * updated row was inserted by our own transaction and the - * FK is deferred, we still need to fire the trigger. This - * is because our UPDATE will invalidate the INSERT so the - * end-of-transaction INSERT RI trigger will not do - * anything, so we have to do the check for the UPDATE - * anyway. - */ - if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(oldtup->t_data)) && - RI_FKey_keyequal_upd_fk(trigger, rel, oldtup, newtup)) + /* Update on trigger's FK table */ + if (!RI_FKey_fk_upd_check_required(trigger, rel, + oldtup, newtup)) { + /* skip queuing this event */ continue; } break; |