I think the code to determine that fk of a partition is inherited or not is
not enough.
For example, in this case, foreign key r_1_p_id_fkey1  is not inherited
from parent.

If conform->conparentid(in DetachPartitionFinalize func) is valid, we
should recheck confrelid(pg_constraint) field.

I try to fix this problem in the attached patch.
Any thoughts.

Alvaro Herrera <alvhe...@alvh.no-ip.org> 于2023年8月3日周四 17:02写道:

> On 2023-Aug-03, tender wang wrote:
>
> > I think  old "sub-FK" should not be dropped, that will be violates
> foreign
> > key constraint.
>
> Yeah, I've been playing more with the patch and it is definitely not
> doing the right things.  Just eyeballing the contents of pg_trigger and
> pg_constraint for partitions added by ALTER...ATTACH shows that the
> catalog contents are inconsistent with those added by CREATE TABLE
> PARTITION OF.
>
> --
> Álvaro Herrera         PostgreSQL Developer  —
> https://www.EnterpriseDB.com/
>
From d84395c7321c201a78661de0b41b76e71ab10678 Mon Sep 17 00:00:00 2001
From: "tender.wang" <tender.w...@openpie.com>
Date: Thu, 3 Aug 2023 17:23:06 +0800
Subject: [PATCH] Recheck foreign key of a partition is inherited from parent.

Previously, fk is inherited if conparentid(pg_constraint) is valid.
It is not enough and we should compare confrelid field to determine
fk is inherited.
---
 src/backend/commands/tablecmds.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 727f151750..1447433109 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -18556,6 +18556,8 @@ DetachPartitionFinalize(Relation rel, Relation partRel, 
bool concurrent,
                ForeignKeyCacheInfo *fk = lfirst(cell);
                HeapTuple       contup;
                Form_pg_constraint conform;
+               HeapTuple parentTup;
+               Form_pg_constraint parentForm;
                Constraint *fkconstraint;
                Oid                     insertTriggerOid,
                                        updateTriggerOid;
@@ -18573,6 +18575,23 @@ DetachPartitionFinalize(Relation rel, Relation 
partRel, bool concurrent,
                        continue;
                }
 
+               /* recheck confrelid field */
+               if (OidIsValid(conform->conparentid))
+               {
+                       parentTup = SearchSysCache1(CONSTROID, 
ObjectIdGetDatum(conform->conparentid));
+                       if (!HeapTupleIsValid(parentTup))
+                               elog(ERROR, "cache lookup failed for constraint 
%u", conform->conparentid);
+                       parentForm = (Form_pg_constraint) GETSTRUCT(parentTup);
+                       /* It is not inherited foreign keys */
+                       if (parentForm->confrelid != conform->confrelid)
+                       {
+                               ReleaseSysCache(contup);
+                               ReleaseSysCache(parentTup);
+                               continue;
+                       }
+                       ReleaseSysCache(parentTup);
+               }
+
                /* unset conparentid and adjust conislocal, coninhcount, etc. */
                ConstraintSetParentConstraint(fk->conoid, InvalidOid, 
InvalidOid);
 
-- 
2.25.1

Reply via email to