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

Commitef6f30f

Browse files
committed
Fix REINDEX CONCURRENTLY of partitions
In case of a partition index, when swapping the old and new index, wealso need to attach the new index as a partition and detach the oldone. Also, to handle partition indexes, we not only need to changedependencies referencing the index, but also dependencies of the indexreferencing something else. The previous code did this onlyspecifically for a constraint, but we also need to do this forpartitioned indexes. So instead write a generic function that does itfor all dependencies.Author: Michael Paquier <michael@paquier.xyz>Author: Peter Eisentraut <peter.eisentraut@2ndquadrant.com>Discussion:https://www.postgresql.org/message-id/flat/DF4PR8401MB11964EDB77C860078C343BEBEE5A0%40DF4PR8401MB1196.NAMPRD84.PROD.OUTLOOK.COM#154df1fedb735190a773481765f7b874
1 parentf7feb02 commitef6f30f

File tree

5 files changed

+209
-18
lines changed

5 files changed

+209
-18
lines changed

‎src/backend/catalog/index.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include"catalog/heap.h"
4040
#include"catalog/index.h"
4141
#include"catalog/objectaccess.h"
42+
#include"catalog/partition.h"
4243
#include"catalog/pg_am.h"
4344
#include"catalog/pg_collation.h"
4445
#include"catalog/pg_constraint.h"
@@ -1263,7 +1264,13 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
12631264
indexColNames=lappend(indexColNames,NameStr(att->attname));
12641265
}
12651266

1266-
/* Now create the new index */
1267+
/*
1268+
* Now create the new index.
1269+
*
1270+
* For a partition index, we adjust the partition dependency later, to
1271+
* ensure a consistent state at all times. That is why parentIndexRelid
1272+
* is not set here.
1273+
*/
12671274
newIndexId=index_create(heapRelation,
12681275
newName,
12691276
InvalidOid,/* indexRelationId */
@@ -1395,6 +1402,9 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
13951402
namestrcpy(&newClassForm->relname,NameStr(oldClassForm->relname));
13961403
namestrcpy(&oldClassForm->relname,oldName);
13971404

1405+
/* Copy partition flag to track inheritance properly */
1406+
newClassForm->relispartition=oldClassForm->relispartition;
1407+
13981408
CatalogTupleUpdate(pg_class,&oldClassTuple->t_self,oldClassTuple);
13991409
CatalogTupleUpdate(pg_class,&newClassTuple->t_self,newClassTuple);
14001410

@@ -1555,29 +1565,23 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
15551565
}
15561566

15571567
/*
1558-
*Move all dependencies on the oldindex to the new one
1568+
*Swap inheritance relationship with parentindex
15591569
*/
1560-
1561-
if (OidIsValid(indexConstraintOid))
1570+
if (get_rel_relispartition(oldIndexId))
15621571
{
1563-
ObjectAddressmyself,
1564-
referenced;
1565-
1566-
/* Change to having the new index depend on the constraint */
1567-
deleteDependencyRecordsForClass(RelationRelationId,oldIndexId,
1568-
ConstraintRelationId,DEPENDENCY_INTERNAL);
1572+
List*ancestors=get_partition_ancestors(oldIndexId);
1573+
OidparentIndexRelid=linitial_oid(ancestors);
15691574

1570-
myself.classId=RelationRelationId;
1571-
myself.objectId=newIndexId;
1572-
myself.objectSubId=0;
1575+
DeleteInheritsTuple(oldIndexId,parentIndexRelid);
1576+
StoreSingleInheritance(newIndexId,parentIndexRelid,1);
15731577

1574-
referenced.classId=ConstraintRelationId;
1575-
referenced.objectId=indexConstraintOid;
1576-
referenced.objectSubId=0;
1577-
1578-
recordDependencyOn(&myself,&referenced,DEPENDENCY_INTERNAL);
1578+
list_free(ancestors);
15791579
}
15801580

1581+
/*
1582+
* Move all dependencies of and on the old index to the new one
1583+
*/
1584+
changeDependenciesOf(RelationRelationId,oldIndexId,newIndexId);
15811585
changeDependenciesOn(RelationRelationId,oldIndexId,newIndexId);
15821586

