Skip to content

Commit 05fb5d6

Browse files
committed
Ignore partitioned indexes where appropriate
get_relation_info() was too optimistic about opening indexes in partitioned tables, which would raise errors when any queries were planned on such tables. Fix by ignoring any indexes of the partitioned kind. CLUSTER (and ALTER TABLE CLUSTER ON) had a similar problem. Fix by disallowing these commands in partitioned tables. Fallout from 8b08f7d.
1 parent 5955d93 commit 05fb5d6

File tree

6 files changed

+58
-0
lines changed

6 files changed

+58
-0
lines changed

src/backend/commands/cluster.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
128128
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
129129
errmsg("cannot cluster temporary tables of other sessions")));
130130

131+
/*
132+
* Reject clustering a partitioned table.
133+
*/
134+
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
135+
ereport(ERROR,
136+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
137+
errmsg("cannot cluster a partitioned table")));
138+
131139
if (stmt->indexname == NULL)
132140
{
133141
ListCell *index;
@@ -482,6 +490,12 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
482490
Relation pg_index;
483491
ListCell *index;
484492

493+
/* Disallow applying to a partitioned table */
494+
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
495+
ereport(ERROR,
496+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
497+
errmsg("cannot mark index clustered in partitioned table")));
498+
485499
/*
486500
* If the index is already marked clustered, no need to do anything.
487501
*/

src/backend/optimizer/util/plancat.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,16 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
207207
continue;
208208
}
209209

210+
/*
211+
* Ignore partitioned indexes, since they are not usable for
212+
* queries.
213+
*/
214+
if (indexRelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
215+
{
216+
index_close(indexRelation, NoLock);
217+
continue;
218+
}
219+
210220
/*
211221
* If the index is valid, but cannot yet be used, ignore it; but
212222
* mark the plan we are generating as transient. See

src/test/regress/expected/cluster.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,14 @@ select * from clstr_temp;
439439

440440
drop table clstr_temp;
441441
RESET SESSION AUTHORIZATION;
442+
-- Check that partitioned tables cannot be clustered
443+
CREATE TABLE clstrpart (a int) PARTITION BY RANGE (a);
444+
CREATE INDEX clstrpart_idx ON clstrpart (a);
445+
ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
446+
ERROR: cannot mark index clustered in partitioned table
447+
CLUSTER clstrpart USING clstrpart_idx;
448+
ERROR: cannot cluster a partitioned table
449+
DROP TABLE clstrpart;
442450
-- Test CLUSTER with external tuplesorting
443451
create table clstr_4 as select * from tenk1;
444452
create index cluster_sort on clstr_4 (hundred, thousand, tenthous);

src/test/regress/expected/indexing.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ ERROR: cannot create unique index on partitioned table "idxpart"
3131
create index concurrently on idxpart (a);
3232
ERROR: cannot create index on partitioned table "idxpart" concurrently
3333
drop table idxpart;
34+
-- Verify bugfix with query on indexed partitioned table with no partitions
35+
-- https://postgr.es/m/20180124162006.pmapfiznhgngwtjf@alvherre.pgsql
36+
CREATE TABLE idxpart (col1 INT) PARTITION BY RANGE (col1);
37+
CREATE INDEX ON idxpart (col1);
38+
CREATE TABLE idxpart_two (col2 INT);
39+
SELECT col2 FROM idxpart_two fk LEFT OUTER JOIN idxpart pk ON (col1 = col2);
40+
col2
41+
------
42+
(0 rows)
43+
44+
DROP table idxpart, idxpart_two;
3445
-- If a table without index is attached as partition to a table with
3546
-- an index, the index is automatically created
3647
create table idxpart (a int, b int, c text) partition by range (a);

src/test/regress/sql/cluster.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ drop table clstr_temp;
196196

197197
RESET SESSION AUTHORIZATION;
198198

199+
-- Check that partitioned tables cannot be clustered
200+
CREATE TABLE clstrpart (a int) PARTITION BY RANGE (a);
201+
CREATE INDEX clstrpart_idx ON clstrpart (a);
202+
ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
203+
CLUSTER clstrpart USING clstrpart_idx;
204+
DROP TABLE clstrpart;
205+
199206
-- Test CLUSTER with external tuplesorting
200207

201208
create table clstr_4 as select * from tenk1;

src/test/regress/sql/indexing.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ create unique index on idxpart (a);
1919
create index concurrently on idxpart (a);
2020
drop table idxpart;
2121

22+
-- Verify bugfix with query on indexed partitioned table with no partitions
23+
-- https://postgr.es/m/20180124162006.pmapfiznhgngwtjf@alvherre.pgsql
24+
CREATE TABLE idxpart (col1 INT) PARTITION BY RANGE (col1);
25+
CREATE INDEX ON idxpart (col1);
26+
CREATE TABLE idxpart_two (col2 INT);
27+
SELECT col2 FROM idxpart_two fk LEFT OUTER JOIN idxpart pk ON (col1 = col2);
28+
DROP table idxpart, idxpart_two;
29+
2230
-- If a table without index is attached as partition to a table with
2331
-- an index, the index is automatically created
2432
create table idxpart (a int, b int, c text) partition by range (a);

0 commit comments

Comments
 (0)