Hardwire RI fast-path end-of-xact cleanup into xact.c Commit b7b27eb41a5, which added foreign-key fast-path batching to ri_triggers.c, registered ri_FastPathXactCallback() via RegisterXactCallback() to clear the fast-path batching state at end of transaction. RegisterXactCallback() is documented as intended for dynamically loaded modules; built-in code is supposed to hardwire its end-of-xact hooks into xact.c, mainly so callback ordering can be controlled where it matters (see the header comment on RegisterXactCallback()).
Convert the callback into a plain AtEOXact_RI() function and call it directly from CommitTransaction(), PrepareTransaction() and AbortTransaction(), alongside the other AtEOXact_* cleanup steps, and drop the RegisterXactCallback() registration. Like the other AtEOXact_* routines, AtEOXact_RI() takes an isCommit argument and treats the two paths differently. On commit or prepare the fast-path cache must already have been flushed and torn down by the after-trigger batch callback, so a surviving cache indicates a trigger batch was never flushed -- which would have silently skipped FK checks -- and draws an Assert plus a WARNING. On abort a surviving cache is expected (a flush may have errored out partway) and is simply reset. There is no ordering dependency here: AtEOXact_RI() only resets backend-local static state (the cache pointer, the callback-registered flag, and the in-flush guard). It touches no relations, locks, buffers or catalogs, so its position relative to ResourceOwnerRelease() and the surrounding AtEOXact_* calls does not matter. On a normal commit the fast-path cache has already been flushed and torn down by ri_FastPathEndBatch() (an AfterTriggerBatchCallback fired from AfterTriggerFireDeferred(), well before any end-of-xact callback), so the reset is a no-op; its real job is the abort path, where teardown may not have run and the static pointers would otherwise dangle into the next transaction. The cache memory itself lives in TopTransactionContext and is freed by the end-of-transaction memory-context reset on both paths. The companion RegisterSubXactCallback() use from b7b27eb41a5 was already removed by commit 4113873a, which confined fast-path batching to the top transaction level, so only the RegisterXactCallback() use remained. Reported-by: Bertrand Drouvot <[email protected]> Reviewed-by: Bertrand Drouvot <[email protected]> Discussion: https://postgr.es/m/ajypPeEWceXRGAEW@bdtpg Branch ------ master Details ------- https://git.postgresql.org/pg/commitdiff/6f4bac854fb784f83b86f05c7e9921e038135442 Modified Files -------------- src/backend/access/transam/xact.c | 3 ++ src/backend/utils/adt/ri_triggers.c | 58 +++++++++++++++++++++++++++---------- src/include/commands/trigger.h | 2 ++ 3 files changed, 47 insertions(+), 16 deletions(-)
