]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Propagate trigger arguments to partitions
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 9 Jul 2019 21:16:36 +0000 (17:16 -0400)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 9 Jul 2019 21:16:36 +0000 (17:16 -0400)
We were creating the cloned triggers with an empty list of arguments,
losing the ones that had been specified by the user when creating the
trigger in the partitioned table.  Repair.

This was forgotten in commit 86f575948c77.

Author: Patrick McHardy
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/20190709130027.amr2cavjvo7rdvac@access1.trash.net
Discussion: https://postgr.es/m/15752-123bc90287986de4@postgresql.org

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

index c62922a1124fdc8252b4cf31084401b593529d8f..5fbe7242c42769a836362fb793c8112d049a606e 100644 (file)
@@ -15202,6 +15202,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
                Datum           value;
                bool            isnull;
                List       *cols = NIL;
+               List       *trigargs = NIL;
                MemoryContext oldcxt;
 
                /*
@@ -15266,11 +15267,31 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
                        }
                }
 
+               /* Reconstruct trigger arguments list. */
+               if (trigForm->tgnargs > 0)
+               {
+                       char       *p;
+
+                       value = heap_getattr(tuple, Anum_pg_trigger_tgargs,
+                                                                RelationGetDescr(pg_trigger), &isnull);
+                       if (isnull)
+                               elog(ERROR, "tgargs is null for trigger \"%s\" in partition \"%s\"",
+                                        NameStr(trigForm->tgname), RelationGetRelationName(partition));
+
+                       p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
+
+                       for (int i = 0; i < trigForm->tgnargs; i++)
+                       {
+                               trigargs = lappend(trigargs, makeString(pstrdup(p)));
+                               p += strlen(p) + 1;
+                       }
+               }
+
                trigStmt = makeNode(CreateTrigStmt);
                trigStmt->trigname = NameStr(trigForm->tgname);
                trigStmt->relation = NULL;
                trigStmt->funcname = NULL;      /* passed separately */
-               trigStmt->args = NULL;  /* passed separately */
+               trigStmt->args = trigargs;
                trigStmt->row = true;
                trigStmt->timing = trigForm->tgtype & TRIGGER_TYPE_TIMING_MASK;
                trigStmt->events = trigForm->tgtype & TRIGGER_TYPE_EVENT_MASK;
index f6c7a3fefc59ca9f1cad9a4fa595bb594623e2b5..a716827c77acd7bc6877609f8ad2de2772daf6e2 100644 (file)
@@ -1153,7 +1153,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
                         */
                        childStmt = (CreateTrigStmt *) copyObject(stmt);
                        childStmt->funcname = NIL;
-                       childStmt->args = NIL;
                        childStmt->whenClause = NULL;
 
                        /* If there is a WHEN clause, create a modified copy of it */
index 31dbc9bcfc9380df861251affff9f44f1cc3a430..5be0009f00f3a57daabacd34fbc67f62cc773235 100644 (file)
@@ -2092,6 +2092,30 @@ NOTICE:  trigger zzz on parted_trig_1_1 AFTER INSERT for ROW
 NOTICE:  trigger bbb on parted_trig_2 AFTER INSERT for ROW
 NOTICE:  trigger zzz on parted_trig_2 AFTER INSERT for ROW
 drop table parted_trig;
+-- Verify propagation of trigger arguments to partitions
+create table parted_trig (a int) partition by list (a);
+create table parted_trig1 partition of parted_trig for values in (1);
+create or replace function trigger_notice() returns trigger as $$
+  declare
+    arg1 text = TG_ARGV[0];
+    arg2 integer = TG_ARGV[1];
+  begin
+    raise notice 'trigger % on % % % for % args % %',
+               TG_NAME, TG_TABLE_NAME, TG_WHEN, TG_OP, TG_LEVEL, arg1, arg2;
+    return null;
+  end;
+  $$ language plpgsql;
+create trigger aaa after insert on parted_trig
+   for each row execute procedure trigger_notice('quirky', 1);
+-- Verify propagation of trigger arguments to partitions attached after creating trigger
+create table parted_trig2 partition of parted_trig for values in (2);
+create table parted_trig3 (like parted_trig);
+alter table parted_trig attach partition parted_trig3 for values in (3);
+insert into parted_trig values (1), (2), (3);
+NOTICE:  trigger aaa on parted_trig1 AFTER INSERT for ROW args quirky 1
+NOTICE:  trigger aaa on parted_trig2 AFTER INSERT for ROW args quirky 1
+NOTICE:  trigger aaa on parted_trig3 AFTER INSERT for ROW args quirky 1
+drop table parted_trig;
 -- test irregular partitions (i.e., different column definitions),
 -- including that the WHEN clause works
 create function bark(text) returns bool language plpgsql immutable
index 60b3e22c5c24759916af8e8ed009955c0c398564..6376046c5daf1a0dc063a53b93e26441851c218f 100644 (file)
@@ -1465,6 +1465,29 @@ create trigger qqq after insert on parted_trig_1_1 for each row execute procedur
 insert into parted_trig values (50), (1500);
 drop table parted_trig;
 
+-- Verify propagation of trigger arguments to partitions
+create table parted_trig (a int) partition by list (a);
+create table parted_trig1 partition of parted_trig for values in (1);
+create or replace function trigger_notice() returns trigger as $$
+  declare
+    arg1 text = TG_ARGV[0];
+    arg2 integer = TG_ARGV[1];
+  begin
+    raise notice 'trigger % on % % % for % args % %',
+               TG_NAME, TG_TABLE_NAME, TG_WHEN, TG_OP, TG_LEVEL, arg1, arg2;
+    return null;
+  end;
+  $$ language plpgsql;
+create trigger aaa after insert on parted_trig
+   for each row execute procedure trigger_notice('quirky', 1);
+
+-- Verify propagation of trigger arguments to partitions attached after creating trigger
+create table parted_trig2 partition of parted_trig for values in (2);
+create table parted_trig3 (like parted_trig);
+alter table parted_trig attach partition parted_trig3 for values in (3);
+insert into parted_trig values (1), (2), (3);
+drop table parted_trig;
+
 -- test irregular partitions (i.e., different column definitions),
 -- including that the WHEN clause works
 create function bark(text) returns bool language plpgsql immutable