aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/tablecmds.c7
-rw-r--r--src/backend/partitioning/partbounds.c24
-rw-r--r--src/test/regress/expected/alter_table.out9
-rw-r--r--src/test/regress/expected/create_table.out14
-rw-r--r--src/test/regress/sql/alter_table.sql9
-rw-r--r--src/test/regress/sql/create_table.sql14
6 files changed, 70 insertions, 7 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 7dcd634a1ae..fd67d2a8413 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15682,6 +15682,13 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
defaultrel = table_open(defaultPartOid, NoLock);
defPartConstraint =
get_proposed_default_constraint(partBoundConstraint);
+ /*
+ * Map the Vars in the constraint expression from rel's attnos to
+ * defaultrel's.
+ */
+ defPartConstraint =
+ map_partition_varattnos(defPartConstraint,
+ 1, defaultrel, rel, NULL);
QueuePartitionConstraintValidation(wqueue, defaultrel,
defPartConstraint, true);
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 99d26de7e64..f3c9236ad56 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -1237,6 +1237,13 @@ check_default_partition_contents(Relation parent, Relation default_rel,
: get_qual_for_range(parent, new_spec, false);
def_part_constraints =
get_proposed_default_constraint(new_part_constraints);
+ /*
+ * Map the Vars in the constraint expression from parent's attnos to
+ * default_rel's.
+ */
+ def_part_constraints =
+ map_partition_varattnos(def_part_constraints, 1, default_rel,
+ parent, NULL);
/*
* If the existing constraints on the default partition imply that it will
@@ -1265,7 +1272,6 @@ check_default_partition_contents(Relation parent, Relation default_rel,
{
Oid part_relid = lfirst_oid(lc);
Relation part_rel;
- Expr *constr;
Expr *partition_constraint;
EState *estate;
ExprState *partqualstate = NULL;
@@ -1281,6 +1287,15 @@ check_default_partition_contents(Relation parent, Relation default_rel,
part_rel = table_open(part_relid, NoLock);
/*
+ * Map the Vars in the constraint expression from default_rel's
+ * the sub-partition's.
+ */
+ partition_constraint = make_ands_explicit(def_part_constraints);
+ partition_constraint = (Expr *)
+ map_partition_varattnos((List *) partition_constraint, 1,
+ part_rel, default_rel, NULL);
+
+ /*
* If the partition constraints on default partition child imply
* that it will not contain any row that would belong to the new
* partition, we can avoid scanning the child table.
@@ -1297,7 +1312,10 @@ check_default_partition_contents(Relation parent, Relation default_rel,
}
}
else
+ {
part_rel = default_rel;
+ partition_constraint = make_ands_explicit(def_part_constraints);
+ }
/*
* Only RELKIND_RELATION relations (i.e. leaf partitions) need to be
@@ -1318,10 +1336,6 @@ check_default_partition_contents(Relation parent, Relation default_rel,
continue;
}
- constr = linitial(def_part_constraints);
- partition_constraint = (Expr *)
- map_partition_varattnos((List *) constr,
- 1, part_rel, parent, NULL);
estate = CreateExecutorState();
/* Build expression execution states for partition check quals */
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index a639601f666..e687150511b 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -4008,7 +4008,8 @@ DROP USER regress_alter_table_user1;
-- 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);
+create table defpart_attach_test_d (b int, a int);
+alter table defpart_attach_test_d drop b;
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
@@ -4019,6 +4020,12 @@ 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
+-- check that attaching a partition correctly reports any rows in the default
+-- partition that should not be there for the new partition to be attached
+-- successfully
+create table defpart_attach_test_2 (like defpart_attach_test_d);
+alter table defpart_attach_test attach partition defpart_attach_test_2 for values in (2);
+ERROR: updated partition constraint for default partition would be violated by some row
drop table defpart_attach_test;
-- check combinations of temporary and permanent relations when attaching
-- partitions.
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 204441e7596..262abf2bfb8 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -1119,3 +1119,17 @@ select tableoid::regclass from volatile_partbound_test;
(1 row)
drop table volatile_partbound_test;
+-- test the case where a check constraint on default partition allows
+-- to avoid scanning it when adding a new partition
+create table defcheck (a int, b int) partition by list (b);
+create table defcheck_def (a int, c int, b int);
+alter table defcheck_def drop c;
+alter table defcheck attach partition defcheck_def default;
+alter table defcheck_def add check (b <= 0 and b is not null);
+create table defcheck_1 partition of defcheck for values in (1, null);
+INFO: updated partition constraint for default partition "defcheck_def" is implied by existing constraints
+-- test that complex default partition constraints are enforced correctly
+insert into defcheck_def values (0, 0);
+create table defcheck_0 partition of defcheck for values in (0);
+ERROR: updated partition constraint for default partition "defcheck_def" would be violated by some row
+drop table defcheck;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 0369909b508..8016f8a823a 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -2648,7 +2648,8 @@ DROP USER regress_alter_table_user1;
-- 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);
+create table defpart_attach_test_d (b int, a int);
+alter table defpart_attach_test_d drop b;
insert into defpart_attach_test_d values (1), (2);
-- error because its constraint as the default partition would be violated
@@ -2660,6 +2661,12 @@ 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;
+-- check that attaching a partition correctly reports any rows in the default
+-- partition that should not be there for the new partition to be attached
+-- successfully
+create table defpart_attach_test_2 (like defpart_attach_test_d);
+alter table defpart_attach_test attach partition defpart_attach_test_2 for values in (2);
+
drop table defpart_attach_test;
-- check combinations of temporary and permanent relations when attaching
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 751c0d39f5d..9c6d86a0bfd 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -856,3 +856,17 @@ create table volatile_partbound_test2 partition of volatile_partbound_test for v
insert into volatile_partbound_test values (current_timestamp);
select tableoid::regclass from volatile_partbound_test;
drop table volatile_partbound_test;
+
+-- test the case where a check constraint on default partition allows
+-- to avoid scanning it when adding a new partition
+create table defcheck (a int, b int) partition by list (b);
+create table defcheck_def (a int, c int, b int);
+alter table defcheck_def drop c;
+alter table defcheck attach partition defcheck_def default;
+alter table defcheck_def add check (b <= 0 and b is not null);
+create table defcheck_1 partition of defcheck for values in (1, null);
+
+-- test that complex default partition constraints are enforced correctly
+insert into defcheck_def values (0, 0);
+create table defcheck_0 partition of defcheck for values in (0);
+drop table defcheck;