1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Fix cloning of row triggers to sub-partitions

When row triggers exist in partitioned partitions that are not either
part of FKs or deferred unique constraints, they are not correctly
cloned to their partitions.  That's because they are marked "internal",
and those are purposefully skipped when doing the clone triggers dance.
Fix by relaxing the condition on which internal triggers are skipped.

Amit Langote initially diagnosed the problem and proposed a fix, but I
used a different approach.

Reported-by: Petr Fedorov
Discussion: https://postgr.es/m/6b3f0646-ba8c-b3a9-c62d-1c6651a1920f@phystech.edu
This commit is contained in:
Alvaro Herrera
2020-01-02 17:04:24 -03:00
parent 98b75c38c6
commit d732148398
3 changed files with 90 additions and 15 deletions

View File

@ -1981,15 +1981,22 @@ create trigger trg1 after insert on trigpart for each row execute procedure trig
create table trigpart2 partition of trigpart for values from (1000) to (2000);
create table trigpart3 (like trigpart);
alter table trigpart attach partition trigpart3 for values from (2000) to (3000);
create table trigpart4 partition of trigpart for values from (3000) to (4000) partition by range (a);
create table trigpart41 partition of trigpart4 for values from (3000) to (3500);
create table trigpart42 (like trigpart);
alter table trigpart4 attach partition trigpart42 for values from (3500) to (4000);
select tgrelid::regclass, tgname, tgfoid::regproc from pg_trigger
where tgrelid::regclass::text like 'trigpart%' order by tgrelid::regclass::text;
tgrelid | tgname | tgfoid
-----------+--------+-----------------
trigpart | trg1 | trigger_nothing
trigpart1 | trg1 | trigger_nothing
trigpart2 | trg1 | trigger_nothing
trigpart3 | trg1 | trigger_nothing
(4 rows)
tgrelid | tgname | tgfoid
------------+--------+-----------------
trigpart | trg1 | trigger_nothing
trigpart1 | trg1 | trigger_nothing
trigpart2 | trg1 | trigger_nothing
trigpart3 | trg1 | trigger_nothing
trigpart4 | trg1 | trigger_nothing
trigpart41 | trg1 | trigger_nothing
trigpart42 | trg1 | trigger_nothing
(7 rows)
drop trigger trg1 on trigpart1; -- fail
ERROR: cannot drop trigger trg1 on table trigpart1 because trigger trg1 on table trigpart requires it
@ -2003,12 +2010,15 @@ HINT: You can drop trigger trg1 on table trigpart instead.
drop table trigpart2; -- ok, trigger should be gone in that partition
select tgrelid::regclass, tgname, tgfoid::regproc from pg_trigger
where tgrelid::regclass::text like 'trigpart%' order by tgrelid::regclass::text;
tgrelid | tgname | tgfoid
-----------+--------+-----------------
trigpart | trg1 | trigger_nothing
trigpart1 | trg1 | trigger_nothing
trigpart3 | trg1 | trigger_nothing
(3 rows)
tgrelid | tgname | tgfoid
------------+--------+-----------------
trigpart | trg1 | trigger_nothing
trigpart1 | trg1 | trigger_nothing
trigpart3 | trg1 | trigger_nothing
trigpart4 | trg1 | trigger_nothing
trigpart41 | trg1 | trigger_nothing
trigpart42 | trg1 | trigger_nothing
(6 rows)
drop trigger trg1 on trigpart; -- ok, all gone
select tgrelid::regclass, tgname, tgfoid::regproc from pg_trigger

View File

@ -1366,6 +1366,10 @@ create trigger trg1 after insert on trigpart for each row execute procedure trig
create table trigpart2 partition of trigpart for values from (1000) to (2000);
create table trigpart3 (like trigpart);
alter table trigpart attach partition trigpart3 for values from (2000) to (3000);
create table trigpart4 partition of trigpart for values from (3000) to (4000) partition by range (a);
create table trigpart41 partition of trigpart4 for values from (3000) to (3500);
create table trigpart42 (like trigpart);
alter table trigpart4 attach partition trigpart42 for values from (3500) to (4000);
select tgrelid::regclass, tgname, tgfoid::regproc from pg_trigger
where tgrelid::regclass::text like 'trigpart%' order by tgrelid::regclass::text;
drop trigger trg1 on trigpart1; -- fail