Preserve pg_index.indisclustered across REINDEX CONCURRENTLY
authorMichael Paquier
Tue, 3 Mar 2020 01:12:49 +0000 (10:12 +0900)
committerMichael Paquier
Tue, 3 Mar 2020 01:12:49 +0000 (10:12 +0900)
If the flag value is lost, a CLUSTER query following REINDEX
CONCURRENTLY could fail.  Non-concurrent REINDEX is already handling
this case consistently.

Author: Justin Pryzby
Discussion: https://postgr.es/m/20200229024202[email protected]
Backpatch-through: 12

src/backend/catalog/index.c
src/test/regress/expected/create_index.out
src/test/regress/sql/create_index.sql

index bb90fd38113baa1edf63d690e56d8d62db3e4c20..7408d495326a30a1bd34c8e8f990996d9f70ac16 100644 (file)
@@ -1528,7 +1528,13 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
    newIndexForm->indimmediate = oldIndexForm->indimmediate;
    oldIndexForm->indimmediate = true;
 
-   /* Mark old index as valid and new as invalid as index_set_state_flags */
+   /* Preserve indisclustered in the new index */
+   newIndexForm->indisclustered = oldIndexForm->indisclustered;
+
+   /*
+    * Mark the old index as valid, and the new index as invalid similarly
+    * to what index_set_state_flags() does.
+    */
    newIndexForm->indisvalid = true;
    oldIndexForm->indisvalid = false;
    oldIndexForm->indisclustered = false;
index 593b1f37243f0a905c0614e3a107a156db53825d..a649957f758d3a9bd0a34ae96458a0ddc7e33ff7 100644 (file)
@@ -2115,6 +2115,19 @@ SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
 (1 row)
 
 DROP TABLE testcomment;
+-- Check that indisclustered updates are preserved
+CREATE TABLE concur_clustered(i int);
+CREATE INDEX concur_clustered_i_idx ON concur_clustered(i);
+ALTER TABLE concur_clustered CLUSTER ON concur_clustered_i_idx;
+REINDEX TABLE CONCURRENTLY concur_clustered;
+SELECT indexrelid::regclass, indisclustered FROM pg_index
+  WHERE indrelid = 'concur_clustered'::regclass;
+       indexrelid       | indisclustered 
+------------------------+----------------
+ concur_clustered_i_idx | t
+(1 row)
+
+DROP TABLE concur_clustered;
 -- Partitions
 -- Create some partitioned tables
 CREATE TABLE concur_reindex_part (c1 int, c2 int) PARTITION BY RANGE (c1);
index e4c4272a2c95c801d9ffe10cf60542ffcf038b2d..fb7da725ff0cfdf6879c8864dd8c734c687109d9 100644 (file)
@@ -852,6 +852,15 @@ SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
 REINDEX TABLE CONCURRENTLY testcomment ;
 SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
 DROP TABLE testcomment;
+-- Check that indisclustered updates are preserved
+CREATE TABLE concur_clustered(i int);
+CREATE INDEX concur_clustered_i_idx ON concur_clustered(i);
+ALTER TABLE concur_clustered CLUSTER ON concur_clustered_i_idx;
+REINDEX TABLE CONCURRENTLY concur_clustered;
+SELECT indexrelid::regclass, indisclustered FROM pg_index
+  WHERE indrelid = 'concur_clustered'::regclass;
+DROP TABLE concur_clustered;
+
 -- Partitions
 -- Create some partitioned tables
 CREATE TABLE concur_reindex_part (c1 int, c2 int) PARTITION BY RANGE (c1);