Skip to content

Commit cee8db3

Browse files
committed
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
1 parent 9dfcac8 commit cee8db3

File tree

5 files changed

+52
-0
lines changed

5 files changed

+52
-0
lines changed

src/backend/commands/tablecmds.c

+5
Original file line numberDiff line numberDiff line change
@@ -19550,6 +19550,11 @@ AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel)
1955019550
/* no dice */
1955119551
if (!OidIsValid(cldConstrOid))
1955219552
continue;
19553+
19554+
/* Ensure they're both the same type of constraint */
19555+
if (get_constraint_type(constraintOid) !=
19556+
get_constraint_type(cldConstrOid))
19557+
continue;
1955319558
}
1955419559

1955519560
/* bingo. */

src/backend/utils/cache/lsyscache.c

+22
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,28 @@ get_constraint_index(Oid conoid)
11331133
return InvalidOid;
11341134
}
11351135

1136+
/*
1137+
* get_constraint_type
1138+
* Return the pg_constraint.contype value for the given constraint.
1139+
*
1140+
* No frills.
1141+
*/
1142+
char
1143+
get_constraint_type(Oid conoid)
1144+
{
1145+
HeapTuple tp;
1146+
char contype;
1147+
1148+
tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1149+
if (!HeapTupleIsValid(tp))
1150+
elog(ERROR, "cache lookup failed for constraint %u", conoid);
1151+
1152+
contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
1153+
ReleaseSysCache(tp);
1154+
1155+
return contype;
1156+
}
1157+
11361158
/* ---------- LANGUAGE CACHE ---------- */
11371159

11381160
char *

src/include/utils/lsyscache.h

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ extern char *get_collation_name(Oid colloid);
100100
extern bool get_collation_isdeterministic(Oid colloid);
101101
extern char *get_constraint_name(Oid conoid);
102102
extern Oid get_constraint_index(Oid conoid);
103+
extern char get_constraint_type(Oid conoid);
104+
103105
extern char *get_language_name(Oid langoid, bool missing_ok);
104106
extern Oid get_opclass_family(Oid opclass);
105107
extern Oid get_opclass_input_type(Oid opclass);

src/test/regress/expected/constraints.out

+16
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,22 @@ Inherits: cnn_grandchild,
10061006
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
10071007
ERROR: constraint "cnn_parent_pkey" of relation "cnn_parent" does not exist
10081008
-- keeps these tables around, for pg_upgrade testing
1009+
-- A primary key shouldn't attach to a unique constraint
1010+
create table cnn2_parted (a int primary key) partition by list (a);
1011+
create table cnn2_part1 (a int unique);
1012+
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
1013+
\d+ cnn2_part1
1014+
Table "public.cnn2_part1"
1015+
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1016+
--------+---------+-----------+----------+---------+---------+--------------+-------------
1017+
a | integer | | not null | | plain | |
1018+
Partition of: cnn2_parted FOR VALUES IN (1)
1019+
Partition constraint: ((a IS NOT NULL) AND (a = 1))
1020+
Indexes:
1021+
"cnn2_part1_pkey" PRIMARY KEY, btree (a)
1022+
"cnn2_part1_a_key" UNIQUE CONSTRAINT, btree (a)
1023+
1024+
drop table cnn2_parted;
10091025
-- ensure columns in partitions are marked not-null
10101026
create table cnn2_parted(a int primary key) partition by list (a);
10111027
create table cnn2_part1(a int);

src/test/regress/sql/constraints.sql

+7
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,13 @@ ALTER TABLE cnn_parent ADD PRIMARY KEY USING INDEX b_uq;
657657
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
658658
-- keeps these tables around, for pg_upgrade testing
659659

660+
-- A primary key shouldn't attach to a unique constraint
661+
create table cnn2_parted (a int primary key) partition by list (a);
662+
create table cnn2_part1 (a int unique);
663+
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
664+
\d+ cnn2_part1
665+
drop table cnn2_parted;
666+
660667
-- ensure columns in partitions are marked not-null
661668
create table cnn2_parted(a int primary key) partition by list (a);
662669
create table cnn2_part1(a int);

0 commit comments

Comments
 (0)