Commit 0b48f133 authored by Michael Paquier's avatar Michael Paquier

Fix assertion failure with ALTER TABLE ATTACH PARTITION and indexes

Using ALTER TABLE ATTACH PARTITION causes an assertion failure when
attempting to work on a partitioned index, because partitioned indexes
cannot have partition bounds.

The grammar of ALTER TABLE ATTACH PARTITION requires partition bounds,
but not ALTER INDEX, so mixing ALTER TABLE with partitioned indexes is
confusing.  Hence, on HEAD, prevent ALTER TABLE to attach a partition if
the relation involved is a partitioned index.  On back-branches, as
applications may rely on the existing behavior, just remove the
culprit assertion.

Reported-by: Alexander Lakhin
Author: Amit Langote, Michael Paquier
Discussion: https://postgr.es/m/16276-5cd1dcc8fb8be7b5@postgresql.org
Backpatch-through: 11
parent 54a4f52a
...@@ -3698,8 +3698,16 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd) ...@@ -3698,8 +3698,16 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
cmd->bound); cmd->bound);
break; break;
case RELKIND_PARTITIONED_INDEX: case RELKIND_PARTITIONED_INDEX:
/* nothing to check */
Assert(cmd->bound == NULL); /*
* A partitioned index cannot have a partition bound set. ALTER
* INDEX prevents that with its grammar, but not ALTER TABLE.
*/
if (cmd->bound != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("\"%s\" is not a partitioned table",
RelationGetRelationName(parentRel))));
break; break;
case RELKIND_RELATION: case RELKIND_RELATION:
/* the table must be partitioned */ /* the table must be partitioned */
......
...@@ -121,6 +121,23 @@ Partition of: idxparti2 ...@@ -121,6 +121,23 @@ Partition of: idxparti2
No partition constraint No partition constraint
btree, for table "public.idxpart1" btree, for table "public.idxpart1"
-- Forbid ALTER TABLE when attaching or detaching an index to a partition.
create index idxpart_c on only idxpart (c);
create index idxpart1_c on idxpart1 (c);
alter table idxpart_c attach partition idxpart1_c for values from (10) to (20);
ERROR: "idxpart_c" is not a partitioned table
alter index idxpart_c attach partition idxpart1_c;
select relname, relpartbound from pg_class
where relname in ('idxpart_c', 'idxpart1_c')
order by relname;
relname | relpartbound
------------+--------------
idxpart1_c |
idxpart_c |
(2 rows)
alter table idxpart_c detach partition idxpart1_c;
ERROR: "idxpart_c" is not a table
drop table idxpart; drop table idxpart;
-- If a partition already has an index, don't create a duplicative one -- If a partition already has an index, don't create a duplicative one
create table idxpart (a int, b int) partition by range (a, b); create table idxpart (a int, b int) partition by range (a, b);
......
...@@ -63,6 +63,16 @@ alter table idxpart attach partition idxpart1 for values from (0) to (10); ...@@ -63,6 +63,16 @@ alter table idxpart attach partition idxpart1 for values from (0) to (10);
\d idxpart1 \d idxpart1
\d+ idxpart1_a_idx \d+ idxpart1_a_idx
\d+ idxpart1_b_c_idx \d+ idxpart1_b_c_idx
-- Forbid ALTER TABLE when attaching or detaching an index to a partition.
create index idxpart_c on only idxpart (c);
create index idxpart1_c on idxpart1 (c);
alter table idxpart_c attach partition idxpart1_c for values from (10) to (20);
alter index idxpart_c attach partition idxpart1_c;
select relname, relpartbound from pg_class
where relname in ('idxpart_c', 'idxpart1_c')
order by relname;
alter table idxpart_c detach partition idxpart1_c;
drop table idxpart; drop table idxpart;
-- If a partition already has an index, don't create a duplicative one -- If a partition already has an index, don't create a duplicative one
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment