MCPcopy Create free account
hub / github.com/apache/cloudberry / AfterTriggerEndQuery

Function AfterTriggerEndQuery

src/backend/commands/trigger.c:4768–4849  ·  view source on GitHub ↗

---------- * AfterTriggerEndQuery() * * Called after one query has been completely processed. At this time * we invoke all AFTER IMMEDIATE trigger events queued by the query, and * transfer deferred trigger events to the global deferred-trigger list. * * Note that this must be called BEFORE closing down the executor * with ExecutorEnd, because we make use of the EState's info about * targ

Source from the content-addressed store, hash-verified

4766 * ----------
4767 */
4768void
4769AfterTriggerEndQuery(EState *estate)
4770{
4771 AfterTriggersQueryData *qs;
4772
4773 /* Must be inside a query, too */
4774 Assert(afterTriggers.query_depth >= 0);
4775
4776 /*
4777 * If we never even got as far as initializing the event stack, there
4778 * certainly won't be any events, so exit quickly.
4779 */
4780 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
4781 {
4782 afterTriggers.query_depth--;
4783 return;
4784 }
4785
4786 /*
4787 * Process all immediate-mode triggers queued by the query, and move the
4788 * deferred ones to the main list of deferred events.
4789 *
4790 * Notice that we decide which ones will be fired, and put the deferred
4791 * ones on the main list, before anything is actually fired. This ensures
4792 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
4793 * IMMEDIATE: all events we have decided to defer will be available for it
4794 * to fire.
4795 *
4796 * We loop in case a trigger queues more events at the same query level.
4797 * Ordinary trigger functions, including all PL/pgSQL trigger functions,
4798 * will instead fire any triggers in a dedicated query level. Foreign key
4799 * enforcement triggers do add to the current query level, thanks to their
4800 * passing fire_triggers = false to SPI_execute_snapshot(). Other
4801 * C-language triggers might do likewise.
4802 *
4803 * If we find no firable events, we don't have to increment
4804 * firing_counter.
4805 */
4806 qs = &afterTriggers.query_stack[afterTriggers.query_depth];
4807
4808 for (;;)
4809 {
4810 if (afterTriggerMarkEvents(&qs->events, &afterTriggers.events, true))
4811 {
4812 CommandId firing_id = afterTriggers.firing_counter++;
4813 AfterTriggerEventChunk *oldtail = qs->events.tail;
4814
4815 if (afterTriggerInvokeEvents(&qs->events, firing_id, estate, false))
4816 break; /* all fired */
4817
4818 /*
4819 * Firing a trigger could result in query_stack being repalloc'd,
4820 * so we must recalculate qs after each afterTriggerInvokeEvents
4821 * call. Furthermore, it's unsafe to pass delete_ok = true here,
4822 * because that could cause afterTriggerInvokeEvents to try to
4823 * access qs->events after the stack has been repalloc'd.
4824 */
4825 qs = &afterTriggers.query_stack[afterTriggers.query_depth];

Callers 5

CopyFromDirectoryTableFunction · 0.85
CopyFromFunction · 0.85
ExecuteTruncateGutsFunction · 0.85
finish_edataFunction · 0.85
standard_ExecutorFinishFunction · 0.85

Calls 4

afterTriggerMarkEventsFunction · 0.85
afterTriggerInvokeEventsFunction · 0.85
AfterTriggerFreeQueryFunction · 0.85

Tested by

no test coverage detected