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,
Assert(afterTriggers.events.head == NULL);
Assert(afterTriggers.trans_stack == NULL);
Assert(afterTriggers.maxtransdepth == 0);
+ Assert(afterTriggerFiringDepth == 0);
}
*/
qs = &afterTriggers.query_stack[afterTriggers.query_depth];
+ afterTriggerFiringDepth++;
for (;;)
{
if (afterTriggerMarkEvents(&qs->events, &afterTriggers.events, true))
AfterTriggerFreeQuery(&afterTriggers.query_stack[afterTriggers.query_depth]);
afterTriggers.query_depth--;
+ afterTriggerFiringDepth--;
}
* Run all the remaining triggers. Loop until they are all gone, in case
* some trigger queues more for us to do.
*/
+ afterTriggerFiringDepth++;
while (afterTriggerMarkEvents(events, NULL, false))
{
CommandId firing_id = afterTriggers.firing_counter++;
/* Flush any fast-path batches accumulated by the triggers just fired. */
FireAfterTriggerBatchCallbacks();
+ afterTriggerFiringDepth--;
+
/*
* We don't bother freeing the event list, since it will go away anyway
* (and more efficiently than via pfree) in AfterTriggerEndXact.
/* No more afterTriggers manipulation until next transaction starts. */
afterTriggers.query_depth = -1;
+
+ afterTriggerFiringDepth = 0;
}
/*
AfterTriggerEventList *events = &afterTriggers.events;
bool snapshot_set = false;
+ afterTriggerFiringDepth++;
while (afterTriggerMarkEvents(events, NULL, true))
{
CommandId firing_id = afterTriggers.firing_counter++;
* Flush any fast-path batches accumulated by the triggers just fired.
*/
FireAfterTriggerBatchCallbacks();
+ afterTriggerFiringDepth--;
if (snapshot_set)
PopActiveSnapshot();
* Allocate in TopTransactionContext so the item survives for the duration
* of the batch, which may span multiple trigger invocations.
*
- * Must be called while afterTriggers is active (query_depth >= 0);
- * callbacks registered outside a trigger-firing context would never fire.
+ * Must be called while afterTriggers is active; callbacks registered
+ * outside a trigger-firing context would never fire.
*/
- Assert(afterTriggers.query_depth >= 0);
+ Assert(afterTriggerFiringDepth > 0);
oldcxt = MemoryContextSwitchTo(TopTransactionContext);
item = palloc(sizeof(AfterTriggerCallbackItem));
item->callback = callback;
if (afterTriggers.query_depth > 0)
return;
+ Assert(afterTriggerFiringDepth > 0);
foreach(lc, afterTriggers.batch_callbacks)
{
AfterTriggerCallbackItem *item = lfirst(lc);
bool
AfterTriggerIsActive(void)
{
- return afterTriggers.query_depth >= 0;
+ return afterTriggerFiringDepth > 0;
}