Don't clone internal triggers to partitions
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 3 Apr 2018 22:01:34 +0000 (19:01 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 3 Apr 2018 22:08:25 +0000 (19:08 -0300)
Trigger cloning to partitions was supposed to occur for user-visible
triggers only, but during development the protection that prevented it
from occurring to internal triggers was lost.  Reinstate it, as well as
add a test case to ensure internal triggers (in the tested case,
triggers implementing a deferred unique constraint) are not cloned.
Without the code fix, the partitions in the test end up with different
numbers of triggers, which is clearly wrong ...

Bug in 86f575948c77.

Discussion: https://postgr.es/m/20180403214903.ozfagwjcpk337uw7@alvherre.pgsql

src/backend/commands/tablecmds.c
src/test/regress/expected/triggers.out
src/test/regress/sql/triggers.sql

index c8da82217d4f7d9cea7572a3652f388b287278fd..c0f987cc8144cf3d380c59242e1013e94b9c4c44 100644 (file)
@@ -14336,6 +14336,10 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
        if (!TRIGGER_FOR_ROW(trigForm->tgtype))
            continue;
 
+       /* We don't clone internal triggers, either */
+       if (trigForm->tgisinternal)
+           continue;
+
        /*
         * Complain if we find an unexpected trigger type.
         */
index 7f4a94ef7dc82cc7a1777df3e6e14f5b9218135d..a29b7b1d08d0273b9d4d442b19dca2660b629c0e 100644 (file)
@@ -2234,6 +2234,29 @@ NOTICE:  trigger parted_trigger on parted_trigger_3_1 AFTER UPDATE for ROW: (a,b
 NOTICE:  trigger parted_trigger on parted_trigger_3_2 AFTER UPDATE for ROW: (a,b)=(2003,eeeeb)
 drop table parted_trigger;
 drop function trigger_notice_ab();
+-- Make sure we don't end up with unnecessary copies of triggers, when
+-- cloning them.
+create table trg_clone (a int) partition by range (a);
+create table trg_clone1 partition of trg_clone for values from (0) to (1000);
+alter table trg_clone add constraint uniq unique (a) deferrable;
+create table trg_clone2 partition of trg_clone for values from (1000) to (2000);
+create table trg_clone3 partition of trg_clone for values from (2000) to (3000)
+  partition by range (a);
+create table trg_clone_3_3 partition of trg_clone3 for values from (2000) to (2100);
+select tgrelid::regclass, count(*) from pg_trigger
+  where tgrelid::regclass in ('trg_clone', 'trg_clone1', 'trg_clone2',
+   'trg_clone3', 'trg_clone_3_3')
+  group by tgrelid::regclass order by tgrelid::regclass;
+    tgrelid    | count 
+---------------+-------
+ trg_clone     |     1
+ trg_clone1    |     1
+ trg_clone2    |     1
+ trg_clone3    |     1
+ trg_clone_3_3 |     1
+(5 rows)
+
+drop table trg_clone;
 --
 -- Test the interaction between transition tables and both kinds of
 -- inheritance.  We'll dump the contents of the transition tables in a
index b51c884eee49a15ed82397f1f371858c8cf56c82..b08b83bf5fa8316e0dfd5bc255d5ef29aed13e9a 100644 (file)
@@ -1578,6 +1578,21 @@ drop table parted_trigger;
 
 drop function trigger_notice_ab();
 
+-- Make sure we don't end up with unnecessary copies of triggers, when
+-- cloning them.
+create table trg_clone (a int) partition by range (a);
+create table trg_clone1 partition of trg_clone for values from (0) to (1000);
+alter table trg_clone add constraint uniq unique (a) deferrable;
+create table trg_clone2 partition of trg_clone for values from (1000) to (2000);
+create table trg_clone3 partition of trg_clone for values from (2000) to (3000)
+  partition by range (a);
+create table trg_clone_3_3 partition of trg_clone3 for values from (2000) to (2100);
+select tgrelid::regclass, count(*) from pg_trigger
+  where tgrelid::regclass in ('trg_clone', 'trg_clone1', 'trg_clone2',
+   'trg_clone3', 'trg_clone_3_3')
+  group by tgrelid::regclass order by tgrelid::regclass;
+drop table trg_clone;
+
 --
 -- Test the interaction between transition tables and both kinds of
 -- inheritance.  We'll dump the contents of the transition tables in a