Preserve pg_index.indisclustered across REINDEX CONCURRENTLY
authorMichael Paquier
Tue, 3 Mar 2020 01:12:28 +0000 (10:12 +0900)
committerMichael Paquier
Tue, 3 Mar 2020 01:12:28 +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 8880586c37280ad1c92c7f5eb5255c154c2d862c..1681f61727edd107ccad7b6e57a66058521bc92c 100644 (file)
@@ -1527,7 +1527,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 6ddf3a63c3a7ad01dc6e0d47d0aa352a5359c65c..ae95bb38a64642679397018e8e3e3b0273e1b25f 100644 (file)
@@ -2128,6 +2128,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 f7fd756189b4490b8ca216ffe7ee762e4f757b7b..c3246cb296ff8de9284a56961df51fac153d1a8a 100644 (file)
@@ -858,6 +858,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);