Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2cf16cd

Browse files
committed
Fix subtly-incorrect matching of parent and child partitioned indexes.
When creating a partitioned index, DefineIndex tries to identifyany existing indexes on the partitions that match the partitionedindex, so that it can absorb those as child indexes instead ofbuilding new ones. Part of the matching is to compare IndexInfostructs --- but that wasn't done quite right. We're comparingthe IndexInfo built within DefineIndex itself to one made fromexisting catalog contents by BuildIndexInfo. Notably, whileBuildIndexInfo will run index expressions and predicates throughexpression preprocessing, that has not happened to DefineIndex'sstruct. The result is failure to match and subsequent creationof duplicate indexes.The easiest and most bulletproof fix is to build a new IndexInfousing BuildIndexInfo, thereby guaranteeing that the processing doneis identical.While here, let's also extract the opfamily and collation datafrom the new partitioned index, removing ad-hoc logic thatduplicated knowledge about how those are constructed.Per report from Christophe Pettus. Back-patch to v11 wherewe invented partitioned indexes.Richard Guo and Tom LaneDiscussion:https://postgr.es/m/8864BFAA-81FD-4BF9-8E06-7DEB8D4164ED@thebuild.com
1 parentd0e5dc7 commit2cf16cd

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

‎src/backend/commands/indexcmds.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,18 +1141,27 @@ DefineIndex(Oid relationId,
11411141
intnparts=partdesc->nparts;
11421142
Oid*part_oids=palloc(sizeof(Oid)*nparts);
11431143
boolinvalidate_parent= false;
1144+
RelationparentIndex;
11441145
TupleDescparentDesc;
1145-
Oid*opfamOids;
11461146

11471147
pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_TOTAL,
11481148
nparts);
11491149

1150+
/* Make a local copy of partdesc->oids[], just for safety */
11501151
memcpy(part_oids,partdesc->oids,sizeof(Oid)*nparts);
11511152

1153+
/*
1154+
* We'll need an IndexInfo describing the parent index. The one
1155+
* built above is almost good enough, but not quite, because (for
1156+
* example) its predicate expression if any hasn't been through
1157+
* expression preprocessing. The most reliable way to get an
1158+
* IndexInfo that will match those for child indexes is to build
1159+
* it the same way, using BuildIndexInfo().
1160+
*/
1161+
parentIndex=index_open(indexRelationId,lockmode);
1162+
indexInfo=BuildIndexInfo(parentIndex);
1163+
11521164
parentDesc=RelationGetDescr(rel);
1153-
opfamOids=palloc(sizeof(Oid)*numberOfKeyAttributes);
1154-
for (i=0;i<numberOfKeyAttributes;i++)
1155-
opfamOids[i]=get_opclass_family(classObjectId[i]);
11561165

