On 23.01.25 16:40, Peter Eisentraut wrote:
I think my interpretation of what RESTRICT should do is different.

The clause "Execution of referential actions" in the SQL standard only talks about referenced and referencing columns, not periods.  So this would mean you can change the period columns all you want (as long as they maintain referential integrity).  So it would be like the NO ACTION case.  But you can't change any of the non-period columns on the primary key if they are referenced by any referencing columns, even if the respective periods are disjoint.

Maybe this makes sense, or maybe this is a mistake (neglected to update this part when periods were introduced?).  But in any case, I can't get from this to what the patch does.  When I apply the tests in the patch without the code changes, what I would intuitively like are more errors than the starting state, but your patch results in fewer errors.

After staring at this a bit more, I think my interpretation above was not correct. This seems better:

The clause "Execution of referential actions" in the SQL standard only
talks about referenced and referencing columns, not periods. The RESTRICT error is raised when a "matching row" exists in the referencing table. The "matching row" is determined purely by looking at the "normal" columns of the key, not the period columns.

So in our implementation in ri_restrict(), ISTM, we just need to ignore the period/range columns when doing the RESTRICT check.

Attached is a quick patch that demonstrates how this could work. I think the semantics of this are right and make sense.
From 7d2ae226da67838825120f759a912362cf91e065 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Thu, 13 Feb 2025 13:15:23 +0100
Subject: [PATCH] WIP: Fix RESTRICT behavior for temporal foreign keys

---
 src/backend/utils/adt/ri_triggers.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/backend/utils/adt/ri_triggers.c 
b/src/backend/utils/adt/ri_triggers.c
index 8473448849c..bbd1d5712f2 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -787,6 +787,12 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
                        Oid                     pk_type = RIAttType(pk_rel, 
riinfo->pk_attnums[i]);
                        Oid                     fk_type = RIAttType(fk_rel, 
riinfo->fk_attnums[i]);
 
+                       if (riinfo->hasperiod && !is_no_action)
+                       {
+                               if (i == riinfo->nkeys - 1)
+                                       continue;
+                       }
+
                        quoteOneName(attname,
                                                 RIAttName(fk_rel, 
riinfo->fk_attnums[i]));
                        sprintf(paramname, "$%d", i + 1);
@@ -2734,6 +2740,12 @@ ri_ReportViolation(const RI_ConstraintInfo *riinfo,
                        Datum           datum;
                        bool            isnull;
 
+                       if (riinfo->hasperiod && is_restrict)
+                       {
+                               if (idx == riinfo->nkeys - 1)
+                                       continue;
+                       }
+
                        name = NameStr(att->attname);
 
                        datum = slot_getattr(violatorslot, fnum, &isnull);
-- 
2.48.1

Reply via email to