Preserve opclass parameters across REINDEX CONCURRENTLY
authorMichael Paquier <michael@paquier.xyz>
Mon, 1 Nov 2021 02:38:23 +0000 (11:38 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 1 Nov 2021 02:38:23 +0000 (11:38 +0900)
The opclass parameter Datums from the old index are fetched in the same
way as for predicates and expressions, by grabbing them directly from
the system catalogs.  They are then copied into the new IndexInfo that
will be used for the creation of the new copy.

This caused the new index to be rebuilt with default parameters rather
than the ones pre-defined by a user.  The only way to get back a new
index with correct opclass parameters would be to recreate a new index
from scratch.

The issue has been introduced by 911e702.

Author: Michael Paquier
Reviewed-by: Zhihong Yu
Discussion: https://postgr.es/m/YX0CG/QpLXcPr8HJ@paquier.xyz
Backpatch-through: 13

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

index 26bfa74ce757181349e550ae6725aea26f4bb68f..c255806e38cc19a69ea1731dd01d9b0862ca5061 100644 (file)
@@ -73,6 +73,7 @@
 #include "storage/procarray.h"
 #include "storage/smgr.h"
 #include "utils/builtins.h"
+#include "utils/datum.h"
 #include "utils/fmgroids.h"
 #include "utils/guc.h"
 #include "utils/inval.h"
@@ -1365,6 +1366,15 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
        newInfo->ii_IndexAttrNumbers[i] = oldInfo->ii_IndexAttrNumbers[i];
    }
 
+   /* Extract opclass parameters for each attribute, if any */
+   if (oldInfo->ii_OpclassOptions != NULL)
+   {
+       newInfo->ii_OpclassOptions = palloc0(sizeof(Datum) *
+                                            newInfo->ii_NumIndexAttrs);
+       for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
+           newInfo->ii_OpclassOptions[i] = get_attoptions(oldIndexId, i + 1);
+   }
+
    /*
     * Now create the new index.
     *
index 4750eac359a578f5a20cc999d55f0f4f7821bb73..daf75dd5c44e85b6089fbe892847419de43bd136 100644 (file)
@@ -2176,6 +2176,25 @@ SELECT indexrelid::regclass, indisreplident FROM pg_index
 (1 row)
 
 DROP TABLE concur_replident;
+-- Check that opclass parameters are preserved
+CREATE TABLE concur_appclass_tab(i tsvector, j tsvector, k tsvector);
+CREATE INDEX concur_appclass_ind on concur_appclass_tab
+  USING gist (i tsvector_ops (siglen='1000'), j tsvector_ops (siglen='500'));
+CREATE INDEX concur_appclass_ind_2 on concur_appclass_tab
+  USING gist (k tsvector_ops (siglen='300'), j tsvector_ops);
+REINDEX TABLE CONCURRENTLY concur_appclass_tab;
+\d concur_appclass_tab
+         Table "public.concur_appclass_tab"
+ Column |   Type   | Collation | Nullable | Default 
+--------+----------+-----------+----------+---------
+ i      | tsvector |           |          | 
+ j      | tsvector |           |          | 
+ k      | tsvector |           |          | 
+Indexes:
+    "concur_appclass_ind" gist (i tsvector_ops (siglen='1000'), j tsvector_ops (siglen='500'))
+    "concur_appclass_ind_2" gist (k tsvector_ops (siglen='300'), j)
+
+DROP TABLE concur_appclass_tab;
 -- Partitions
 -- Create some partitioned tables
 CREATE TABLE concur_reindex_part (c1 int, c2 int) PARTITION BY RANGE (c1);
index 22209b0691f9aa737dc6bffec88641fe7f9f7e24..8b353be16e09b7ffb55626873a9699c6fe0ff031 100644 (file)
@@ -888,6 +888,15 @@ REINDEX TABLE CONCURRENTLY concur_replident;
 SELECT indexrelid::regclass, indisreplident FROM pg_index
   WHERE indrelid = 'concur_replident'::regclass;
 DROP TABLE concur_replident;
+-- Check that opclass parameters are preserved
+CREATE TABLE concur_appclass_tab(i tsvector, j tsvector, k tsvector);
+CREATE INDEX concur_appclass_ind on concur_appclass_tab
+  USING gist (i tsvector_ops (siglen='1000'), j tsvector_ops (siglen='500'));
+CREATE INDEX concur_appclass_ind_2 on concur_appclass_tab
+  USING gist (k tsvector_ops (siglen='300'), j tsvector_ops);
+REINDEX TABLE CONCURRENTLY concur_appclass_tab;
+\d concur_appclass_tab
+DROP TABLE concur_appclass_tab;
 
 -- Partitions
 -- Create some partitioned tables