From 7619357adf748e4396f418652adf40e9d77941fc Mon Sep 17 00:00:00 2001 From: Junwang Zhao Date: Tue, 10 Mar 2026 18:06:21 +0800 Subject: [PATCH v5 6/6] Reuse FK tuple slot across fast-path batches --- src/backend/utils/adt/ri_triggers.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index eb112aabc98..ae1765a37f4 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -213,8 +213,9 @@ typedef struct RI_FastPathEntry Relation idx_rel; IndexScanDesc scandesc; TupleTableSlot *slot; + TupleTableSlot *fk_slot; Snapshot snapshot; /* registered snapshot for the scan */ - + /* For when IsolationUsesXactSnapshot() is true */ Snapshot xact_snap; IndexScanDesc xact_scan; @@ -314,7 +315,7 @@ pg_noreturn static void ri_ReportViolation(const RI_ConstraintInfo *riinfo, Relation pk_rel, Relation fk_rel, TupleTableSlot *violatorslot, TupleDesc tupdesc, int queryno, bool is_restrict, bool partgone); -static RI_FastPathEntry *ri_FastPathGetEntry(const RI_ConstraintInfo *riinfo); +static RI_FastPathEntry *ri_FastPathGetEntry(const RI_ConstraintInfo *riinfo, Relation fk_rel); static void ri_FastPathEndBatch(void *arg); static void ri_FastPathTeardown(void); static void ri_FastPathBatchAdd(const RI_ConstraintInfo *riinfo, @@ -3851,6 +3852,8 @@ ri_FastPathTeardown(void) table_close(entry->pk_rel, NoLock); if (entry->slot) ExecDropSingleTupleTableSlot(entry->slot); + if (entry->fk_slot) + ExecDropSingleTupleTableSlot(entry->fk_slot); if (entry->snapshot) UnregisterSnapshot(entry->snapshot); if (entry->xact_snap) @@ -3909,7 +3912,7 @@ ri_FastPathSubXactCallback(SubXactEvent event, SubTransactionId mySubid, * index_rescan() with new keys. */ static RI_FastPathEntry * -ri_FastPathGetEntry(const RI_ConstraintInfo *riinfo) +ri_FastPathGetEntry(const RI_ConstraintInfo *riinfo, Relation fk_rel) { RI_FastPathEntry *entry; bool found; @@ -3974,6 +3977,8 @@ ri_FastPathGetEntry(const RI_ConstraintInfo *riinfo) entry->snapshot = RegisterSnapshot(GetLatestSnapshot()); entry->slot = table_slot_create(entry->pk_rel, NULL); + entry->fk_slot = MakeSingleTupleTableSlot(RelationGetDescr(fk_rel), + &TTSOpsHeapTuple); entry->scandesc = index_beginscan(entry->pk_rel, entry->idx_rel, entry->snapshot, NULL, @@ -4238,7 +4243,7 @@ ri_FastPathBatchFlush(RI_FastPathEntry *fpentry, Relation fk_rel) Relation pk_rel = fpentry->pk_rel; Relation idx_rel = fpentry->idx_rel; Snapshot snapshot = fpentry->snapshot; - TupleTableSlot *fk_slot; + TupleTableSlot *fk_slot = fpentry->fk_slot; Oid saved_userid; int saved_sec_context; @@ -4259,9 +4264,6 @@ ri_FastPathBatchFlush(RI_FastPathEntry *fpentry, Relation fk_rel) SECURITY_LOCAL_USERID_CHANGE | SECURITY_NOFORCE_RLS); - fk_slot = MakeSingleTupleTableSlot(RelationGetDescr(fk_rel), - &TTSOpsHeapTuple); - if (riinfo->nkeys == 1) ri_FastPathFlushArray(fpentry, fk_slot, riinfo, fk_rel); else @@ -4272,10 +4274,7 @@ ri_FastPathBatchFlush(RI_FastPathEntry *fpentry, Relation fk_rel) /* Free materialized tuples and reset */ for (int i = 0; i < fpentry->batch_count; i++) heap_freetuple(fpentry->batch[i]); - fpentry->batch_count = 0; - - ExecDropSingleTupleTableSlot(fk_slot); } /* @@ -4297,7 +4296,7 @@ ri_FastPathBatchAdd(const RI_ConstraintInfo *riinfo, RI_FastPathEntry *fpentry; MemoryContext oldcxt; - fpentry = ri_FastPathGetEntry(riinfo); + fpentry = ri_FastPathGetEntry(riinfo, fk_rel); oldcxt = MemoryContextSwitchTo(TopTransactionContext); fpentry->batch[fpentry->batch_count] = -- 2.41.0