ATTACH PARTITION: Don't match a PK with a UNIQUE constraint
When matching constraints in AttachPartitionEnsureIndexes() we weren't testing the constraint type, which could make a UNIQUE key lacking a not-null constraint incorrectly satisfy a primary key requirement. Fix this by testing that the constraint types match. (Other possible mismatches are verified by comparing index properties.) Discussion: https://postgr.es/m/202402051447.wimb4xmtiiyb@alvherre.pgsql
This commit is contained in:
parent
9dfcac8e15
commit
cee8db3f68
|
@ -19550,6 +19550,11 @@ AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel)
|
|||
/* no dice */
|
||||
if (!OidIsValid(cldConstrOid))
|
||||
continue;
|
||||
|
||||
/* Ensure they're both the same type of constraint */
|
||||
if (get_constraint_type(constraintOid) !=
|
||||
get_constraint_type(cldConstrOid))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* bingo. */
|
||||
|
|
|
@ -1133,6 +1133,28 @@ get_constraint_index(Oid conoid)
|
|||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_constraint_type
|
||||
* Return the pg_constraint.contype value for the given constraint.
|
||||
*
|
||||
* No frills.
|
||||
*/
|
||||
char
|
||||
get_constraint_type(Oid conoid)
|
||||
{
|
||||
HeapTuple tp;
|
||||
char contype;
|
||||
|
||||
tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
|
||||
if (!HeapTupleIsValid(tp))
|
||||
elog(ERROR, "cache lookup failed for constraint %u", conoid);
|
||||
|
||||
contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
|
||||
ReleaseSysCache(tp);
|
||||
|
||||
return contype;
|
||||
}
|
||||
|
||||
/* ---------- LANGUAGE CACHE ---------- */
|
||||
|
||||
char *
|
||||
|
|
|
@ -100,6 +100,8 @@ extern char *get_collation_name(Oid colloid);
|
|||
extern bool get_collation_isdeterministic(Oid colloid);
|
||||
extern char *get_constraint_name(Oid conoid);
|
||||
extern Oid get_constraint_index(Oid conoid);
|
||||
extern char get_constraint_type(Oid conoid);
|
||||
|
||||
extern char *get_language_name(Oid langoid, bool missing_ok);
|
||||
extern Oid get_opclass_family(Oid opclass);
|
||||
extern Oid get_opclass_input_type(Oid opclass);
|
||||
|
|
|
@ -1006,6 +1006,22 @@ Inherits: cnn_grandchild,
|
|||
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
|
||||
ERROR: constraint "cnn_parent_pkey" of relation "cnn_parent" does not exist
|
||||
-- keeps these tables around, for pg_upgrade testing
|
||||
-- A primary key shouldn't attach to a unique constraint
|
||||
create table cnn2_parted (a int primary key) partition by list (a);
|
||||
create table cnn2_part1 (a int unique);
|
||||
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
|
||||
\d+ cnn2_part1
|
||||
Table "public.cnn2_part1"
|
||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+---------+---------+--------------+-------------
|
||||
a | integer | | not null | | plain | |
|
||||
Partition of: cnn2_parted FOR VALUES IN (1)
|
||||
Partition constraint: ((a IS NOT NULL) AND (a = 1))
|
||||
Indexes:
|
||||
"cnn2_part1_pkey" PRIMARY KEY, btree (a)
|
||||
"cnn2_part1_a_key" UNIQUE CONSTRAINT, btree (a)
|
||||
|
||||
drop table cnn2_parted;
|
||||
-- ensure columns in partitions are marked not-null
|
||||
create table cnn2_parted(a int primary key) partition by list (a);
|
||||
create table cnn2_part1(a int);
|
||||
|
|
|
@ -657,6 +657,13 @@ ALTER TABLE cnn_parent ADD PRIMARY KEY USING INDEX b_uq;
|
|||
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
|
||||
-- keeps these tables around, for pg_upgrade testing
|
||||
|
||||
-- A primary key shouldn't attach to a unique constraint
|
||||
create table cnn2_parted (a int primary key) partition by list (a);
|
||||
create table cnn2_part1 (a int unique);
|
||||
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
|
||||
\d+ cnn2_part1
|
||||
drop table cnn2_parted;
|
||||
|
||||
-- ensure columns in partitions are marked not-null
|
||||
create table cnn2_parted(a int primary key) partition by list (a);
|
||||
create table cnn2_part1(a int);
|
||||
|
|
Loading…
Reference in New Issue