From 5a3ec023120e504e6ba1f9b68069d8949e4222d4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 15 Aug 2007 19:16:12 +0000 Subject: Repair problems occurring when multiple RI updates have to be done to the same row within one query: we were firing check triggers before all the updates were done, leading to bogus failures. Fix by making the triggers queued by an RI update go at the end of the outer query's trigger event list, thereby effectively making the processing "breadth-first". This was indeed how it worked pre-8.0, so the bug does not occur in the 7.x branches. Per report from Pavel Stehule. --- src/backend/commands/trigger.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/backend/commands/trigger.c') diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index a6b75f06d58..14f8980a99e 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.177.4.3 2006/01/12 21:49:16 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.177.4.4 2007/08/15 19:16:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2340,10 +2340,12 @@ AfterTriggerEndQuery(void) * SET CONSTRAINTS ... IMMEDIATE: all events we have decided to defer * will be available for it to fire. * + * We loop in case a trigger queues more events. + * * If we find no firable events, we don't have to increment firing_counter. */ events = &afterTriggers->query_stack[afterTriggers->query_depth]; - if (afterTriggerMarkEvents(events, &afterTriggers->events, true)) + while (afterTriggerMarkEvents(events, &afterTriggers->events, true)) { CommandId firing_id = afterTriggers->firing_counter++; @@ -2834,7 +2836,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) { AfterTriggerEventList *events = &afterTriggers->events; - if (afterTriggerMarkEvents(events, NULL, true)) + while (afterTriggerMarkEvents(events, NULL, true)) { CommandId firing_id = afterTriggers->firing_counter++; -- cgit v1.2.3