public inbox for [email protected]
help / color / mirror / Atom feed[PATCH v6 3/4] Convert data structure to use a list
22+ messages / 3 participants
[nested] [flat]
* [PATCH v6 3/4] Convert data structure to use a list
@ 2020-03-04 23:38 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Justin Pryzby @ 2020-03-04 23:38 UTC (permalink / raw)
---
src/backend/utils/adt/genfile.c | 78 +++++++++++++++++----------------
1 file changed, 41 insertions(+), 37 deletions(-)
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index c5148f547b..bc473e79ef 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -37,8 +37,9 @@
typedef struct
{
- char *location;
- DIR *dirdesc;
+ /* List of opened dirs */
+ List *location;
+ List *dirdesc;
bool include_dot_dirs;
/* Used in ls_dir_files: */
@@ -474,10 +475,9 @@ pg_ls_dir(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
fctx = palloc(sizeof(directory_fctx));
- fctx->location = convert_and_check_filename(PG_GETARG_TEXT_PP(0));
-
+ fctx->location = lappend(NIL, convert_and_check_filename(PG_GETARG_TEXT_PP(0)));
+ fctx->dirdesc = lappend(NIL, AllocateDir(linitial(fctx->location)));
fctx->include_dot_dirs = include_dot_dirs;
- fctx->dirdesc = AllocateDir(fctx->location);
if (!fctx->dirdesc)
{
@@ -490,7 +490,7 @@ pg_ls_dir(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m",
- fctx->location)));
+ (char*)linitial(fctx->location))));
}
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
@@ -499,7 +499,7 @@ pg_ls_dir(PG_FUNCTION_ARGS)
funcctx = SRF_PERCALL_SETUP();
fctx = (directory_fctx *) funcctx->user_fctx;
- while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
+ while ((de = ReadDir(linitial(fctx->dirdesc), linitial(fctx->location))) != NULL)
{
if (!fctx->include_dot_dirs &&
(strcmp(de->d_name, ".") == 0 ||
@@ -509,7 +509,9 @@ pg_ls_dir(PG_FUNCTION_ARGS)
SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(de->d_name));
}
- FreeDir(fctx->dirdesc);
+ FreeDir(linitial(fctx->dirdesc));
+ list_free(fctx->dirdesc);
+ list_free_deep(fctx->location);
SRF_RETURN_DONE(funcctx);
}
@@ -528,20 +530,25 @@ pg_ls_dir_1arg(PG_FUNCTION_ARGS)
}
/*
- * Populate fctx with list of pathnames and stat structues. Generate a full
- * list of the stat structures all at once - the alternative is to re-stat
- * everything later on, which then requires somehow handling cases like the 2nd
- * stat fails, or the 2nd stat returns a dir which didn't exist at the time we
- * originally looked, or existed but wasn't a dir. stat()ing everything all at
- * once gets as close as we can to a consistent view of the filesystem, from
- * which files might be removed or renamed or reordered.
+ * Populate fctx with list of pathnames and stat structues.
+ *
+ * Generate a full list of the stat structures all at once. That gets as close
+ * as we can to a consistent view of the filesystem, from which files might be
+ * removed or renamed or reordered.
+ *
+ * recurse is the recursion level into a stack of dirs, or -1 to not decend
+ * into directories.
*/
static void
-populate_paths(directory_fctx *fctx, bool recurse)
+populate_paths(directory_fctx *fctx, int recurse)
{
struct dirent *de;
struct stat attrib;
- while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
+
+ DIR *dirdesc = llast(fctx->dirdesc);
+ char *location = llast(fctx->location);
+
+ while ((de = ReadDir(dirdesc, location)) != NULL)
{
char path[MAXPGPATH];
@@ -550,28 +557,23 @@ populate_paths(directory_fctx *fctx, bool recurse)
continue;
/* Get the file info */
- snprintf(path, sizeof(path), "%s/%s", fctx->location, de->d_name);
+ snprintf(path, sizeof(path), "%s/%s", location, de->d_name);
if (stat(path, &attrib) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m", path)));
/* Ignore anything but regular files, or dirs, if requested */
- if (S_ISDIR(attrib.st_mode))
+ if (recurse == -1)
+ ; /* Do nothing, fall through */
+ else if (S_ISDIR(attrib.st_mode))
{
- /* Save current dir while recursing */
- directory_fctx oldfctx = *fctx;
-
- fctx->location = path;
- fctx->dirdesc = AllocateDir(path);
-
- if (recurse)
- populate_paths(fctx, recurse);
-
- /* Restore previous dir */
- FreeDir(fctx->dirdesc);
- fctx->dirdesc = oldfctx.dirdesc;
- fctx->location = oldfctx.location;
+ /* Reallocate location and dirdesc whenever recursing */
+ fctx->location = lappend(fctx->location, path);
+ fctx->dirdesc = lappend(fctx->dirdesc, AllocateDir(path));
+ populate_paths(fctx, 1+recurse);
+ FreeDir(llast(fctx->dirdesc));
+ list_delete_last(fctx->dirdesc);
} else if (!S_ISREG(attrib.st_mode))
continue;
@@ -619,8 +621,8 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok, bool
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
- fctx->location = pstrdup(dir);
- fctx->dirdesc = AllocateDir(fctx->location);
+ fctx->location = lappend(NIL, pstrdup(dir));
+ fctx->dirdesc = lappend(NIL, AllocateDir(dir));
fctx->npaths = 0;
fctx->path = palloc(sizeof(*fctx->path));
fctx->stat = palloc(sizeof(*fctx->stat));
@@ -636,10 +638,10 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok, bool
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m",
- fctx->location)));
+ dir)));
}
- populate_paths(fctx, dir_ok);
+ populate_paths(fctx, dir_ok ? 0 : -1);
funcctx->max_calls = fctx->npaths;
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
@@ -674,7 +676,9 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok, bool
pfree(fctx->path);
pfree(fctx->stat);
- FreeDir(fctx->dirdesc);
+ FreeDir(linitial(fctx->dirdesc));
+ list_free(fctx->dirdesc);
+ list_free(fctx->location);
SRF_RETURN_DONE(funcctx);
}
--
2.17.0
--V88s5gaDVPzZ0KCq
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v6-0004-Read-each-dir-incrementally-during-each-SRF-call.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* Re: New committers: Nathan Bossart, Amit Langote, Masahiko Sawada
@ 2023-04-24 08:32 Jesper Pedersen <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Jesper Pedersen @ 2023-04-24 08:32 UTC (permalink / raw)
To: [email protected]
On 4/20/23 13:40, Tom Lane wrote:
> The Core Team would like to extend our congratulations to
> Nathan Bossart, Amit Langote, and Masahiko Sawada, who have
> accepted invitations to become our newest Postgres committers.
>
> Please join me in wishing them much success and few reverts.
>
Huge congrats !
Best regards,
Jesper
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v44b 1/4] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--fot5plqmb33ey33c
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v44b-0002-Do-not-dereference-varattrib_4b-in-VARSIZE_4B.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v45 1/8] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--cldir6umqisr673d
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v45-0002-Do-not-dereference-varattrib_4b-in-VARSIZE_4B.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v46 1/7] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--mdsv5bdgfjjj6d77
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v46-0002-Add-CONCURRENTLY-option-to-REPACK-command.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v47 1/9] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..b86ad73c626 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..4a2d21915b1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--2fxmamo6mu2qbxgv
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v47-0002-give-options-bitmask-to-table_delete-table_updat.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v48 1/7] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..b86ad73c626 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..4a2d21915b1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--qfkt2ktdpcfeypib
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v48-0002-Give-options-parameter-to-table_delete-table_upd.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v49 1/7] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..b86ad73c626 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..4a2d21915b1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--3n3vqr5y2jhknrqj
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v49-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v50 1/8] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 41 ++++++++++++++++++++++----------
src/backend/commands/indexcmds.c | 9 +++----
src/include/catalog/index.h | 7 +++---
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..e418d67e8e4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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? */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..cba379810c7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
--
2.47.3
--brnevsqjnuzpyok4
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v50-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v52 01/10] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 41 ++++++++++++++++++++++----------
src/backend/commands/indexcmds.c | 9 +++----
src/include/catalog/index.h | 7 +++---
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..e418d67e8e4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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? */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..cba379810c7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
--
2.47.3
--gp2pyozrd5pweboh
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v52-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v51 01/10] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 41 ++++++++++++++++++++++----------
src/backend/commands/indexcmds.c | 9 +++----
src/include/catalog/index.h | 7 +++---
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..e418d67e8e4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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? */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..cba379810c7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
--
2.47.3
--r2slln3zpmilwu22
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v51-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v44 01/10] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--gwom7bl7ogtszo4k
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v44-0002-Do-not-dereference-varattrib_4b-in-VARSIZE_4B.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v44b 1/4] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--fot5plqmb33ey33c
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v44b-0002-Do-not-dereference-varattrib_4b-in-VARSIZE_4B.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v45 1/8] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--cldir6umqisr673d
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v45-0002-Do-not-dereference-varattrib_4b-in-VARSIZE_4B.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v46 1/7] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--mdsv5bdgfjjj6d77
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v46-0002-Add-CONCURRENTLY-option-to-REPACK-command.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v47 1/9] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..b86ad73c626 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..4a2d21915b1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--2fxmamo6mu2qbxgv
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v47-0002-give-options-bitmask-to-table_delete-table_updat.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v48 1/7] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..b86ad73c626 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..4a2d21915b1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--qfkt2ktdpcfeypib
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v48-0002-Give-options-parameter-to-table_delete-table_upd.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v49 1/7] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..b86ad73c626 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..4a2d21915b1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--3n3vqr5y2jhknrqj
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v49-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v50 1/8] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 41 ++++++++++++++++++++++----------
src/backend/commands/indexcmds.c | 9 +++----
src/include/catalog/index.h | 7 +++---
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..e418d67e8e4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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? */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..cba379810c7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
--
2.47.3
--brnevsqjnuzpyok4
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v50-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v51 01/10] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 41 ++++++++++++++++++++++----------
src/backend/commands/indexcmds.c | 9 +++----
src/include/catalog/index.h | 7 +++---
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..e418d67e8e4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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? */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..cba379810c7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
--
2.47.3
--r2slln3zpmilwu22
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v51-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v52 01/10] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 41 ++++++++++++++++++++++----------
src/backend/commands/indexcmds.c | 9 +++----
src/include/catalog/index.h | 7 +++---
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 1ccfa687f05..e418d67e8e4 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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? */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373e8234794..cba379810c7 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a38e95bc0eb..ed9e4c37d27 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
--
2.47.3
--gp2pyozrd5pweboh
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v52-0002-Rename-cluster.c-h-repack.c-h.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
* [PATCH v44 01/10] Make index_concurrently_create_copy more general
@ 2026-03-24 18:02 Álvaro Herrera <[email protected]>
0 siblings, 0 replies; 22+ messages in thread
From: Álvaro Herrera @ 2026-03-24 18:02 UTC (permalink / raw)
Add a 'boolean concurrent' option, and make it work for both cases.
Also rename it to index_create_copy.
This allows it to be reused for other purposes -- specifically, for
REPACK CONCURRENTLY.
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 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 <[email protected]>
Discussion: https://postgr.es/m/41104.1754922120@localhost
---
src/backend/catalog/index.c | 39 +++++++++++++++++++-------------
src/backend/commands/indexcmds.c | 15 +++++++-----
src/backend/nodes/makefuncs.c | 9 ++++----
src/include/catalog/index.h | 7 +++---
src/include/nodes/makefuncs.h | 4 +++-
5 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d8219b18c48..de7182a85a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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,10 +1394,13 @@ 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);
+ oldInfo->ii_WithoutOverlaps,
+ oldInfo->ii_ExclusionOps,
+ oldInfo->ii_ExclusionProcs,
+ oldInfo->ii_ExclusionStrats);
/*
* Extract the list of column names and the column numbers for the new
@@ -1436,6 +1438,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 +1464,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? */
@@ -2453,7 +2458,8 @@ BuildIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
@@ -2513,7 +2519,8 @@ BuildDummyIndexInfo(Relation index)
indexStruct->indisready,
false,
index->rd_indam->amsummarizing,
- indexStruct->indisexclusion && indexStruct->indisunique);
+ indexStruct->indisexclusion && indexStruct->indisunique,
+ NULL, NULL, NULL);
/* fill in attribute numbers */
for (i = 0; i < numAtts; i++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index dd593ccbc1c..83edab38760 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -244,7 +244,8 @@ CheckIndexCompatible(Oid oldId,
*/
indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes,
accessMethodId, NIL, NIL, false, false,
- false, false, amsummarizing, isWithoutOverlaps);
+ false, false, amsummarizing, isWithoutOverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
opclassIds = palloc_array(Oid, numberOfAttributes);
@@ -931,7 +932,8 @@ DefineIndex(ParseState *pstate,
!concurrent,
concurrent,
amissummarizing,
- stmt->iswithoutoverlaps);
+ stmt->iswithoutoverlaps,
+ NULL, NULL, NULL);
typeIds = palloc_array(Oid, numberOfAttributes);
collationIds = palloc_array(Oid, numberOfAttributes);
@@ -3989,10 +3991,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
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 3cd35c5c457..8d23aa917e5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -834,7 +834,8 @@ IndexInfo *
makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
List *predicates, bool unique, bool nulls_not_distinct,
bool isready, bool concurrent, bool summarizing,
- bool withoutoverlaps)
+ bool withoutoverlaps, Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats)
{
IndexInfo *n = makeNode(IndexInfo);
@@ -863,9 +864,9 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions,
n->ii_PredicateState = NULL;
/* exclusion constraints */
- n->ii_ExclusionOps = NULL;
- n->ii_ExclusionProcs = NULL;
- n->ii_ExclusionStrats = NULL;
+ n->ii_ExclusionOps = exclusion_ops;
+ n->ii_ExclusionProcs = exclusion_procs;
+ n->ii_ExclusionStrats = exclusion_strats;
/* speculative inserts */
n->ii_UniqueOps = NULL;
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 36b70689254..56a064ef444 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -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);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index bf54d39feb0..40ec249a7a1 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -99,7 +99,9 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
List *expressions, List *predicates,
bool unique, bool nulls_not_distinct,
bool isready, bool concurrent,
- bool summarizing, bool withoutoverlaps);
+ bool summarizing, bool withoutoverlaps,
+ Oid *exclusion_ops, Oid *exclusion_procs,
+ uint16 *exclusion_strats);
extern Node *makeStringConst(char *str, int location);
extern DefElem *makeDefElem(char *name, Node *arg, int location);
--
2.47.3
--gwom7bl7ogtszo4k
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="v44-0002-Do-not-dereference-varattrib_4b-in-VARSIZE_4B.patch"
^ permalink raw reply [nested|flat] 22+ messages in thread
end of thread, other threads:[~2026-03-24 18:02 UTC | newest]
Thread overview: 22+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-03-04 23:38 [PATCH v6 3/4] Convert data structure to use a list Justin Pryzby <[email protected]>
2023-04-24 08:32 Re: New committers: Nathan Bossart, Amit Langote, Masahiko Sawada Jesper Pedersen <[email protected]>
2026-03-24 18:02 [PATCH v45 1/8] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v47 1/9] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v51 01/10] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v52 01/10] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v46 1/7] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v44b 1/4] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v44 01/10] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v44b 1/4] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v49 1/7] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v45 1/8] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v52 01/10] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v44 01/10] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v46 1/7] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v47 1/9] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v48 1/7] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v50 1/8] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v48 1/7] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v49 1/7] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v50 1/8] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
2026-03-24 18:02 [PATCH v51 01/10] Make index_concurrently_create_copy more general Álvaro Herrera <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox