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 1iS6OQ-0008CM-JL for pgsql-hackers@arkaria.postgresql.org; Tue, 05 Nov 2019 21:29:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1iS6OP-00064f-A9 for pgsql-hackers@arkaria.postgresql.org; Tue, 05 Nov 2019 21:29:37 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1iS6OO-00064X-Pk for pgsql-hackers@lists.postgresql.org; Tue, 05 Nov 2019 21:29:37 +0000 Received: from mail-yb1-xb44.google.com ([2607:f8b0:4864:20::b44]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1iS6OK-0006Zy-1Q for pgsql-hackers@lists.postgresql.org; Tue, 05 Nov 2019 21:29:35 +0000 Received: by mail-yb1-xb44.google.com with SMTP id i12so3988447ybg.2 for ; Tue, 05 Nov 2019 13:29:31 -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:in-reply-to:user-agent; bh=UEp6iGt4roZ6HSV/d0GHKFSUxC88Uao9WUM152ZyIJY=; b=1laAGOe67Tkhj6+ZbiPbCdq79c5VRwaKBNJKM2z2VZn+WGKN78pdfFl/3wS/IYEH0b UAiFNOa91cSFY57/rT41nh++cDkNbeerIR11OwaIpfNaRxyVYsx3m1oG1ISDL3W15HiX DxVcwmQXiXYBGD7fSJn8V+lEjziqkhl5V3U6UkLzol3JYadtLLgOlmEbO+rltbqgUGnJ uqheI0ZIuSdQ6lYZBpeEMpGwEBJpe4wtQ2iGZsPoxhC8lDRR15uHVEuXD0u1xovnwCHi RkibMqXsF+U0ANO1tcKyGPiMsJgx5APZmvYd/rZBzxTtZO49qaEUqDLVeNgkEti62PdZ GUqg== 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:in-reply-to :user-agent; bh=UEp6iGt4roZ6HSV/d0GHKFSUxC88Uao9WUM152ZyIJY=; b=IIuT4hYYmIzyfA2CF4dBo0yz/1qtYw59n5s7K+tWwvgm74hBh4wtGJjUcK7iZyMcn1 5CIvvCibVXp0nE/SMbq6f6pgL1az02Klb3/erExF+ZP0VsjkNvG7dZIyu5CZOw7NDTWQ c4g9DnHW/ORhfO3NKpPyz7Za2q2PJsaFk50OkQLJ2qZx/n1XX1YZRgeyTFCXp3ng/BFy VQnataZZmnI7DkbihWScWHQAk/iOfwl2Z9u67SDvVKYNp44Klg3jpYY4A3k2eB4hj3fS wrYI9g2hLqMeVMuLQfC9zthmadjEDYAXTfxTihWmY7mMMOgiP6tA3qg8pTTCg77GCyO8 vyRw== X-Gm-Message-State: APjAAAUsED0IZbxbSuKheGtAN7SsughVpiAaEZ8qE2IpaL8c0uYpujRh kDjWAH+8Y+jsF0noWajZpXUfHL9fBf0fhCs9BQqvSd4kwSrb8kKC3K3ZmdM4kEVOyo/O9F0syJp /mlZldLD5sVwvkMxXeL3dqEIGJqRcqRtAm5sKv8+9zLrbWRBZN42/1jqsrAHQ5lva1vs/RX85JS WJaRkak36tBOwh6aii X-Google-Smtp-Source: APXvYqyQCR08sSdgbwbpvrdqs600sj81P9k7n9x+nJbOJnMoPBvBSaCO7O2VKY2ZQTSN/fjhdFiEcw== X-Received: by 2002:a25:c385:: with SMTP id t127mr29068191ybf.139.1572989370409; Tue, 05 Nov 2019 13:29:30 -0800 (PST) Received: from nimloth.alvh.no-ip.org ([66.115.168.20]) by smtp.gmail.com with ESMTPSA id l76sm17009355ywl.24.2019.11.05.13.29.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Nov 2019 13:29:29 -0800 (PST) Received: by nimloth.alvh.no-ip.org (Postfix, from userid 1000) id 0A1DE3024BD; Tue, 5 Nov 2019 18:29:16 -0300 (-03) Date: Tue, 5 Nov 2019 18:29:16 -0300 From: Alvaro Herrera To: Pg Hackers Subject: Re: deferrable FK constraints on partitioned rels Message-ID: <20191105212915.GA11324@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="fdj2RfSjLxBAspz7" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20191105191948.GA11182@alvherre.pgsql> User-Agent: Mutt/1.10.1 (2018-07-13) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --fdj2RfSjLxBAspz7 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit On 2019-Nov-05, Alvaro Herrera wrote: > 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.) Uh, somehow I posted a previous version of the patch that implements my rejected approach, instead of the final version I described. Here's the real patch (which also includes tests). -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --fdj2RfSjLxBAspz7 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-Fix-deferred-constraints-on-partitioned-rels.patch" From 567f0b172564feeb055226b38b81da37e2d0b2bf 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 | 10 -------- src/test/regress/expected/foreign_key.out | 31 +++++++++++++++++++++++ src/test/regress/sql/foreign_key.sql | 25 ++++++++++++++++++ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 57c98912d5..e2048c19f7 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -5512,13 +5512,10 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) foreach(lc, conoidlist) { Oid conoid = lfirst_oid(lc); - bool found; ScanKeyData skey; SysScanDesc tgscan; HeapTuple htup; - found = false; - ScanKeyInit(&skey, Anum_pg_trigger_tgconstraint, BTEqualStrategyNumber, F_OIDEQ, @@ -5539,16 +5536,9 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt) */ if (pg_trigger->tgdeferrable) tgoidlist = lappend_oid(tgoidlist, pg_trigger->oid); - - found = true; } systable_endscan(tgscan); - - /* Safety check: a deferrable constraint should have triggers */ - if (!found) - elog(ERROR, "no triggers found for constraint with OID %u", - conoid); } table_close(tgrel, AccessShareLock); diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 894084f94f..2014d38a8b 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -2267,6 +2267,37 @@ INSERT INTO fk4 VALUES (50); ALTER TABLE fk ATTACH PARTITION fk4 FOR VALUES IN (50); ERROR: insert or update on table "fk4" violates foreign key constraint "fk_a_fkey" DETAIL: Key (a)=(50) is not present in table "pk". +-- Verify constraint deferrability +CREATE SCHEMA fkpart9; +SET search_path TO fkpart9; +CREATE TABLE pk (a int PRIMARY KEY) PARTITION BY LIST (a); +CREATE TABLE pk1 PARTITION OF pk FOR VALUES IN (1, 2) PARTITION BY LIST (a); +CREATE TABLE pk11 PARTITION OF pk1 FOR VALUES IN (1); +CREATE TABLE pk3 PARTITION OF pk FOR VALUES IN (3); +CREATE TABLE fk (a int REFERENCES pk DEFERRABLE INITIALLY IMMEDIATE); +INSERT INTO fk VALUES (1); -- should fail +ERROR: insert or update on table "fk" violates foreign key constraint "fk_a_fkey" +DETAIL: Key (a)=(1) is not present in table "pk". +BEGIN; +SET CONSTRAINTS fk_a_fkey DEFERRED; +INSERT INTO fk VALUES (1); +COMMIT; -- should fail +ERROR: insert or update on table "fk" violates foreign key constraint "fk_a_fkey" +DETAIL: Key (a)=(1) is not present in table "pk". +BEGIN; +SET CONSTRAINTS fk_a_fkey DEFERRED; +INSERT INTO fk VALUES (1); +INSERT INTO pk VALUES (1); +COMMIT; -- OK +BEGIN; +SET CONSTRAINTS fk_a_fkey DEFERRED; +DELETE FROM pk WHERE a = 1; +DELETE FROM fk WHERE a = 1; +COMMIT; -- OK +DROP SCHEMA fkpart9 CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table pk +drop cascades to table fk -- Verify ON UPDATE/DELETE behavior CREATE SCHEMA fkpart6; SET search_path TO fkpart6; diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql index b67bef01df..63db7f667a 100644 --- a/src/test/regress/sql/foreign_key.sql +++ b/src/test/regress/sql/foreign_key.sql @@ -1595,6 +1595,31 @@ CREATE TABLE fk4 (LIKE fk); INSERT INTO fk4 VALUES (50); ALTER TABLE fk ATTACH PARTITION fk4 FOR VALUES IN (50); +-- Verify constraint deferrability +CREATE SCHEMA fkpart9; +SET search_path TO fkpart9; +CREATE TABLE pk (a int PRIMARY KEY) PARTITION BY LIST (a); +CREATE TABLE pk1 PARTITION OF pk FOR VALUES IN (1, 2) PARTITION BY LIST (a); +CREATE TABLE pk11 PARTITION OF pk1 FOR VALUES IN (1); +CREATE TABLE pk3 PARTITION OF pk FOR VALUES IN (3); +CREATE TABLE fk (a int REFERENCES pk DEFERRABLE INITIALLY IMMEDIATE); +INSERT INTO fk VALUES (1); -- should fail +BEGIN; +SET CONSTRAINTS fk_a_fkey DEFERRED; +INSERT INTO fk VALUES (1); +COMMIT; -- should fail +BEGIN; +SET CONSTRAINTS fk_a_fkey DEFERRED; +INSERT INTO fk VALUES (1); +INSERT INTO pk VALUES (1); +COMMIT; -- OK +BEGIN; +SET CONSTRAINTS fk_a_fkey DEFERRED; +DELETE FROM pk WHERE a = 1; +DELETE FROM fk WHERE a = 1; +COMMIT; -- OK +DROP SCHEMA fkpart9 CASCADE; + -- Verify ON UPDATE/DELETE behavior CREATE SCHEMA fkpart6; SET search_path TO fkpart6; -- 2.20.1 --fdj2RfSjLxBAspz7--