15831587
/*

‎src/backend/catalog/pg_depend.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,62 @@ changeDependencyFor(Oid classId, Oid objectId,
395395
returncount;
396396
}
397397

398+
/*
399+
* Adjust all dependency records to come from a different object of the same type
400+
*
401+
* classId/oldObjectId specify the old referencing object.
402+
* newObjectId is the new referencing object (must be of class classId).
403+
*
404+
* Returns the number of records updated.
405+
*/
406+
long
407+
changeDependenciesOf(OidclassId,OidoldObjectId,
408+
OidnewObjectId)
409+
{
410+
longcount=0;
411+
RelationdepRel;
412+
ScanKeyDatakey[2];
413+
SysScanDescscan;
414+
HeapTupletup;
415+
416+
depRel=table_open(DependRelationId,RowExclusiveLock);
417+
418+
ScanKeyInit(&key[0],
419+
Anum_pg_depend_classid,
420+
BTEqualStrategyNumber,F_OIDEQ,
421+
ObjectIdGetDatum(classId));
422+
ScanKeyInit(&key[1],
423+
Anum_pg_depend_objid,
424+
BTEqualStrategyNumber,F_OIDEQ,
425+
ObjectIdGetDatum(oldObjectId));
426+
427+
scan=systable_beginscan(depRel,DependDependerIndexId, true,
428+
NULL,2,key);
429+
430+
while (HeapTupleIsValid((tup=systable_getnext(scan))))
431+
{
432+
Form_pg_dependdepform= (Form_pg_depend)GETSTRUCT(tup);
433+
434+
/* make a modifiable copy */
435+
tup=heap_copytuple(tup);
436+
depform= (Form_pg_depend)GETSTRUCT(tup);
437+
438+
depform->objid=newObjectId;
439+
440+
CatalogTupleUpdate(depRel,&tup->t_self,tup);
441+
442+
heap_freetuple(tup);
443+
444+
count++;
445+
}
446+
447+
systable_endscan(scan);
448+
449+
table_close(depRel,RowExclusiveLock);
450+
451+
returncount;
452+
}
453+
398454
/*
399455
* Adjust all dependency records to point to a different object of the same type
400456
*

‎src/include/catalog/dependency.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ extern long changeDependencyFor(Oid classId, Oid objectId,
199199
OidrefClassId,OidoldRefObjectId,
200200
OidnewRefObjectId);
201201

202+
externlongchangeDependenciesOf(OidclassId,OidoldObjectId,
203+
OidnewObjectId);
204+
202205
externlongchangeDependenciesOn(OidrefClassId,OidoldRefObjectId,
203206
OidnewRefObjectId);
204207

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

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,91 @@ SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
20012001
(1 row)
20022002

20032003
DROP TABLE testcomment;
2004+
-- Partitions
2005+
-- Create some partitioned tables
2006+
CREATE TABLE concur_reindex_part (c1 int, c2 int) PARTITION BY RANGE (c1);
2007+
CREATE TABLE concur_reindex_part_0 PARTITION OF concur_reindex_part
2008+
FOR VALUES FROM (0) TO (10) PARTITION BY list (c2);
2009+
CREATE TABLE concur_reindex_part_0_1 PARTITION OF concur_reindex_part_0
2010+
FOR VALUES IN (1);
2011+
CREATE TABLE concur_reindex_part_0_2 PARTITION OF concur_reindex_part_0
2012+
FOR VALUES IN (2);
2013+
-- This partitioned table will have no partitions.
2014+
CREATE TABLE concur_reindex_part_10 PARTITION OF concur_reindex_part
2015+
FOR VALUES FROM (10) TO (20) PARTITION BY list (c2);
2016+
-- Create some partitioned indexes
2017+
CREATE INDEX concur_reindex_part_index ON ONLY concur_reindex_part (c1);
2018+
CREATE INDEX concur_reindex_part_index_0 ON ONLY concur_reindex_part_0 (c1);
2019+
ALTER INDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_0;
2020+
-- This partitioned index will have no partitions.
2021+
CREATE INDEX concur_reindex_part_index_10 ON ONLY concur_reindex_part_10 (c1);
2022+
ALTER INDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_10;
2023+
CREATE INDEX concur_reindex_part_index_0_1 ON ONLY concur_reindex_part_0_1 (c1);
2024+
ALTER INDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_1;
2025+
CREATE INDEX concur_reindex_part_index_0_2 ON ONLY concur_reindex_part_0_2 (c1);
2026+
ALTER INDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_2;
2027+
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index')
2028+
ORDER BY relid, level;
2029+
relid | parentrelid | level
2030+
-------------------------------+-----------------------------+-------
2031+
concur_reindex_part_index | | 0
2032+
concur_reindex_part_index_0 | concur_reindex_part_index | 1
2033+
concur_reindex_part_index_10 | concur_reindex_part_index | 1
2034+
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2
2035+
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2
2036+
(5 rows)
2037+
2038+
-- REINDEX fails for partitioned indexes
2039+
REINDEX INDEX concur_reindex_part_index_10;
2040+
ERROR: REINDEX is not yet implemented for partitioned indexes
2041+
REINDEX INDEX CONCURRENTLY concur_reindex_part_index_10;
2042+
ERROR: REINDEX is not yet implemented for partitioned indexes
2043+
-- REINDEX is a no-op for partitioned tables
2044+
REINDEX TABLE concur_reindex_part_10;
2045+
WARNING: REINDEX of partitioned tables is not yet implemented, skipping "concur_reindex_part_10"
2046+
NOTICE: table "concur_reindex_part_10" has no indexes
2047+
REINDEX TABLE CONCURRENTLY concur_reindex_part_10;
2048+
WARNING: REINDEX of partitioned tables is not yet implemented, skipping "concur_reindex_part_10"
2049+
NOTICE: table "concur_reindex_part_10" has no indexes
2050+
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index')
2051+
ORDER BY relid, level;
2052+
relid | parentrelid | level
2053+
-------------------------------+-----------------------------+-------
2054+
concur_reindex_part_index | | 0
2055+
concur_reindex_part_index_0 | concur_reindex_part_index | 1
2056+
concur_reindex_part_index_10 | concur_reindex_part_index | 1
2057+
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2
2058+
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2
2059+
(5 rows)
2060+
2061+
-- REINDEX should preserve dependencies of partition tree.
2062+
REINDEX INDEX CONCURRENTLY concur_reindex_part_index_0_1;
2063+
REINDEX INDEX CONCURRENTLY concur_reindex_part_index_0_2;
2064+
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index')
2065+
ORDER BY relid, level;
2066+
relid | parentrelid | level
2067+
-------------------------------+-----------------------------+-------
2068+
concur_reindex_part_index | | 0
2069+
concur_reindex_part_index_0 | concur_reindex_part_index | 1
2070+
concur_reindex_part_index_10 | concur_reindex_part_index | 1
2071+
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2
2072+
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2
2073+
(5 rows)
2074+
2075+
REINDEX TABLE CONCURRENTLY concur_reindex_part_0_1;
2076+
REINDEX TABLE CONCURRENTLY concur_reindex_part_0_2;
2077+
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index')
2078+
ORDER BY relid, level;
2079+
relid | parentrelid | level
2080+
-------------------------------+-----------------------------+-------
2081+
concur_reindex_part_index | | 0
2082+
concur_reindex_part_index_0 | concur_reindex_part_index | 1
2083+
concur_reindex_part_index_10 | concur_reindex_part_index | 1
2084+
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2
2085+
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2
2086+
(5 rows)
2087+
2088+
DROP TABLE concur_reindex_part;
20042089
-- Check errors
20052090
-- Cannot run inside a transaction block
20062091
BEGIN;

‎src/test/regress/sql/create_index.sql

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,49 @@ SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
789789
REINDEX TABLE CONCURRENTLY testcomment ;
790790
SELECT obj_description('testcomment_idx1'::regclass,'pg_class');
791791
DROPTABLE testcomment;
792+
-- Partitions
793+
-- Create some partitioned tables
794+
CREATETABLEconcur_reindex_part (c1int, c2int) PARTITION BY RANGE (c1);
795+
CREATETABLEconcur_reindex_part_0 PARTITION OF concur_reindex_part
796+
FORVALUESFROM (0) TO (10) PARTITION BY list (c2);
797+
CREATETABLEconcur_reindex_part_0_1 PARTITION OF concur_reindex_part_0
798+
FORVALUESIN (1);
799+
CREATETABLEconcur_reindex_part_0_2 PARTITION OF concur_reindex_part_0
800+
FORVALUESIN (2);
801+
-- This partitioned table will have no partitions.
802+
CREATETABLEconcur_reindex_part_10 PARTITION OF concur_reindex_part
803+
FORVALUESFROM (10) TO (20) PARTITION BY list (c2);
804+
-- Create some partitioned indexes
805+
CREATEINDEXconcur_reindex_part_indexON ONLY concur_reindex_part (c1);
806+
CREATEINDEXconcur_reindex_part_index_0ON ONLY concur_reindex_part_0 (c1);
807+
ALTERINDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_0;
808+
-- This partitioned index will have no partitions.
809+
CREATEINDEXconcur_reindex_part_index_10ON ONLY concur_reindex_part_10 (c1);
810+
ALTERINDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_10;
811+
CREATEINDEXconcur_reindex_part_index_0_1ON ONLY concur_reindex_part_0_1 (c1);
812+
ALTERINDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_1;
813+
CREATEINDEXconcur_reindex_part_index_0_2ON ONLY concur_reindex_part_0_2 (c1);
814+
ALTERINDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_2;
815+
SELECT relid, parentrelid, levelFROM pg_partition_tree('concur_reindex_part_index')
816+
ORDER BY relid, level;
817+
-- REINDEX fails for partitioned indexes
818+
REINDEX INDEX concur_reindex_part_index_10;
819+
REINDEX INDEX CONCURRENTLY concur_reindex_part_index_10;
820+
-- REINDEX is a no-op for partitioned tables
821+
REINDEX TABLE concur_reindex_part_10;
822+
REINDEX TABLE CONCURRENTLY concur_reindex_part_10;
823+
SELECT relid, parentrelid, levelFROM pg_partition_tree('concur_reindex_part_index')
824+
ORDER BY relid, level;
825+
-- REINDEX should preserve dependencies of partition tree.
826+
REINDEX INDEX CONCURRENTLY concur_reindex_part_index_0_1;
827+
REINDEX INDEX CONCURRENTLY concur_reindex_part_index_0_2;
828+
SELECT relid, parentrelid, levelFROM pg_partition_tree('concur_reindex_part_index')
829+
ORDER BY relid, level;
830+
REINDEX TABLE CONCURRENTLY concur_reindex_part_0_1;
831+
REINDEX TABLE CONCURRENTLY concur_reindex_part_0_2;
832+
SELECT relid, parentrelid, levelFROM pg_partition_tree('concur_reindex_part_index')
833+
ORDER BY relid, level;
834+
DROPTABLE concur_reindex_part;
792835

793836
-- Check errors
794837
-- Cannot run inside a transaction block

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp