mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Fix ALTER TABLE .. ATTACH PARTITION ... DEFAULT
If the table being attached contained values that contradict the default
partition's partition constraint, it would fail to complain, because
CommandCounterIncrement changes in 4dba331cb3
coupled with some bogus
coding in the existing ValidatePartitionConstraints prevented the
partition constraint from being validated after all -- or rather, it
caused to constraint to become an empty one, always succeeding.
Fix by not re-reading the OID of the default partition in
ATExecAttachPartition. To forestall similar problems, revise the
existing code:
* rename routine from ValidatePartitionConstraints() to
QueuePartitionConstraintValidation, to better represent what it
actually does.
* add an Assert() to make sure that when queueing a constraint for a
partition we're not overwriting a constraint previously queued.
* add an Assert() that we don't try to invoke the special-purpose
validation of the default partition when attaching the default
partition itself.
While at it, change some loops to obtain partition OIDs from
partdesc->oids rather than find_all_inheritors; reduce the lock level
of partitions being scanned from AccessExclusiveLock to ShareLock;
rewrite QueuePartitionConstraintValidation in a recursive fashion rather
than repetitive.
Author: Álvaro Herrera. Tests written by Amit Langote
Reported-by: Rushabh Lathia
Diagnosed-by: Kyotaro HORIGUCHI, who also provided the initial fix.
Reviewed-by: Kyotaro HORIGUCHI, Amit Langote, Jeevan Ladhe
Discussion: https://postgr.es/m/CAGPqQf0W+v-Ci_qNV_5R3A=Z9LsK4+jO7LzgddRncpp_rrnJqQ@mail.gmail.com
This commit is contained in:
@ -3887,3 +3887,19 @@ ALTER TABLE attmp ALTER COLUMN i RESET (n_distinct_inherited);
|
||||
ANALYZE attmp;
|
||||
DROP TABLE attmp;
|
||||
DROP USER regress_alter_table_user1;
|
||||
-- check that violating rows are correctly reported when attaching as the
|
||||
-- default partition
|
||||
create table defpart_attach_test (a int) partition by list (a);
|
||||
create table defpart_attach_test1 partition of defpart_attach_test for values in (1);
|
||||
create table defpart_attach_test_d (like defpart_attach_test);
|
||||
insert into defpart_attach_test_d values (1), (2);
|
||||
-- error because its constraint as the default partition would be violated
|
||||
-- by the row containing 1
|
||||
alter table defpart_attach_test attach partition defpart_attach_test_d default;
|
||||
ERROR: partition constraint is violated by some row
|
||||
delete from defpart_attach_test_d where a = 1;
|
||||
alter table defpart_attach_test_d add check (a > 1);
|
||||
-- should be attached successfully and without needing to be scanned
|
||||
alter table defpart_attach_test attach partition defpart_attach_test_d default;
|
||||
INFO: partition constraint for table "defpart_attach_test_d" is implied by existing constraints
|
||||
drop table defpart_attach_test;
|
||||
|
@ -2564,3 +2564,21 @@ ANALYZE attmp;
|
||||
DROP TABLE attmp;
|
||||
|
||||
DROP USER regress_alter_table_user1;
|
||||
|
||||
-- check that violating rows are correctly reported when attaching as the
|
||||
-- default partition
|
||||
create table defpart_attach_test (a int) partition by list (a);
|
||||
create table defpart_attach_test1 partition of defpart_attach_test for values in (1);
|
||||
create table defpart_attach_test_d (like defpart_attach_test);
|
||||
insert into defpart_attach_test_d values (1), (2);
|
||||
|
||||
-- error because its constraint as the default partition would be violated
|
||||
-- by the row containing 1
|
||||
alter table defpart_attach_test attach partition defpart_attach_test_d default;
|
||||
delete from defpart_attach_test_d where a = 1;
|
||||
alter table defpart_attach_test_d add check (a > 1);
|
||||
|
||||
-- should be attached successfully and without needing to be scanned
|
||||
alter table defpart_attach_test attach partition defpart_attach_test_d default;
|
||||
|
||||
drop table defpart_attach_test;
|
||||
|
Reference in New Issue
Block a user