From a15ad255e7591ae3f14d3cb91e60be2794078c28 Mon Sep 17 00:00:00 2001 From: "Paul A. Jungwirth" Date: Thu, 30 Jul 2026 12:39:13 -0700 Subject: [PATCH v1 4/7] Let ri_PerformCheck pass a FOR PORTION OF parameter Temporal CASCADE/SET NULL/SET DEFAULT run their referencing statements with a FOR PORTION OF clause whose bounds are computed by the trigger, not taken from the key columns, so the query has one more parameter than the key values supply. Give ri_PerformCheck the parameter number and the value to put there, and let every existing caller pass -1 to say it has no such parameter. No behavior change; this only gets the plumbing out of the way of the commits that use it. Author: Paul A. Jungwirth --- src/backend/utils/adt/ri_triggers.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 00ff0f949b9..690f4fb620f 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -366,6 +366,7 @@ static bool ri_PerformCheck(const RI_ConstraintInfo *riinfo, RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, + int periodParam, Datum period, bool is_restrict, bool detectNewRows, int expect_OK); static void ri_FastPathCheck(RI_ConstraintInfo *riinfo, @@ -655,6 +656,7 @@ RI_FKey_check(TriggerData *trigdata) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, NULL, newslot, + -1, (Datum) 0, false, pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE, SPI_OK_SELECT); @@ -820,6 +822,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, result = ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + -1, (Datum) 0, false, true, /* treat like update */ SPI_OK_SELECT); @@ -1096,6 +1099,7 @@ ri_restrict(TriggerData *trigdata, bool is_no_action) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + -1, (Datum) 0, !is_no_action, true, /* must detect new rows */ SPI_OK_SELECT); @@ -1198,6 +1202,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + -1, (Datum) 0, false, true, /* must detect new rows */ SPI_OK_DELETE); @@ -1315,6 +1320,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, newslot, + -1, (Datum) 0, false, true, /* must detect new rows */ SPI_OK_UPDATE); @@ -1543,6 +1549,7 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + -1, (Datum) 0, false, true, /* must detect new rows */ SPI_OK_UPDATE); @@ -2723,6 +2730,7 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo, RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, + int periodParam, Datum period, bool is_restrict, bool detectNewRows, int expect_OK) { @@ -2735,8 +2743,8 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo, int spi_result; Oid save_userid; int save_sec_context; - Datum vals[RI_MAX_NUMKEYS * 2]; - char nulls[RI_MAX_NUMKEYS * 2]; + Datum vals[RI_MAX_NUMKEYS * 2 + 1]; + char nulls[RI_MAX_NUMKEYS * 2 + 1]; /* * Use the query type code to determine whether the query is run against @@ -2779,6 +2787,12 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo, ri_ExtractValues(source_rel, oldslot, riinfo, source_is_pk, vals, nulls); } + /* Add/replace a query param for the PERIOD if needed */ + if (periodParam > 0) + { + vals[periodParam - 1] = period; + nulls[periodParam - 1] = ' '; + } /* * In READ COMMITTED mode, we just need to use an up-to-date regular -- 2.45.0