Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jR3rP-0003DX-Mb for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2020 01:07:31 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1jR3qq-0007nO-OO for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2020 01:06:56 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jR3qq-0007nD-6G for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2020 01:06:56 +0000 Received: from mail-qt1-x829.google.com ([2607:f8b0:4864:20::829]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jR3qm-0002OK-KK for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2020 01:06:54 +0000 Received: by mail-qt1-x829.google.com with SMTP id o10so397733qtr.6 for ; Tue, 21 Apr 2020 18:06:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=tstpJV5zFSRXh3v0+Erh/J7uCSM8u/95/aqIv/mb0DM=; b=Ce2FX/BQNMSAK5Fpnj2HD1JUeT7RL4Lls24nWZlEokLy/zwBjgJmfHRljo7EML0Cb4 7DuYXM0uwJ6FOXDsgsVjpejbouqTP/rDt6hQS98e8iqocVk14R8AEbJ7HwDwnAnjhwDz gutY6ZcdrCRsFBlMGbjjop4xSLWwn6yQ3KJ3SzmXQItPDdx2wkfW6XO2Yp9UzkKRaIBg YWDBubAGRd17ZKaQkjV72ECjlBvesXY1UilXgQnnsuFZX6Rd/aRQfteyKtC3N8n3s5VO ZXhrFEUUz/5kw4a/BAK1dx22XilaNeBpGwt1J9Fp/Cwje+0IbyibpwAdYUpoDDri61pR BdeA== 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:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=tstpJV5zFSRXh3v0+Erh/J7uCSM8u/95/aqIv/mb0DM=; b=l2RVOEsPTUJ9SaLXhv2D2XpTkbmArS2NmVGAZKs1xzrGHUW034CizMpDILgJqok1bX kIEpIM/VfQl7RHqme78cn/wciCOmKMe0oZRLtPfLblrKdFNnm+e3WHiek7H4vmFw2LBR FOfOuUjFjMCa/NVSkf0dCyhWoeKlhR8DCP98/P8gspEDUcTjzxo5JwrHDspNq49cTHTu A2cNgqc6C0ueWbIVQADKZ1HCmZVWNuiN53FnqECfTqy1/hEt/v+u+pcx6RjZ8LpYVKMg 6LJLWvYGXZP5o9dEnk8fWD35YZwQB0bkoFWOy4g6l9xRic5YS7TWjme2Oh/hms3QEUYC sdrA== X-Gm-Message-State: AGi0Puawku3oMu8sTDHr0uLKil5V0WQmFLV09peJFHMuTfFLC8wrgFbI LG0OyKRrnpo+7w9V7F90zT+oDQ== X-Google-Smtp-Source: APiQypIjFDMeOR2frYJMxyGDoeVeFyF1lUM0Tb+MBRRShTg0IMLq1NR6df+ePcUtwzv9clsD20wpZQ== X-Received: by 2002:ac8:4907:: with SMTP id e7mr24440968qtq.300.1587517611428; Tue, 21 Apr 2020 18:06:51 -0700 (PDT) Received: from pryzbyj (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id 11sm2975684qkg.122.2020.04.21.18.06.49 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Apr 2020 18:06:50 -0700 (PDT) Received: by pryzbyj (Postfix, from userid 1000) id 8992D801457; Tue, 21 Apr 2020 20:06:48 -0500 (CDT) Date: Tue, 21 Apr 2020 20:06:48 -0500 From: Justin Pryzby To: Alvaro Herrera Cc: Amit Langote , Tom Lane , pgsql-hackers@lists.postgresql.org Subject: Re: DETACH PARTITION and FOR EACH ROW triggers on partitioned tables Message-ID: <20200422010648.GM3890@telsasoft.com> References: <20200420195740.GE3890@telsasoft.com> <20200421230330.GA23831@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="XMCwj5IQnwKtuyBG" Content-Disposition: inline In-Reply-To: <20200421230330.GA23831@alvherre.pgsql> User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --XMCwj5IQnwKtuyBG Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Tue, Apr 21, 2020 at 07:03:30PM -0400, Alvaro Herrera wrote: > On 2020-Apr-20, Justin Pryzby wrote: > > > On Mon, Apr 20, 2020 at 06:35:44PM +0900, Amit Langote wrote: > > > > Also, how about, for consistency, making the parent table labeling of > > > the trigger look similar to that for the foreign constraint, so > > > Triggers: > > > TABLE "f1" TRIGGER "trig" BEFORE INSERT ON f11 FOR EACH ROW EXECUTE FUNCTION trigfunc() > > > > I'll leave that for committer to decide. > > Pushed. Many thanks for this! Thanks for polishing it. I was just about to convince myself of the merits of doing it Amit's way :) I noticed a few issues: - should put \n's around Amit's subquery to make psql -E look pretty; - maybe should quote the TABLE, like \"%s\" ? #3 is that *if* we did it Amit's way, I *think* maybe we should show the parent's triggerdef, not the childs. It seems strange to me to say "TABLE trigpart .* INSERT ON trigpart3" - TABLE "trigpart" TRIGGER trg1 AFTER INSERT ON trigpart3 FOR EACH ROW EXECUTE FUNCTION trigger_nothing() + TABLE "trigpart" TRIGGER trg1 AFTER INSERT ON trigpart FOR EACH ROW EXECUTE FUNCTION trigger_nothing() -- Justin --XMCwj5IQnwKtuyBG Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6-0001-fixups-c33869cc3bfc42bce822251f2fa1a2a346f86cc5.patch" From 86ff4e592afe56d2611e22b63fa3f1268b583e58 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Fri, 3 Apr 2020 22:43:26 -0500 Subject: [PATCH v6 1/2] fixups: c33869cc3bfc42bce822251f2fa1a2a346f86cc5 --- src/bin/psql/describe.c | 14 +++++++------- src/test/regress/expected/triggers.out | 2 +- src/test/regress/sql/triggers.sql | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 8dca6d8bb4..5ef56f7a9d 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2947,12 +2947,12 @@ describeOneTableDetails(const char *schemaname, pset.sversion >= 80300 ? "t.tgconstraint <> 0 AS tgisinternal" : "false AS tgisinternal"), - (pset.sversion >= 130000 ? - "(SELECT (NULLIF(a.relid, t.tgrelid))::pg_catalog.regclass" - " FROM pg_catalog.pg_trigger AS u, " - " pg_catalog.pg_partition_ancestors(t.tgrelid) AS a" - " WHERE u.tgname = t.tgname AND u.tgrelid = a.relid" - " AND u.tgparentid = 0) AS parent" : + (pset.sversion >= 130000 ? "\n" + " (SELECT (NULLIF(a.relid, t.tgrelid))::pg_catalog.regclass\n" + " FROM pg_catalog.pg_trigger AS u,\n" + " pg_catalog.pg_partition_ancestors(t.tgrelid) AS a\n" + " WHERE u.tgname = t.tgname AND u.tgrelid = a.relid\n" + " AND u.tgparentid = 0) AS parent" : "NULL AS parent"), oid); if (pset.sversion >= 110000) @@ -3073,7 +3073,7 @@ describeOneTableDetails(const char *schemaname, /* Visually distinguish inherited triggers */ if (!PQgetisnull(result, i, 4)) - appendPQExpBuffer(&buf, ", ON TABLE %s", + appendPQExpBuffer(&buf, ", ON TABLE \"%s\"", PQgetvalue(result, i, 4)); printTableAddFooter(&cont, buf.data); diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index 5e76b3a47e..4104711c29 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -2065,7 +2065,7 @@ create trigger trg1 after insert on trigpart3 for each row execute procedure tri Triggers: trg1 AFTER INSERT ON trigpart3 FOR EACH ROW EXECUTE FUNCTION trigger_nothing() -alter table trigpart attach partition trigpart3 FOR VALUES FROM (2000) to (3000); -- fail +alter table trigpart attach partition trigpart3 for values from (2000) to (3000); -- fail ERROR: trigger "trg1" for relation "trigpart3" already exists drop table trigpart3; drop table trigpart; diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index e228d0a8a5..c359c6d3fa 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -1398,7 +1398,7 @@ select tgrelid::regclass::text, tgname, tgfoid::regproc, tgenabled, tgisinternal create table trigpart3 (like trigpart); create trigger trg1 after insert on trigpart3 for each row execute procedure trigger_nothing(); \d trigpart3 -alter table trigpart attach partition trigpart3 FOR VALUES FROM (2000) to (3000); -- fail +alter table trigpart attach partition trigpart3 for values from (2000) to (3000); -- fail drop table trigpart3; drop table trigpart; -- 2.17.0 --XMCwj5IQnwKtuyBG Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6-0002-show-inherited-triggers-Amit-s-way.patch" From 4712253f66e03f6666d57a7a7a971a9f00c492c6 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Mon, 20 Apr 2020 13:46:06 -0500 Subject: [PATCH v6 2/2] show inherited triggers Amit's way.. ..this also updates the query to avoid saying things like: TABLE trigpart .* INSERT ON trigpart3 --- src/bin/psql/describe.c | 42 +++++++++++++++++--------- src/test/regress/expected/triggers.out | 2 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 5ef56f7a9d..3b02eab84e 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2936,10 +2936,27 @@ describeOneTableDetails(const char *schemaname, PGresult *result; int tuples; - printfPQExpBuffer(&buf, + if (pset.sversion >= 130000) + { + printfPQExpBuffer(&buf, + "SELECT t.tgname, " + "pg_catalog.pg_get_triggerdef(COALESCE(u.oid, t.oid), true), " + "t.tgenabled, t.tgisinternal, a.relid AS othertable\n" + "FROM pg_catalog.pg_trigger t LEFT JOIN\n" + "pg_catalog.pg_partition_ancestors(t.tgrelid) AS a\n" + "ON true LEFT JOIN\n" + "pg_catalog.pg_trigger AS u ON\n" + "u.tgname = t.tgname AND u.tgrelid = a.relid\n" + "WHERE t.tgrelid = '%s' AND " + "(u.tgparentid = 0 OR a.relid IS NULL) AND \n", + oid); + } + else + { + printfPQExpBuffer(&buf, "SELECT t.tgname, " "pg_catalog.pg_get_triggerdef(t.oid%s), " - "t.tgenabled, %s, %s\n" + "t.tgenabled, %s, NULL AS parent\n" "FROM pg_catalog.pg_trigger t\n" "WHERE t.tgrelid = '%s' AND ", (pset.sversion >= 90000 ? ", true" : ""), @@ -2947,14 +2964,9 @@ describeOneTableDetails(const char *schemaname, pset.sversion >= 80300 ? "t.tgconstraint <> 0 AS tgisinternal" : "false AS tgisinternal"), - (pset.sversion >= 130000 ? "\n" - " (SELECT (NULLIF(a.relid, t.tgrelid))::pg_catalog.regclass\n" - " FROM pg_catalog.pg_trigger AS u,\n" - " pg_catalog.pg_partition_ancestors(t.tgrelid) AS a\n" - " WHERE u.tgname = t.tgname AND u.tgrelid = a.relid\n" - " AND u.tgparentid = 0) AS parent" : - "NULL AS parent"), oid); + } + if (pset.sversion >= 110000) appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D') \n" " OR EXISTS (SELECT 1 FROM pg_catalog.pg_depend WHERE objid = t.oid \n" @@ -3069,12 +3081,12 @@ describeOneTableDetails(const char *schemaname, if (usingpos) tgdef = usingpos + 9; - printfPQExpBuffer(&buf, " %s", tgdef); - - /* Visually distinguish inherited triggers */ - if (!PQgetisnull(result, i, 4)) - appendPQExpBuffer(&buf, ", ON TABLE \"%s\"", - PQgetvalue(result, i, 4)); + if (PQgetisnull(result, i, 4)) + printfPQExpBuffer(&buf, " %s", tgdef); + else + /* Visually distinguish inherited triggers */ + printfPQExpBuffer(&buf, " TABLE \"%s\" TRIGGER %s", + PQgetvalue(result, i, 4), tgdef); printTableAddFooter(&cont, buf.data); } diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index 4104711c29..a1b81f49ff 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -2033,7 +2033,7 @@ create trigger trg1 after insert on trigpart for each row execute procedure trig b | integer | | | Partition of: trigpart FOR VALUES FROM (2000) TO (3000) Triggers: - trg1 AFTER INSERT ON trigpart3 FOR EACH ROW EXECUTE FUNCTION trigger_nothing(), ON TABLE trigpart + TABLE "trigpart" TRIGGER trg1 AFTER INSERT ON trigpart3 FOR EACH ROW EXECUTE FUNCTION trigger_nothing() alter table trigpart detach partition trigpart3; drop trigger trg1 on trigpart3; -- fail due to "does not exist" -- 2.17.0 --XMCwj5IQnwKtuyBG--