From 4ed90a5b74c77c5e4a2f5b0a602a06a372aec795 Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Wed, 8 Apr 2026 23:22:41 +0900 Subject: [PATCH v3 3/4] Move afterTriggerFiringDepth into AfterTriggersData The static variable afterTriggerFiringDepth is logically part of the after-trigger state. Move it into AfterTriggersData as firing_depth, alongside query_depth and the other per-transaction after-trigger state. --- src/backend/commands/trigger.c | 42 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index f59537fe86e..bbc2405cc4a 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -3894,7 +3894,16 @@ typedef struct AfterTriggersData AfterTriggersTransData *trans_stack; /* array of structs shown below */ int maxtransdepth; /* allocated len of above array */ - List *batch_callbacks; /* List of AfterTriggerCallbackItem */ + /* + * Incremented around the trigger-firing loops in AfterTriggerEndQuery, + * AfterTriggerFireDeferred, and AfterTriggerSetState. Used by + * AfterTriggerIsActive() and to tag batch callbacks with the depth at + * which they should fire. + */ + int firing_depth; + + List *batch_callbacks; /* List of AfterTriggerCallbackItem, + * possibly from multiple firing depths */ } AfterTriggersData; struct AfterTriggersQueryData @@ -3942,13 +3951,6 @@ typedef struct AfterTriggerCallbackItem static AfterTriggersData afterTriggers; -/* - * Incremented before invoking afterTriggerInvokeEvents(). Used by - * AfterTriggerIsActive() to determine whether batch callbacks will fire, - * so that RI trigger functions can take the batched fast path. - */ -static int afterTriggerFiringDepth = 0; - static void AfterTriggerExecute(EState *estate, AfterTriggerEvent event, ResultRelInfo *relInfo, @@ -5108,6 +5110,7 @@ AfterTriggerBeginXact(void) */ afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */ afterTriggers.query_depth = -1; + afterTriggers.firing_depth = 0; afterTriggers.batch_callbacks = NIL; /* @@ -5122,7 +5125,6 @@ AfterTriggerBeginXact(void) Assert(afterTriggers.events.head == NULL); Assert(afterTriggers.trans_stack == NULL); Assert(afterTriggers.maxtransdepth == 0); - Assert(afterTriggerFiringDepth == 0); } @@ -5194,7 +5196,7 @@ AfterTriggerEndQuery(EState *estate) */ qs = &afterTriggers.query_stack[afterTriggers.query_depth]; - afterTriggerFiringDepth++; + afterTriggers.firing_depth++; for (;;) { if (afterTriggerMarkEvents(&qs->events, &afterTriggers.events, true)) @@ -5245,7 +5247,7 @@ AfterTriggerEndQuery(EState *estate) AfterTriggerFreeQuery(&afterTriggers.query_stack[afterTriggers.query_depth]); afterTriggers.query_depth--; - afterTriggerFiringDepth--; + afterTriggers.firing_depth--; } @@ -5341,7 +5343,7 @@ AfterTriggerFireDeferred(void) * Run all the remaining triggers. Loop until they are all gone, in case * some trigger queues more for us to do. */ - afterTriggerFiringDepth++; + afterTriggers.firing_depth++; while (afterTriggerMarkEvents(events, NULL, false)) { CommandId firing_id = afterTriggers.firing_counter++; @@ -5353,7 +5355,7 @@ AfterTriggerFireDeferred(void) /* Flush any fast-path batches accumulated by the triggers just fired. */ FireAfterTriggerBatchCallbacks(); - afterTriggerFiringDepth--; + afterTriggers.firing_depth--; /* * We don't bother freeing the event list, since it will go away anyway @@ -5420,7 +5422,7 @@ AfterTriggerEndXact(bool isCommit) /* No more afterTriggers manipulation until next transaction starts. */ afterTriggers.query_depth = -1; - afterTriggerFiringDepth = 0; + afterTriggers.firing_depth = 0; Assert(afterTriggers.batch_callbacks == NIL || !isCommit); @@ -6079,7 +6081,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) AfterTriggerEventList *events = &afterTriggers.events; bool snapshot_set = false; - afterTriggerFiringDepth++; + afterTriggers.firing_depth++; while (afterTriggerMarkEvents(events, NULL, true)) { CommandId firing_id = afterTriggers.firing_counter++; @@ -6113,7 +6115,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) * Flush any fast-path batches accumulated by the triggers just fired. */ FireAfterTriggerBatchCallbacks(); - afterTriggerFiringDepth--; + afterTriggers.firing_depth--; if (snapshot_set) PopActiveSnapshot(); @@ -6837,11 +6839,11 @@ RegisterAfterTriggerBatchCallback(AfterTriggerBatchCallback callback, * Must be called while afterTriggers is active; callbacks registered * outside a trigger-firing context would never fire. */ - Assert(afterTriggerFiringDepth > 0); + Assert(afterTriggers.firing_depth > 0); oldcxt = MemoryContextSwitchTo(TopTransactionContext); item = palloc(sizeof(AfterTriggerCallbackItem)); item->callback = callback; - item->firing_depth = afterTriggerFiringDepth; + item->firing_depth = afterTriggers.firing_depth; item->arg = arg; afterTriggers.batch_callbacks = lappend(afterTriggers.batch_callbacks, item); @@ -6876,7 +6878,7 @@ FireAfterTriggerBatchCallbacks(void) { AfterTriggerCallbackItem *item = lfirst(lc); - if (item->firing_depth == afterTriggerFiringDepth) + if (item->firing_depth == afterTriggers.firing_depth) to_fire = lappend(to_fire, item); else remaining = lappend(remaining, item); @@ -6908,5 +6910,5 @@ FireAfterTriggerBatchCallbacks(void) bool AfterTriggerIsActive(void) { - return afterTriggerFiringDepth > 0; + return afterTriggers.firing_depth > 0; } -- 2.47.3