summaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorTom Lane2012-06-20 00:07:08 +0000
committerTom Lane2012-06-20 00:07:33 +0000
commitcfa0f4255bb0f5550d37a01c4d8fe2966d20040c (patch)
tree8dc72f8c53b3c5eeed79bf566487cd95216331ac /src/backend/commands/trigger.c
parentafe1c51c9d65c67c7474c60d64bceefe9953dde6 (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.c31
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;