Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iS4Xh-00041g-13 for pgsql-hackers@arkaria.postgresql.org; Tue, 05 Nov 2019 19:31:05 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1iS4Wh-00010v-T4 for pgsql-hackers@arkaria.postgresql.org; Tue, 05 Nov 2019 19:30:03 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iS4Wh-00010i-KL for pgsql-hackers@lists.postgresql.org; Tue, 05 Nov 2019 19:30:03 +0000 Received: from mail-yb1-xb42.google.com ([2607:f8b0:4864:20::b42]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iS4We-0003Z6-H4 for pgsql-hackers@lists.postgresql.org; Tue, 05 Nov 2019 19:30:03 +0000 Received: by mail-yb1-xb42.google.com with SMTP id i15so945781ybq.0 for ; Tue, 05 Nov 2019 11:30:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:subject:message-id:mime-version:content-disposition :content-transfer-encoding:user-agent; bh=x99xWgjUx0WyOf6C0wXdMWVxs9waoZKWVU3unLnD59M=; b=qn03it1+U3CFR/O5APOCUDmgxC4MhhKN01nXmM0QSysjqBKMW48WEjAist6uCi1/vh 2zpyWgWh84/WkyfbEE9a9tT5/zs/ggVh/ApdbexwGrcf4m9DEiIU+guiT9wSXzi1aLoW LHv5kyzgp84NLxIYx1G4avCNslS5+IWttx/CYaBW50m4/yfs+JEsbsqF0UeUVKUFJD/8 ncTxWzTbP1RkdtQ0HbxsSOszz99uIsaxQUiuYS2uA1vKGJStaHMd08JLkFE0VLkyEiXa 2By3bFBo6UPBoa1fBZ5vcg9vNx80LQNUXyUJ7+UpH6/4sDB+MPj/GjZ7dN2OzEBjIygC X9zg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition:content-transfer-encoding:user-agent; bh=x99xWgjUx0WyOf6C0wXdMWVxs9waoZKWVU3unLnD59M=; b=RfTXvqSwegKYp+whseYKVfaPLOWP7SUaB1hjEjkdFriCfEiL3sPKPf6w1oZd0UQZ73 IqV0WvQkd8sDPf+6cza16Q5RBeBAlL54E7znrb8wxBVv97qp7kc4q5YfbU2361dzW0jT xpURb6B1syNasH5SNDqIHFO8rYXguXceHG/GnrZIpr4NiWLqWyFKLqJ7IBFuEGaVQTW2 V4ozYncfqU7TbdYCHI5nBsxN1hjgH7WTpJ0FHe3jUhqBMiqYXB3KJGqR2Rkt0dbQUEzp vFI1LYwBzSfF8//+c4jD3Y7vqd6XRvksM3DJAXBbc9PStr03UDoaw9hbdOR0uoPVybm9 EYxA== X-Gm-Message-State: APjAAAVQy57lM0wRSYUUW0mRYBAAfxvnXyAa6TBOtQtX11+ruVoPVmZ8 1V0mnxfVP9ZvpaNRIuA39Em/nUb7TVDmwZp++kXLGn3bJ9HuHxuZpwFj9+mwO4tPj3aDRqgHsgD J+0YxpnXHjE6T8KL5zVThAZSnCZgdxnLHfDE5VtCkhqFEtcNcWEU0I2Y+LVBkAlshygQTotNDxs s/SkolFQ7Ywh6xyM3i X-Google-Smtp-Source: APXvYqzpNLM4Hnzts7NH4XUbazNWsaNJAeBOsd6oXOyo72HswqjreR9hUsgYvMSLk4+9AIp9VSWybw== X-Received: by 2002:a25:d28d:: with SMTP id j135mr29946397ybg.34.1572982197493; Tue, 05 Nov 2019 11:29:57 -0800 (PST) Received: from nimloth.alvh.no-ip.org ([66.115.168.24]) by smtp.gmail.com with ESMTPSA id x78sm1993223ywg.108.2019.11.05.11.29.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Nov 2019 11:29:56 -0800 (PST) Received: by nimloth.alvh.no-ip.org (Postfix, from userid 1000) id 5C562302246; Tue, 5 Nov 2019 16:19:48 -0300 (-03) Date: Tue, 5 Nov 2019 16:19:48 -0300 From: Alvaro Herrera To: Pg Hackers Subject: deferrable FK constraints on partitioned rels Message-ID: <20191105191948.GA11182@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="EeQfGwPcQSOJBaQU" Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.10.1 (2018-07-13) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --EeQfGwPcQSOJBaQU Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit While messing around, I noticed that SET CONSTRAINTS ... DEFERRED does not work with partitioned tables. I had some code to cover this case, but it has a bug that prevents it from working at all: the sanity check that verifies whether triggers exist fails. The attached patch fixes this problem: it merely removes the sanity check. With that, everything works. (Another approach I tried was to split out constraints in partitioned tables vs. constraints in regular ones. That's indeed workable, but it requires us to do two additional syscache access per partition for get_rel_relkind, which seems excessive.) The UNIQUE DEFERRABLE case works after the patch. (I didn't try without the patch.) -- Álvaro Herrera Developer, https://www.PostgreSQL.org/ --EeQfGwPcQSOJBaQU Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-Fix-deferred-constraints-on-partitioned-rels.patch" From e08007504e1c0ec88e583b7cba6f6b08effe26d7 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Tue, 5 Nov 2019 12:52:27 -0300 Subject: [PATCH] Fix deferred constraints on partitioned rels --- src/backend/commands/trigger.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 57c98912d5..5e302fee64 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -5362,6 +5362,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) Relation conrel; Relation tgrel; List *conoidlist = NIL; + List *pcl = NIL; List *tgoidlist = NIL; ListCell *lc; @@ -5440,7 +5441,18 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup); if (con->condeferrable) - conoidlist = lappend_oid(conoidlist, con->oid); + { + /* + * If we found it and it's deferrable, save it to one + * of the lists depending on whether it belongs to a + * partitioned table. + */ + if (get_rel_relkind(con->conrelid) == + RELKIND_PARTITIONED_TABLE) + pcl = lappend_oid(pcl, con->oid); + else + conoidlist = lappend_oid(conoidlist, con->oid); + } else if (stmt->deferred) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -5472,12 +5484,12 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) } /* - * Scan for any possible descendants of the constraints. We append - * whatever we find to the same list that we're scanning; this has the - * effect that we create new scans for those, too, so if there are - * further descendents, we'll also catch them. + * Scan for any possible descendants of constraints in partitioned + * tables. If we find any that are on further partitioned tables, + * append them to the list we're scanning. This ensures we process + * all descendant relations. */ - foreach(lc, conoidlist) + foreach(lc, pcl) { Oid parent = lfirst_oid(lc); ScanKeyData key; @@ -5495,7 +5507,10 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple); - conoidlist = lappend_oid(conoidlist, con->oid); + if (get_rel_relkind(con->conrelid) == RELKIND_PARTITIONED_TABLE) + pcl = lappend_oid(pcl, con->oid); + else + conoidlist = lappend_oid(conoidlist, con->oid); } systable_endscan(scan); -- 2.20.1 --EeQfGwPcQSOJBaQU--