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