The following bug has been logged on the website:
Bug reference: 16705
Logged by: Ross Biro
Email address: rbiro@interfacefinancial.com
PostgreSQL version: 10.10
Operating system: Linux
Description:
If you register a function with RegisterXactCallback that causes a trigger
to be deferred, that trigger is never executed.
The code in CommitTransaction:
/*
* Do pre-commit processing that involves calling user-defined code,
such
* as triggers. Since closing cursors could queue trigger actions,
* triggers could open cursors, etc, we have to keep looping until
there's
* nothing left to do.
*/
for (;;)
{
/*
* Fire all currently pending deferred triggers.
*/
AfterTriggerFireDeferred();
/*
* Close open portals (converting holdable ones into static
portals).
* If there weren't any, we are done ... otherwise loop back to
check
* if they queued deferred triggers. Lather, rinse, repeat.
*/
if (!PreCommit_Portals(false))
break;
}
CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
: XACT_EVENT_PRE_COMMIT);
It may be possible to just move CallXactCallbacks inside the loop or ad a
second loop around the existing loop and the callbacks. Alternatively,
perhaps the right solution is to document that commit callbacks cannot do
anything that might defer a trigger, or prevent triggers from being deferred
for the rest of the transactions.