11571166
/*
11581167
* For each partition, scan all existing indexes; if one matches
@@ -1226,9 +1235,9 @@ DefineIndex(Oid relationId,
12261235
cldIdxInfo=BuildIndexInfo(cldidx);
12271236
if (CompareIndexInfo(cldIdxInfo,indexInfo,
12281237
cldidx->rd_indcollation,
1229-
collationObjectId,
1238+
parentIndex->rd_indcollation,
12301239
cldidx->rd_opfamily,
1231-
opfamOids,
1240+
parentIndex->rd_opfamily,
12321241
attmap,maplen))
12331242
{
12341243
OidcldConstrOid=InvalidOid;
@@ -1353,6 +1362,8 @@ DefineIndex(Oid relationId,
13531362
pfree(attmap);
13541363
}
13551364

1365+
index_close(parentIndex,lockmode);
1366+
13561367
/*
13571368
* The pg_index row we inserted for this index was marked
13581369
* indisvalid=true. But if we attached an existing index that is

‎src/test/regress/expected/indexing.out

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ drop table idxpart;
376376
-- When a table is attached a partition and it already has an index, a
377377
-- duplicate index should not get created, but rather the index becomes
378378
-- attached to the parent's index.
379-
create table idxpart (a int, b int, c text) partition by range (a);
379+
create table idxpart (a int, b int, c text, d bool) partition by range (a);
380380
create index idxparti on idxpart (a);
381381
create index idxparti2 on idxpart (b, c);
382382
create table idxpart1 (like idxpart including indexes);
@@ -387,6 +387,7 @@ create table idxpart1 (like idxpart including indexes);
387387
a | integer | | |
388388
b | integer | | |
389389
c | text | | |
390+
d | boolean | | |
390391
Indexes:
391392
"idxpart1_a_idx" btree (a)
392393
"idxpart1_b_c_idx" btree (b, c)
@@ -413,6 +414,7 @@ alter table idxpart attach partition idxpart1 for values from (0) to (10);
413414
a | integer | | |
414415
b | integer | | |
415416
c | text | | |
417+
d | boolean | | |
416418
Partition of: idxpart FOR VALUES FROM (0) TO (10)
417419
Indexes:
418420
"idxpart1_a_idx" btree (a)
@@ -432,6 +434,68 @@ select relname, relkind, inhparent::regclass
432434
idxparti2 | I |
433435
(6 rows)
434436

437+
-- While here, also check matching when creating an index after the fact.
438+
create index on idxpart1 ((a+b)) where d = true;
439+
\d idxpart1
440+
Table "public.idxpart1"
441+
Column | Type | Collation | Nullable | Default
442+
--------+---------+-----------+----------+---------
443+
a | integer | | |
444+
b | integer | | |
445+
c | text | | |
446+
d | boolean | | |
447+
Partition of: idxpart FOR VALUES FROM (0) TO (10)
448+
Indexes:
449+
"idxpart1_a_idx" btree (a)
450+
"idxpart1_b_c_idx" btree (b, c)
451+
"idxpart1_expr_idx" btree ((a + b)) WHERE d = true
452+
453+
select relname, relkind, inhparent::regclass
454+
from pg_class left join pg_index ix on (indexrelid = oid)
455+
left join pg_inherits on (ix.indexrelid = inhrelid)
456+
where relname like 'idxpart%' order by relname;
457+
relname | relkind | inhparent
458+
-------------------+---------+-----------
459+
idxpart | p |
460+
idxpart1 | r |
461+
idxpart1_a_idx | i | idxparti
462+
idxpart1_b_c_idx | i | idxparti2
463+
idxpart1_expr_idx | i |
464+
idxparti | I |
465+
idxparti2 | I |
466+
(7 rows)
467+
468+
create index idxparti3 on idxpart ((a+b)) where d = true;
469+
\d idxpart1
470+
Table "public.idxpart1"
471+
Column | Type | Collation | Nullable | Default
472+
--------+---------+-----------+----------+---------
473+
a | integer | | |
474+
b | integer | | |
475+
c | text | | |
476+
d | boolean | | |
477+
Partition of: idxpart FOR VALUES FROM (0) TO (10)
478+
Indexes:
479+
"idxpart1_a_idx" btree (a)
480+
"idxpart1_b_c_idx" btree (b, c)
481+
"idxpart1_expr_idx" btree ((a + b)) WHERE d = true
482+
483+
select relname, relkind, inhparent::regclass
484+
from pg_class left join pg_index ix on (indexrelid = oid)
485+
left join pg_inherits on (ix.indexrelid = inhrelid)
486+
where relname like 'idxpart%' order by relname;
487+
relname | relkind | inhparent
488+
-------------------+---------+-----------
489+
idxpart | p |
490+
idxpart1 | r |
491+
idxpart1_a_idx | i | idxparti
492+
idxpart1_b_c_idx | i | idxparti2
493+
idxpart1_expr_idx | i | idxparti3
494+
idxparti | I |
495+
idxparti2 | I |
496+
idxparti3 | I |
497+
(8 rows)
498+
435499
drop table idxpart;
436500
-- Verify that attaching an invalid index does not mark the parent index valid.
437501
-- On the other hand, attaching a valid index marks not only its direct

‎src/test/regress/sql/indexing.sql

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ drop table idxpart;
192192
-- When a table is attached a partition and it already has an index, a
193193
-- duplicate index should not get created, but rather the index becomes
194194
-- attached to the parent's index.
195-
createtableidxpart (aint, bint, ctext) partition by range (a);
195+
createtableidxpart (aint, bint, ctext, d bool) partition by range (a);
196196
createindexidxpartion idxpart (a);
197197
createindexidxparti2on idxpart (b, c);
198198
createtableidxpart1 (like idxpart including indexes);
@@ -203,6 +203,19 @@ select relname, relkind, inhparent::regclass
203203
where relnamelike'idxpart%'order by relname;
204204
altertable idxpart attach partition idxpart1 forvaluesfrom (0) to (10);
205205
\d idxpart1
206+
select relname, relkind, inhparent::regclass
207+
from pg_classleft join pg_index ixon (indexrelid=oid)
208+
left join pg_inheritson (ix.indexrelid= inhrelid)
209+
where relnamelike'idxpart%'order by relname;
210+
-- While here, also check matching when creating an index after the fact.
211+
createindexon idxpart1 ((a+b))where d= true;
212+
\d idxpart1
213+
select relname, relkind, inhparent::regclass
214+
from pg_classleft join pg_index ixon (indexrelid=oid)
215+
left join pg_inheritson (ix.indexrelid= inhrelid)
216+
where relnamelike'idxpart%'order by relname;
217+
createindexidxparti3on idxpart ((a+b))where d= true;
218+
\d idxpart1
206219
select relname, relkind, inhparent::regclass
207220
from pg_classleft join pg_index ixon (indexrelid=oid)
208221
left join pg_inheritson (ix.indexrelid= inhrelid)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp