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
This commit is contained in:
parent
e97c4d967b
commit
ff347f8aff
@ -218,12 +218,12 @@ index_check_primary_key(Relation heapRel,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If ALTER TABLE, check that there isn't already a PRIMARY KEY. In CREATE
|
* If ALTER TABLE and CREATE TABLE .. PARTITION OF, check that there isn't
|
||||||
* TABLE, we have faith that the parser rejected multiple pkey clauses;
|
* already a PRIMARY KEY. In CREATE TABLE for an ordinary relations, we
|
||||||
* and CREATE INDEX doesn't have a way to say PRIMARY KEY, so it's no
|
* have faith that the parser rejected multiple pkey clauses; and CREATE
|
||||||
* problem either.
|
* INDEX doesn't have a way to say PRIMARY KEY, so it's no problem either.
|
||||||
*/
|
*/
|
||||||
if (is_alter_table &&
|
if ((is_alter_table || heapRel->rd_rel->relispartition) &&
|
||||||
relationHasPrimaryKey(heapRel))
|
relationHasPrimaryKey(heapRel))
|
||||||
{
|
{
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
|
@ -800,8 +800,24 @@ Indexes:
|
|||||||
"idxpart_pkey" PRIMARY KEY, btree (a)
|
"idxpart_pkey" PRIMARY KEY, btree (a)
|
||||||
Number of partitions: 0
|
Number of partitions: 0
|
||||||
|
|
||||||
|
-- multiple primary key on child should fail
|
||||||
|
create table failpart partition of idxpart (b primary key) for values from (0) to (100);
|
||||||
|
ERROR: multiple primary keys for table "failpart" are not allowed
|
||||||
drop table idxpart;
|
drop table idxpart;
|
||||||
-- but not if you fail to use the full partition key
|
-- primary key on child is okay if there's no PK in the parent, though
|
||||||
|
create table idxpart (a int) partition by range (a);
|
||||||
|
create table idxpart1pk partition of idxpart (a primary key) for values from (0) to (100);
|
||||||
|
\d idxpart1pk
|
||||||
|
Table "public.idxpart1pk"
|
||||||
|
Column | Type | Collation | Nullable | Default
|
||||||
|
--------+---------+-----------+----------+---------
|
||||||
|
a | integer | | not null |
|
||||||
|
Partition of: idxpart FOR VALUES FROM (0) TO (100)
|
||||||
|
Indexes:
|
||||||
|
"idxpart1pk_pkey" PRIMARY KEY, btree (a)
|
||||||
|
|
||||||
|
drop table idxpart;
|
||||||
|
-- Failing to use the full partition key is not allowed
|
||||||
create table idxpart (a int unique, b int) partition by range (a, b);
|
create table idxpart (a int unique, b int) partition by range (a, b);
|
||||||
ERROR: insufficient columns in UNIQUE constraint definition
|
ERROR: insufficient columns in UNIQUE constraint definition
|
||||||
DETAIL: UNIQUE constraint on table "idxpart" lacks column "b" which is part of the partition key.
|
DETAIL: UNIQUE constraint on table "idxpart" lacks column "b" which is part of the partition key.
|
||||||
|
@ -401,9 +401,16 @@ drop table idxpart;
|
|||||||
-- Verify that it works to add primary key / unique to partitioned tables
|
-- Verify that it works to add primary key / unique to partitioned tables
|
||||||
create table idxpart (a int primary key, b int) partition by range (a);
|
create table idxpart (a int primary key, b int) partition by range (a);
|
||||||
\d idxpart
|
\d idxpart
|
||||||
|
-- multiple primary key on child should fail
|
||||||
|
create table failpart partition of idxpart (b primary key) for values from (0) to (100);
|
||||||
|
drop table idxpart;
|
||||||
|
-- primary key on child is okay if there's no PK in the parent, though
|
||||||
|
create table idxpart (a int) partition by range (a);
|
||||||
|
create table idxpart1pk partition of idxpart (a primary key) for values from (0) to (100);
|
||||||
|
\d idxpart1pk
|
||||||
drop table idxpart;
|
drop table idxpart;
|
||||||
|
|
||||||
-- but not if you fail to use the full partition key
|
-- Failing to use the full partition key is not allowed
|
||||||
create table idxpart (a int unique, b int) partition by range (a, b);
|
create table idxpart (a int unique, b int) partition by range (a, b);
|
||||||
create table idxpart (a int, b int unique) partition by range (a, b);
|
create table idxpart (a int, b int unique) partition by range (a, b);
|
||||||
create table idxpart (a int primary key, b int) partition by range (b, a);
|
create table idxpart (a int primary key, b int) partition by range (b, a);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user