aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2020-03-18 18:58:05 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2020-03-18 18:58:05 -0300
commit487e9861d0cf83e9100ad0d0369147db3ef4ea73 (patch)
treef3cc3f4e8c89154a4d12800c1d4df86ca0161cc3 /src/test
parentb029395f5e616e0f2b1131b2c7ecb6640f30c055 (diff)
downloadpostgresql-487e9861d0cf83e9100ad0d0369147db3ef4ea73.tar.gz
postgresql-487e9861d0cf83e9100ad0d0369147db3ef4ea73.zip
Enable BEFORE row-level triggers for partitioned tables
... with the limitation that the tuple must remain in the same partition. Reviewed-by: Ashutosh Bapat Discussion: https://postgr.es/m/20200227165158.GA2071@alvherre.pgsql
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/triggers.out78
-rw-r--r--src/test/regress/sql/triggers.sql55
2 files changed, 127 insertions, 6 deletions
diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index 22e65cc1ece..e9da4ef983e 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -1958,10 +1958,6 @@ drop table my_table;
create table parted_trig (a int) partition by list (a);
create function trigger_nothing() returns trigger
language plpgsql as $$ begin end; $$;
-create trigger failed before insert or update or delete on parted_trig
- for each row execute procedure trigger_nothing();
-ERROR: "parted_trig" is a partitioned table
-DETAIL: Partitioned tables cannot have BEFORE / FOR EACH ROW triggers.
create trigger failed instead of update on parted_trig
for each row execute procedure trigger_nothing();
ERROR: "parted_trig" is a table
@@ -2246,6 +2242,80 @@ NOTICE: aasvogel <- woof!
NOTICE: trigger parted_trig on parted1_irreg AFTER INSERT for ROW: (a,b)=(3,aasvogel)
NOTICE: trigger parted_trig_odd on parted1_irreg AFTER INSERT for ROW: (a,b)=(3,aasvogel)
drop table parted_irreg_ancestor;
+-- Before triggers and partitions
+create table parted (a int, b int, c text) partition by list (a);
+create table parted_1 partition of parted for values in (1)
+ partition by list (b);
+create table parted_1_1 partition of parted_1 for values in (1);
+create function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.a = new.a + 1;
+ return new;
+end;
+$$;
+insert into parted values (1, 1, 'uno uno v1'); -- works
+create trigger t before insert or update or delete on parted
+ for each row execute function parted_trigfunc();
+insert into parted values (1, 1, 'uno uno v2'); -- fail
+ERROR: moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported
+DETAIL: Before executing trigger "t", the row was to be in partition "public.parted_1_1".
+update parted set c = c || 'v3'; -- fail
+ERROR: moving row to another partition during a BEFORE trigger is not supported
+DETAIL: Before executing trigger "t", the row was to be in partition "public.parted_1_1".
+create or replace function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.b = new.b + 1;
+ return new;
+end;
+$$;
+insert into parted values (1, 1, 'uno uno v4'); -- fail
+ERROR: moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported
+DETAIL: Before executing trigger "t", the row was to be in partition "public.parted_1_1".
+update parted set c = c || 'v5'; -- fail
+ERROR: moving row to another partition during a BEFORE trigger is not supported
+DETAIL: Before executing trigger "t", the row was to be in partition "public.parted_1_1".
+create or replace function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.c = new.c || ' and so';
+ return new;
+end;
+$$;
+insert into parted values (1, 1, 'uno uno'); -- works
+update parted set c = c || ' v6'; -- works
+select tableoid::regclass, * from parted;
+ tableoid | a | b | c
+------------+---+---+--------------------------
+ parted_1_1 | 1 | 1 | uno uno v1 v6 and so
+ parted_1_1 | 1 | 1 | uno uno and so v6 and so
+(2 rows)
+
+drop table parted;
+create table parted (a int, b int, c text) partition by list ((a + b));
+create or replace function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.a = new.a + new.b;
+ return new;
+end;
+$$;
+create table parted_1 partition of parted for values in (1, 2);
+create table parted_2 partition of parted for values in (3, 4);
+create trigger t before insert or update on parted
+ for each row execute function parted_trigfunc();
+insert into parted values (0, 1, 'zero win');
+insert into parted values (1, 1, 'one fail');
+ERROR: moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported
+DETAIL: Before executing trigger "t", the row was to be in partition "public.parted_1".
+insert into parted values (1, 2, 'two fail');
+ERROR: moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported
+DETAIL: Before executing trigger "t", the row was to be in partition "public.parted_2".
+select * from parted;
+ a | b | c
+---+---+----------
+ 1 | 1 | zero win
+(1 row)
+
+drop table parted;
+drop function parted_trigfunc();
--
-- Constraint triggers and partitioned tables
create table parted_constr_ancestor (a int, b text)
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index 0f61fdf0ea2..80ffbb4b028 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -1348,8 +1348,6 @@ drop table my_table;
create table parted_trig (a int) partition by list (a);
create function trigger_nothing() returns trigger
language plpgsql as $$ begin end; $$;
-create trigger failed before insert or update or delete on parted_trig
- for each row execute procedure trigger_nothing();
create trigger failed instead of update on parted_trig
for each row execute procedure trigger_nothing();
create trigger failed after update on parted_trig
@@ -1561,6 +1559,59 @@ insert into parted1_irreg values ('aardwolf', 2);
insert into parted_irreg_ancestor values ('aasvogel', 3);
drop table parted_irreg_ancestor;
+-- Before triggers and partitions
+create table parted (a int, b int, c text) partition by list (a);
+create table parted_1 partition of parted for values in (1)
+ partition by list (b);
+create table parted_1_1 partition of parted_1 for values in (1);
+create function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.a = new.a + 1;
+ return new;
+end;
+$$;
+insert into parted values (1, 1, 'uno uno v1'); -- works
+create trigger t before insert or update or delete on parted
+ for each row execute function parted_trigfunc();
+insert into parted values (1, 1, 'uno uno v2'); -- fail
+update parted set c = c || 'v3'; -- fail
+create or replace function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.b = new.b + 1;
+ return new;
+end;
+$$;
+insert into parted values (1, 1, 'uno uno v4'); -- fail
+update parted set c = c || 'v5'; -- fail
+create or replace function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.c = new.c || ' and so';
+ return new;
+end;
+$$;
+insert into parted values (1, 1, 'uno uno'); -- works
+update parted set c = c || ' v6'; -- works
+select tableoid::regclass, * from parted;
+
+drop table parted;
+create table parted (a int, b int, c text) partition by list ((a + b));
+create or replace function parted_trigfunc() returns trigger language plpgsql as $$
+begin
+ new.a = new.a + new.b;
+ return new;
+end;
+$$;
+create table parted_1 partition of parted for values in (1, 2);
+create table parted_2 partition of parted for values in (3, 4);
+create trigger t before insert or update on parted
+ for each row execute function parted_trigfunc();
+insert into parted values (0, 1, 'zero win');
+insert into parted values (1, 1, 'one fail');
+insert into parted values (1, 2, 'two fail');
+select * from parted;
+drop table parted;
+drop function parted_trigfunc();
+
--
-- Constraint triggers and partitioned tables
create table parted_constr_ancestor (a int, b text)