mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Fix dependency handling of partitions and inheritance for ON COMMIT
This commit fixes a set of issues with ON COMMIT actions when used on partitioned tables and tables with inheritance children: - Applying ON COMMIT DROP on a partitioned table with partitions or on a table with inheritance children caused a failure at commit time, with complains about the children being already dropped as all relations are dropped one at the same time. - Applying ON COMMIT DELETE on a partition relying on a partitioned table which uses ON COMMIT DROP would cause the partition truncation to fail as the parent is removed first. The solution to the first problem is to handle the removal of all the dependencies in one go instead of dropping relations one-by-one, based on a suggestion from Álvaro Herrera. So instead all the relation OIDs to remove are gathered and then processed in one round of multiple deletions. The solution to the second problem is to reorder the actions, with truncation happening first and relation drop done after. Even if it means that a partition could be first truncated, then immediately dropped if its partitioned table is dropped, this has the merit to keep the code simple as there is no need to do existence checks on the relations to drop. Contrary to a manual TRUNCATE on a partitioned table, ON COMMIT DELETE does not cascade to its partitions. The ON COMMIT action defined on each partition gets the priority. Author: Michael Paquier Reviewed-by: Amit Langote, Álvaro Herrera, Robert Haas Discussion: https://postgr.es/m/68f17907-ec98-1192-f99f-8011400517f5@lab.ntt.co.jp Backpatch-through: 10
This commit is contained in:
@ -216,3 +216,88 @@ select * from temp_parted_oncommit;
|
||||
(0 rows)
|
||||
|
||||
drop table temp_parted_oncommit;
|
||||
-- Check dependencies between ON COMMIT actions with a partitioned
|
||||
-- table and its partitions. Using ON COMMIT DROP on a parent removes
|
||||
-- the whole set.
|
||||
begin;
|
||||
create temp table temp_parted_oncommit_test (a int)
|
||||
partition by list (a) on commit drop;
|
||||
create temp table temp_parted_oncommit_test1
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (1) on commit delete rows;
|
||||
create temp table temp_parted_oncommit_test2
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (2) on commit drop;
|
||||
insert into temp_parted_oncommit_test values (1), (2);
|
||||
commit;
|
||||
-- no relations remain in this case.
|
||||
select relname from pg_class where relname like 'temp_parted_oncommit_test%';
|
||||
relname
|
||||
---------
|
||||
(0 rows)
|
||||
|
||||
-- Using ON COMMIT DELETE on a partitioned table does not remove
|
||||
-- all rows if partitions preserve their data.
|
||||
begin;
|
||||
create temp table temp_parted_oncommit_test (a int)
|
||||
partition by list (a) on commit delete rows;
|
||||
create temp table temp_parted_oncommit_test1
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (1) on commit preserve rows;
|
||||
create temp table temp_parted_oncommit_test2
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (2) on commit drop;
|
||||
insert into temp_parted_oncommit_test values (1), (2);
|
||||
commit;
|
||||
-- Data from the remaining partition is still here as its rows are
|
||||
-- preserved.
|
||||
select * from temp_parted_oncommit_test;
|
||||
a
|
||||
---
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- two relations remain in this case.
|
||||
select relname from pg_class where relname like 'temp_parted_oncommit_test%';
|
||||
relname
|
||||
----------------------------
|
||||
temp_parted_oncommit_test
|
||||
temp_parted_oncommit_test1
|
||||
(2 rows)
|
||||
|
||||
drop table temp_parted_oncommit_test;
|
||||
-- Check dependencies between ON COMMIT actions with inheritance trees.
|
||||
-- Using ON COMMIT DROP on a parent removes the whole set.
|
||||
begin;
|
||||
create temp table temp_inh_oncommit_test (a int) on commit drop;
|
||||
create temp table temp_inh_oncommit_test1 ()
|
||||
inherits(temp_inh_oncommit_test) on commit delete rows;
|
||||
insert into temp_inh_oncommit_test1 values (1);
|
||||
commit;
|
||||
-- no relations remain in this case
|
||||
select relname from pg_class where relname like 'temp_inh_oncommit_test%';
|
||||
relname
|
||||
---------
|
||||
(0 rows)
|
||||
|
||||
-- Data on the parent is removed, and the child goes away.
|
||||
begin;
|
||||
create temp table temp_inh_oncommit_test (a int) on commit delete rows;
|
||||
create temp table temp_inh_oncommit_test1 ()
|
||||
inherits(temp_inh_oncommit_test) on commit drop;
|
||||
insert into temp_inh_oncommit_test1 values (1);
|
||||
insert into temp_inh_oncommit_test values (1);
|
||||
commit;
|
||||
select * from temp_inh_oncommit_test;
|
||||
a
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
-- one relation remains
|
||||
select relname from pg_class where relname like 'temp_inh_oncommit_test%';
|
||||
relname
|
||||
------------------------
|
||||
temp_inh_oncommit_test
|
||||
(1 row)
|
||||
|
||||
drop table temp_inh_oncommit_test;
|
||||
|
@ -165,3 +165,62 @@ commit;
|
||||
-- partitions are emptied by the previous commit
|
||||
select * from temp_parted_oncommit;
|
||||
drop table temp_parted_oncommit;
|
||||
|
||||
-- Check dependencies between ON COMMIT actions with a partitioned
|
||||
-- table and its partitions. Using ON COMMIT DROP on a parent removes
|
||||
-- the whole set.
|
||||
begin;
|
||||
create temp table temp_parted_oncommit_test (a int)
|
||||
partition by list (a) on commit drop;
|
||||
create temp table temp_parted_oncommit_test1
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (1) on commit delete rows;
|
||||
create temp table temp_parted_oncommit_test2
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (2) on commit drop;
|
||||
insert into temp_parted_oncommit_test values (1), (2);
|
||||
commit;
|
||||
-- no relations remain in this case.
|
||||
select relname from pg_class where relname like 'temp_parted_oncommit_test%';
|
||||
-- Using ON COMMIT DELETE on a partitioned table does not remove
|
||||
-- all rows if partitions preserve their data.
|
||||
begin;
|
||||
create temp table temp_parted_oncommit_test (a int)
|
||||
partition by list (a) on commit delete rows;
|
||||
create temp table temp_parted_oncommit_test1
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (1) on commit preserve rows;
|
||||
create temp table temp_parted_oncommit_test2
|
||||
partition of temp_parted_oncommit_test
|
||||
for values in (2) on commit drop;
|
||||
insert into temp_parted_oncommit_test values (1), (2);
|
||||
commit;
|
||||
-- Data from the remaining partition is still here as its rows are
|
||||
-- preserved.
|
||||
select * from temp_parted_oncommit_test;
|
||||
-- two relations remain in this case.
|
||||
select relname from pg_class where relname like 'temp_parted_oncommit_test%';
|
||||
drop table temp_parted_oncommit_test;
|
||||
|
||||
-- Check dependencies between ON COMMIT actions with inheritance trees.
|
||||
-- Using ON COMMIT DROP on a parent removes the whole set.
|
||||
begin;
|
||||
create temp table temp_inh_oncommit_test (a int) on commit drop;
|
||||
create temp table temp_inh_oncommit_test1 ()
|
||||
inherits(temp_inh_oncommit_test) on commit delete rows;
|
||||
insert into temp_inh_oncommit_test1 values (1);
|
||||
commit;
|
||||
-- no relations remain in this case
|
||||
select relname from pg_class where relname like 'temp_inh_oncommit_test%';
|
||||
-- Data on the parent is removed, and the child goes away.
|
||||
begin;
|
||||
create temp table temp_inh_oncommit_test (a int) on commit delete rows;
|
||||
create temp table temp_inh_oncommit_test1 ()
|
||||
inherits(temp_inh_oncommit_test) on commit drop;
|
||||
insert into temp_inh_oncommit_test1 values (1);
|
||||
insert into temp_inh_oncommit_test values (1);
|
||||
commit;
|
||||
select * from temp_inh_oncommit_test;
|
||||
-- one relation remains
|
||||
select relname from pg_class where relname like 'temp_inh_oncommit_test%';
|
||||
drop table temp_inh_oncommit_test;
|
||||
|
Reference in New Issue
Block a user