Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sUnVO-005jUS-Kc for pgsql-hackers@arkaria.postgresql.org; Fri, 19 Jul 2024 13:18:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1sUnVM-00GXY4-N9 for pgsql-hackers@arkaria.postgresql.org; Fri, 19 Jul 2024 13:18:37 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sUnVL-00GXXs-My for pgsql-hackers@lists.postgresql.org; Fri, 19 Jul 2024 13:18:36 +0000 Received: from fhigh1-smtp.messagingengine.com ([103.168.172.152]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sUnVJ-000NFR-4b for pgsql-hackers@postgresql.org; Fri, 19 Jul 2024 13:18:34 +0000 Received: from compute8.internal (compute8.nyi.internal [10.202.2.227]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 61C5D11403E2; Fri, 19 Jul 2024 09:18:31 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute8.internal (MEProxy); Fri, 19 Jul 2024 09:18:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1721395111; x= 1721481511; bh=+0qDMTzFmTWr4QjPArY0mZfWKuHIPROoJio1chXsg08=; b=f 6wGwRZo+12Cn8srve13bk3/7xyRg/hwhrQLFaVHTCqirji3QAqxlC3XHIPNJySc3 KQiQHcJDOTvAYuoIPlLIlb962+ODXb1soGDujk8F7YSHMaY/J34uAiMVnYe6iuco xt/fnvACVh+gKT3DPcoMdRm09B5RXOzL+bVejlqZSeK0/oGhExEJ/ddgLqzzrEvO E/eq+LQ+FPZSjRdTgz4KxISCQZvKbgj7NRogm94nwXKqxLANZdBAZoaRCp7Rgcew T/DrfyQnlrXln/SeRSvSXI9WMO+AUW3Hh9fr//8mGkQUTYjF95o3StClEN4zXmLj psoP/ZVchXC3cphGgQGbQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrhedugdeifecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpeffhffvvefukfggtggugfgjsehmkeerredttdejnecuhfhrohhmpeetlhhvrghr ohcujfgvrhhrvghrrgcuoegrlhhvhhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorhhgqe enucggtffrrghtthgvrhhnpeduleekkefgtddttedtkefguddvieffleetgeejiefhteeh keevfeettdduvdfhueenucffohhmrghinhepvghnthgvrhhprhhishgvuggsrdgtohhmne cuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghlvhhh vghrrhgvsegrlhhvhhdrnhhoqdhiphdrohhrgh X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 19 Jul 2024 09:18:30 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alvh.no-ip.org; s=schmee; t=1721395108; bh=4PVvJy6Fac71wPBYsNpadOFR0uz0FfWfRJ6OGVikLds=; h=Date:From:To:Cc:Subject:In-Reply-To:From; b=n8WFbh49vbs9RUy5h4SiKXaw8rSvaSsNP6clnE6s0P/xisdj1iGi4Oupwni9qDlTr JKBTWLuo9lVu/UZ3/963z2OcmS/UG8zcOLfXfymRNEUNrVn+4z934lJGeRbs1Gciq9 MPC3+K8PlouTGg0c9RZTriRAKXghOETwWzceVEbRyMDye7d5E753QGzwILZA1aBNCQ v+jvYiaiVzHlupYp41rMgK5my5tEIHzdbti9YQK7NrfJDAtpSm0AsQ9XTGDUcJU8YN alaONhpV1hsMR1mjAmv2LYXc4nQz1q73Lv1isM93veeQOTOZ20PBejbVjMDmTOzurA A63lFWYF6pzAA== Received: by schmee.alvh.no-ip.org (Postfix, from userid 1000) id C6747BE; Fri, 19 Jul 2024 15:18:28 +0200 (CEST) Date: Fri, 19 Jul 2024 15:18:28 +0200 From: Alvaro Herrera To: Tender Wang Cc: Jehan-Guillaume de Rorthais , "pgsql-hackers@postgresql.org" , Alexander Lakhin Subject: Re: [BUG] Fix DETACH with FK pointing to a partitioned table fails Message-ID: <202407191318.uecnw7oaidhu@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="pbb5725efu3pjse7" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --pbb5725efu3pjse7 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hello, I think the fix for the check triggers should be as the attached. Very close to what you did, but you were skipping some operations that needed to be kept. AFAICS this patch works correctly for the posted cases. I haven't looked at the action triggers yet; I think we need to create one trigger for each partition of the referenced side, so we need to loop instead of doing a single one. I find this pair of queries useful; they show which constraints exist and which triggers belong to each. We need to make the constraints and triggers match after a detach right as things would be if the just-detached partition were an individual table having the same foreign key. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ "People get annoyed when you try to debug them." (Larry Wall) --pbb5725efu3pjse7 Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0001-Fix-partition-detach-on-tables-with-FKs-to-partition.patch" From 925739ef0c6b64c73b021ed930f65f140004ceb5 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 19 Jul 2024 15:12:38 +0200 Subject: [PATCH] Fix partition detach on tables with FKs to partitioned tables --- src/backend/commands/tablecmds.c | 49 +++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 721d24783b..ca777d3c88 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -19185,8 +19185,11 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, { ForeignKeyCacheInfo *fk = lfirst(cell); HeapTuple contup; + HeapTuple parentConTup; Form_pg_constraint conform; + Form_pg_constraint parentConForm; Constraint *fkconstraint; + Oid parentConstrOid; Oid insertTriggerOid, updateTriggerOid; @@ -19203,22 +19206,46 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, continue; } + parentConstrOid = conform->conparentid; + /* unset conparentid and adjust conislocal, coninhcount, etc. */ ConstraintSetParentConstraint(fk->conoid, InvalidOid, InvalidOid); /* - * Also, look up the partition's "check" triggers corresponding to the - * constraint being detached and detach them from the parent triggers. + * Search for the partition's check triggers that implement the + * constraint being detached, and make them no longer children of the + * triggers on the parent table. However, if the referenced side is a + * partitioned table, there are no such check triggers (we know that + * the referenced side is partitioned because our constraint row points + * to a partition, whereas our parent constraint points to its parent + * partitioned table.) */ - GetForeignKeyCheckTriggers(trigrel, - fk->conoid, fk->confrelid, fk->conrelid, - &insertTriggerOid, &updateTriggerOid); - Assert(OidIsValid(insertTriggerOid)); - TriggerSetParentTrigger(trigrel, insertTriggerOid, InvalidOid, - RelationGetRelid(partRel)); - Assert(OidIsValid(updateTriggerOid)); - TriggerSetParentTrigger(trigrel, updateTriggerOid, InvalidOid, - RelationGetRelid(partRel)); + Assert(OidIsValid(conform->conparentid)); + parentConTup = SearchSysCache1(CONSTROID, + ObjectIdGetDatum(parentConstrOid)); + if (!HeapTupleIsValid(parentConTup)) + elog(ERROR, "cache lookup failed for constraint %u", + conform->conparentid); + parentConForm = (Form_pg_constraint) GETSTRUCT(parentConTup); + + if (parentConForm->conrelid != conform->conrelid) + { + /* + * Also, look up the partition's "check" triggers corresponding to the + * constraint being detached and detach them from the parent triggers. + */ + GetForeignKeyCheckTriggers(trigrel, + fk->conoid, fk->confrelid, fk->conrelid, + &insertTriggerOid, &updateTriggerOid); + Assert(OidIsValid(insertTriggerOid)); + TriggerSetParentTrigger(trigrel, insertTriggerOid, InvalidOid, + RelationGetRelid(partRel)); + Assert(OidIsValid(updateTriggerOid)); + TriggerSetParentTrigger(trigrel, updateTriggerOid, InvalidOid, + RelationGetRelid(partRel)); + } + + ReleaseSysCache(parentConTup); /* * Make the action triggers on the referenced relation. When this was -- 2.39.2 --pbb5725efu3pjse7--