Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fb9e93a

Browse files
committed
Fix duplicate primary keys in partitions
When using the CREATE TABLE .. PARTITION OF syntax, it's possible to cause a partition to get two primary keys if the parent already has one. Tighten the check to disallow that. Reported-by: Rajkumar Raghuwanshi Author: Amul Sul Discussion: https://postgr.es/m/CAKcux6=OnSV3-qd8Gb6W=KPPwcCz6Fe_O_MQYjTa24__Xn8XxA@mail.gmail.com
1 parent 09921f3 commit fb9e93a

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

src/backend/catalog/index.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,12 @@ index_check_primary_key(Relation heapRel,
218218
int i;
219219

220220
/*
221-
* If ALTER TABLE, check that there isn't already a PRIMARY KEY. In CREATE
222-
* TABLE, we have faith that the parser rejected multiple pkey clauses;
223-
* and CREATE INDEX doesn't have a way to say PRIMARY KEY, so it's no
224-
* problem either.
221+
* If ALTER TABLE and CREATE TABLE .. PARTITION OF, check that there isn't
222+
* already a PRIMARY KEY. In CREATE TABLE for an ordinary relations, we
223+
* have faith that the parser rejected multiple pkey clauses; and CREATE
224+
* INDEX doesn't have a way to say PRIMARY KEY, so it's no problem either.
225225
*/
226-
if (is_alter_table &&
226+
if ((is_alter_table || heapRel->rd_rel->relispartition) &&
227227
relationHasPrimaryKey(heapRel))
228228
{
229229
ereport(ERROR,

src/test/regress/expected/indexing.out

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,8 +800,24 @@ Indexes:
800800
"idxpart_pkey" PRIMARY KEY, btree (a)
801801
Number of partitions: 0
802802

803+
-- multiple primary key on child should fail
804+
create table failpart partition of idxpart (b primary key) for values from (0) to (100);
805+
ERROR: multiple primary keys for table "failpart" are not allowed
803806
drop table idxpart;
804-
-- but not if you fail to use the full partition key
807+
-- primary key on child is okay if there's no PK in the parent, though
808+
create table idxpart (a int) partition by range (a);
809+
create table idxpart1pk partition of idxpart (a primary key) for values from (0) to (100);
810+
\d idxpart1pk
811+
Table "public.idxpart1pk"
812+
Column | Type | Collation | Nullable | Default
813+
--------+---------+-----------+----------+---------
814+
a | integer | | not null |
815+
Partition of: idxpart FOR VALUES FROM (0) TO (100)
816+
Indexes:
817+
"idxpart1pk_pkey" PRIMARY KEY, btree (a)
818+
819+
drop table idxpart;
820+
-- Failing to use the full partition key is not allowed
805821
create table idxpart (a int unique, b int) partition by range (a, b);
806822
ERROR: insufficient columns in UNIQUE constraint definition
807823
DETAIL: UNIQUE constraint on table "idxpart" lacks column "b" which is part of the partition key.

src/test/regress/sql/indexing.sql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,16 @@ drop table idxpart;
401401
-- Verify that it works to add primary key / unique to partitioned tables
402402
create table idxpart (a int primary key, b int) partition by range (a);
403403
\d idxpart
404+
-- multiple primary key on child should fail
405+
create table failpart partition of idxpart (b primary key) for values from (0) to (100);
406+
drop table idxpart;
407+
-- primary key on child is okay if there's no PK in the parent, though
408+
create table idxpart (a int) partition by range (a);
409+
create table idxpart1pk partition of idxpart (a primary key) for values from (0) to (100);
410+
\d idxpart1pk
404411
drop table idxpart;
405412

406-
-- but not if you fail to use the full partition key
413+
-- Failing to use the full partition key is not allowed
407414
create table idxpart (a int unique, b int) partition by range (a, b);
408415
create table idxpart (a int, b int unique) partition by range (a, b);
409416
create table idxpart (a int primary key, b int) partition by range (b, a);

0 commit comments

Comments
 (0)