]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make index_concurrently_create_copy more general
authorÁlvaro Herrera <alvherre@kurilemu.de>
Sat, 4 Apr 2026 18:38:26 +0000 (20:38 +0200)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Sat, 4 Apr 2026 18:38:26 +0000 (20:38 +0200)
Also rename it to index_create_copy.  Add a 'boolean concurrent' option,
and make it work for both cases: in concurrent mode, just create the
catalog entries; caller is responsible for the actual building later.
In non-concurrent mode, the index is built right away.

This allows it to be reused for other purposes -- specifically, for
concurrent REPACK.

(With the CONCURRENTLY option, REPACK cannot simply swap the heap file and
rebuild its indexes.  Instead, it needs to build a separate set of
indexes, including their system catalog entries, *before* the actual
swap, to reduce the time AccessExclusiveLock needs to be held for.  This
approach is different from what CREATE INDEX CONCURRENTLY does.)

Per a suggestion from Mihail Nikalayeu.

Author: Antonin Houska <ah@cybertec.at>
Reviewed-by: Mihail Nikalayeu <mihailnikalayeu@gmail.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://postgr.es/m/41104.1754922120@localhost

src/backend/catalog/index.c
src/backend/commands/indexcmds.c
src/include/catalog/index.h

index 1ccfa687f052b1d63ba1f807d131558b6b52a516..e418d67e8e422e67371db22339e2362818fd3d50 100644 (file)
@@ -1289,17 +1289,17 @@ index_create(Relation heapRelation,
 }
 
 /*
- * index_concurrently_create_copy
+ * index_create_copy
  *
- * Create concurrently an index based on the definition of the one provided by
- * caller.  The index is inserted into catalogs and needs to be built later
- * on.  This is called during concurrent reindex processing.
+ * Create an index based on the definition of the one provided by caller.  The
+ * index is inserted into catalogs. If 'concurrently' is TRUE, it needs to be
+ * built later on; otherwise it's built immediately.
  *
  * "tablespaceOid" is the tablespace to use for this index.
  */
 Oid
-index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
-                                                          Oid tablespaceOid, const char *newName)
+index_create_copy(Relation heapRelation, bool concurrently,
+                                 Oid oldIndexId, Oid tablespaceOid, const char *newName)
 {
        Relation        indexRelation;
        IndexInfo  *oldInfo,
@@ -1318,6 +1318,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
        List       *indexColNames = NIL;
        List       *indexExprs = NIL;
        List       *indexPreds = NIL;
+       int                     flags = 0;
 
        indexRelation = index_open(oldIndexId, RowExclusiveLock);
 
@@ -1328,7 +1329,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
         * Concurrent build of an index with exclusion constraints is not
         * supported.
         */
-       if (oldInfo->ii_ExclusionOps != NULL)
+       if (oldInfo->ii_ExclusionOps != NULL && concurrently)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("concurrent index creation for exclusion constraints is not supported")));
@@ -1384,9 +1385,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
        }
 
        /*
-        * Build the index information for the new index.  Note that rebuild of
-        * indexes with exclusion constraints is not supported, hence there is no
-        * need to fill all the ii_Exclusion* fields.
+        * Build the index information for the new index.
         */
        newInfo = makeIndexInfo(oldInfo->ii_NumIndexAttrs,
                                                        oldInfo->ii_NumIndexKeyAttrs,
@@ -1395,11 +1394,24 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
                                                        indexPreds,
                                                        oldInfo->ii_Unique,
                                                        oldInfo->ii_NullsNotDistinct,
-                                                       false,  /* not ready for inserts */
-                                                       true,
+                                                       !concurrently,  /* isready */
+                                                       concurrently,   /* concurrent */
                                                        indexRelation->rd_indam->amsummarizing,
                                                        oldInfo->ii_WithoutOverlaps);
 
+       /* fetch exclusion constraint info if any */
+       if (indexRelation->rd_index->indisexclusion)
+       {
+               /*
+                * XXX Beware: we're making newInfo point to oldInfo-owned memory.  It
+                * would be more orthodox to palloc+memcpy, but we don't need that
+                * here at present.
+                */
+               newInfo->ii_ExclusionOps = oldInfo->ii_ExclusionOps;
+               newInfo->ii_ExclusionProcs = oldInfo->ii_ExclusionProcs;
+               newInfo->ii_ExclusionStrats = oldInfo->ii_ExclusionStrats;
+       }
+
        /*
         * Extract the list of column names and the column numbers for the new
         * index information.  All this information will be used for the index
@@ -1436,6 +1448,9 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
                stattargets[i].isnull = isnull;
        }
 
+       if (concurrently)
+               flags = INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT;
+
        /*
         * Now create the new index.
         *
@@ -1459,7 +1474,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
                                                          indcoloptions->values,
                                                          stattargets,
                                                          reloptionsDatum,
-                                                         INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT,
+                                                         flags,
                                                          0,
                                                          true, /* allow table to be a system catalog? */
                                                          false,        /* is_internal? */
index 373e82347946685d6f9494e34d85e26c6cb03ab0..cba379810c7797af2712c04607eb0bcba89586e4 100644 (file)
@@ -3989,10 +3989,11 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
                        tablespaceid = indexRel->rd_rel->reltablespace;
 
                /* Create new index definition based on given index */
-               newIndexId = index_concurrently_create_copy(heapRel,
-                                                                                                       idx->indexId,
-                                                                                                       tablespaceid,
-                                                                                                       concurrentName);
+               newIndexId = index_create_copy(heapRel,
+                                                                          true,
+                                                                          idx->indexId,
+                                                                          tablespaceid,
+                                                                          concurrentName);
 
                /*
                 * Now open the relation of the new index, a session-level lock is
index a38e95bc0eb59c6a932ff1c6f3080dc6d9b5780e..ed9e4c37d27a5efa702861ecf6278e0bb354492e 100644 (file)
@@ -101,10 +101,9 @@ extern Oid index_create(Relation heapRelation,
 #define        INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS     (1 << 4)
 #define        INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS (1 << 5)
 
-extern Oid     index_concurrently_create_copy(Relation heapRelation,
-                                                                                  Oid oldIndexId,
-                                                                                  Oid tablespaceOid,
-                                                                                  const char *newName);
+extern Oid     index_create_copy(Relation heapRelation, bool concurrently,
+                                                         Oid oldIndexId, Oid tablespaceOid,
+                                                         const char *newName);
 
 extern void index_concurrently_build(Oid heapRelationId,
                                                                         Oid indexRelationId);