On Tue, Dec 22, 2020 at 02:32:05AM -0600, Justin Pryzby wrote: > Also, this one is going to be subsumed by ExecReindex(), so the palloc will go > away (otherwise I would ask to pass it in from the caller):
Yeah, maybe. Still you need to be very careful if you have any allocated variables like a tablespace or a path which requires to be in the private context used by ReindexMultipleInternal() or even ReindexRelationConcurrently(), so I am not sure you can avoid that completely. For now, we could choose the option to still use a palloc(), and then save the options in the private contexts. Forgot that in the previous version actually. -- Michael
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index c041628049..89394b648e 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -30,13 +30,16 @@ typedef enum } IndexStateFlagsAction; /* options for REINDEX */ -typedef enum ReindexOption +typedef struct ReindexOptions { - REINDEXOPT_VERBOSE = 1 << 0, /* print progress info */ - REINDEXOPT_REPORT_PROGRESS = 1 << 1, /* report pgstat progress */ - REINDEXOPT_MISSING_OK = 1 << 2, /* skip missing relations */ - REINDEXOPT_CONCURRENTLY = 1 << 3 /* concurrent mode */ -} ReindexOption; + bits32 flags; /* bitmask of REINDEXOPT_* */ +} ReindexOptions; + +/* flag bits for ReindexOptions->flags */ +#define REINDEXOPT_VERBOSE 0x01 /* print progress info */ +#define REINDEXOPT_REPORT_PROGRESS 0x02 /* report pgstat progress */ +#define REINDEXOPT_MISSING_OK 0x04 /* skip missing relations */ +#define REINDEXOPT_CONCURRENTLY 0x08 /* concurrent mode */ /* state info for validate_index bulkdelete callback */ typedef struct ValidateIndexState @@ -146,7 +149,7 @@ extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action); extern Oid IndexGetRelation(Oid indexId, bool missing_ok); extern void reindex_index(Oid indexId, bool skip_constraint_checks, - char relpersistence, int options); + char relpersistence, ReindexOptions *options); /* Flag bits for reindex_relation(): */ #define REINDEX_REL_PROCESS_TOAST 0x01 @@ -155,7 +158,7 @@ extern void reindex_index(Oid indexId, bool skip_constraint_checks, #define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08 #define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10 -extern bool reindex_relation(Oid relid, int flags, int options); +extern bool reindex_relation(Oid relid, int flags, ReindexOptions *options); extern bool ReindexIsProcessingHeap(Oid heapOid); extern bool ReindexIsProcessingIndex(Oid indexOid); diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h index 7cfb37c9b2..c66629cf73 100644 --- a/src/include/commands/cluster.h +++ b/src/include/commands/cluster.h @@ -18,16 +18,17 @@ #include "storage/lock.h" #include "utils/relcache.h" - /* options for CLUSTER */ -typedef enum ClusterOption +#define CLUOPT_RECHECK 0x01 /* recheck relation state */ +#define CLUOPT_VERBOSE 0x02 /* print progress info */ + +typedef struct ClusterOptions { - CLUOPT_RECHECK = 1 << 0, /* recheck relation state */ - CLUOPT_VERBOSE = 1 << 1 /* print progress info */ -} ClusterOption; + bits32 flags; /* bitmask of CLUSTEROPT_* */ +} ClusterOptions; extern void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel); -extern void cluster_rel(Oid tableOid, Oid indexOid, int options); +extern void cluster_rel(Oid tableOid, Oid indexOid, ClusterOptions *options); extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMODE lockmode); extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal); diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 1133ae1143..43d5480c20 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -14,6 +14,7 @@ #ifndef DEFREM_H #define DEFREM_H +#include "catalog/index.h" #include "catalog/objectaddress.h" #include "nodes/params.h" #include "parser/parse_node.h" @@ -34,11 +35,16 @@ extern ObjectAddress DefineIndex(Oid relationId, bool check_not_in_use, bool skip_build, bool quiet); -extern int ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt); -extern void ReindexIndex(RangeVar *indexRelation, int options, bool isTopLevel); -extern Oid ReindexTable(RangeVar *relation, int options, bool isTopLevel); -extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, - int options); +extern ReindexOptions *ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt); +extern void ReindexIndex(RangeVar *indexRelation, + ReindexOptions *options, + bool isTopLevel); +extern Oid ReindexTable(RangeVar *relation, + ReindexOptions *options, + bool isTopLevel); +extern void ReindexMultipleTables(const char *objectName, + ReindexObjectType objectKind, + ReindexOptions *options); extern char *makeObjectName(const char *name1, const char *name2, const char *label); extern char *ChooseRelationName(const char *name1, const char *name2, diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index a4cd721400..e3fe4b38e8 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -174,17 +174,15 @@ typedef struct VacAttrStats int rowstride; } VacAttrStats; -typedef enum VacuumOption -{ - VACOPT_VACUUM = 1 << 0, /* do VACUUM */ - VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */ - VACOPT_VERBOSE = 1 << 2, /* print progress info */ - VACOPT_FREEZE = 1 << 3, /* FREEZE option */ - VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */ - VACOPT_SKIP_LOCKED = 1 << 5, /* skip if cannot get lock */ - VACOPT_SKIPTOAST = 1 << 6, /* don't process the TOAST table, if any */ - VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */ -} VacuumOption; +/* flag bits for VacuumParams->options */ +#define VACOPT_VACUUM 0x01 /* do VACUUM */ +#define VACOPT_ANALYZE 0x02 /* do ANALYZE */ +#define VACOPT_VERBOSE 0x04 /* print progress info */ +#define VACOPT_FREEZE 0x08 /* FREEZE option */ +#define VACOPT_FULL 0x10 /* FULL (non-concurrent) vacuum */ +#define VACOPT_SKIP_LOCKED 0x20 /* skip if cannot get lock */ +#define VACOPT_SKIPTOAST 0x40 /* don't process the TOAST table, if any */ +#define VACOPT_DISABLE_PAGE_SKIPPING 0x80 /* don't skip any pages */ /* * A ternary value used by vacuum parameters. diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 731610c701..19a76873f0 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3594,7 +3594,7 @@ IndexGetRelation(Oid indexId, bool missing_ok) */ void reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, - int options) + ReindexOptions *options) { Relation iRel, heapRelation; @@ -3602,7 +3602,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, IndexInfo *indexInfo; volatile bool skipped_constraint = false; PGRUsage ru0; - bool progress = (options & REINDEXOPT_REPORT_PROGRESS) != 0; + bool progress = ((options->flags & REINDEXOPT_REPORT_PROGRESS) != 0); pg_rusage_init(&ru0); @@ -3611,12 +3611,12 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, * we only need to be sure no schema or data changes are going on. */ heapId = IndexGetRelation(indexId, - (options & REINDEXOPT_MISSING_OK) != 0); + (options->flags & REINDEXOPT_MISSING_OK) != 0); /* if relation is missing, leave */ if (!OidIsValid(heapId)) return; - if ((options & REINDEXOPT_MISSING_OK) != 0) + if ((options->flags & REINDEXOPT_MISSING_OK) != 0) heapRelation = try_table_open(heapId, ShareLock); else heapRelation = table_open(heapId, ShareLock); @@ -3792,7 +3792,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, } /* Log what we did */ - if (options & REINDEXOPT_VERBOSE) + if ((options->flags & REINDEXOPT_VERBOSE) != 0) ereport(INFO, (errmsg("index \"%s\" was reindexed", get_rel_name(indexId)), @@ -3846,7 +3846,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, * index rebuild. */ bool -reindex_relation(Oid relid, int flags, int options) +reindex_relation(Oid relid, int flags, ReindexOptions *options) { Relation rel; Oid toast_relid; @@ -3861,7 +3861,7 @@ reindex_relation(Oid relid, int flags, int options) * to prevent schema and data changes in it. The lock level used here * should match ReindexTable(). */ - if ((options & REINDEXOPT_MISSING_OK) != 0) + if ((options->flags & REINDEXOPT_MISSING_OK) != 0) rel = try_table_open(relid, ShareLock); else rel = table_open(relid, ShareLock); @@ -3965,8 +3965,11 @@ reindex_relation(Oid relid, int flags, int options) * Note that this should fail if the toast relation is missing, so * reset REINDEXOPT_MISSING_OK. */ - result |= reindex_relation(toast_relid, flags, - options & ~(REINDEXOPT_MISSING_OK)); + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags &= ~(REINDEXOPT_MISSING_OK); + result |= reindex_relation(toast_relid, flags, &newoptions); } return result; diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index fd5a6eec86..0a9bcd094a 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -103,7 +103,7 @@ void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) { ListCell *lc; - int options = 0; + ClusterOptions options = {0}; bool verbose = false; /* Parse option list */ @@ -121,7 +121,7 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) parser_errposition(pstate, opt->location))); } - options = (verbose ? CLUOPT_VERBOSE : 0); + options.flags = (verbose ? CLUOPT_VERBOSE : 0); if (stmt->relation != NULL) { @@ -192,7 +192,7 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) table_close(rel, NoLock); /* Do the job. */ - cluster_rel(tableOid, indexOid, options); + cluster_rel(tableOid, indexOid, &options); } else { @@ -234,6 +234,10 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) foreach(rv, rvs) { RelToCluster *rvtc = (RelToCluster *) lfirst(rv); + ClusterOptions cluster_options; + + memcpy(&cluster_options, &options, sizeof(ClusterOptions)); + cluster_options.flags |= CLUOPT_RECHECK; /* Start a new transaction for each relation. */ StartTransactionCommand(); @@ -241,7 +245,7 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) PushActiveSnapshot(GetTransactionSnapshot()); /* Do the job. */ cluster_rel(rvtc->tableOid, rvtc->indexOid, - options | CLUOPT_RECHECK); + &cluster_options); PopActiveSnapshot(); CommitTransactionCommand(); } @@ -272,11 +276,11 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) * and error messages should refer to the operation as VACUUM not CLUSTER. */ void -cluster_rel(Oid tableOid, Oid indexOid, int options) +cluster_rel(Oid tableOid, Oid indexOid, ClusterOptions *options) { Relation OldHeap; - bool verbose = ((options & CLUOPT_VERBOSE) != 0); - bool recheck = ((options & CLUOPT_RECHECK) != 0); + bool verbose = ((options->flags & CLUOPT_VERBOSE) != 0); + bool recheck = ((options->flags & CLUOPT_RECHECK) != 0); /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); @@ -1355,6 +1359,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, ObjectAddress object; Oid mapped_tables[4]; int reindex_flags; + ReindexOptions reindex_options = {0}; int i; /* Report that we are now swapping relation files */ @@ -1412,7 +1417,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, PROGRESS_CLUSTER_PHASE_REBUILD_INDEX); - reindex_relation(OIDOldHeap, reindex_flags, 0); + reindex_relation(OIDOldHeap, reindex_flags, &reindex_options); /* Report that we are now doing clean up */ pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE, diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 14d24b3cc4..37940b4319 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -89,9 +89,12 @@ static List *ChooseIndexColumnNames(List *indexElems); static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); static void reindex_error_callback(void *args); -static void ReindexPartitions(Oid relid, int options, bool isTopLevel); -static void ReindexMultipleInternal(List *relids, int options); -static bool ReindexRelationConcurrently(Oid relationOid, int options); +static void ReindexPartitions(Oid relid, ReindexOptions *options, + bool isTopLevel); +static void ReindexMultipleInternal(List *relids, + ReindexOptions *options); +static bool ReindexRelationConcurrently(Oid relationOid, + ReindexOptions *options); static void update_relispartition(Oid relationId, bool newval); static inline void set_indexsafe_procflags(void); @@ -100,7 +103,7 @@ static inline void set_indexsafe_procflags(void); */ struct ReindexIndexCallbackState { - int options; /* options from statement */ + ReindexOptions *options; /* options from statement */ Oid locked_table_oid; /* tracks previously locked table */ }; @@ -2455,14 +2458,16 @@ ChooseIndexColumnNames(List *indexElems) * ReindexParseOptions * Parse list of REINDEX options, returning a bitmask of ReindexOption. */ -int +ReindexOptions * ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt) { ListCell *lc; - int options = 0; + ReindexOptions *options; bool concurrently = false; bool verbose = false; + options = (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + /* Parse option list */ foreach(lc, stmt->params) { @@ -2480,7 +2485,7 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt) parser_errposition(pstate, opt->location))); } - options = + options->flags = (verbose ? REINDEXOPT_VERBOSE : 0) | (concurrently ? REINDEXOPT_CONCURRENTLY : 0); @@ -2492,7 +2497,7 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt) * Recreate a specific index. */ void -ReindexIndex(RangeVar *indexRelation, int options, bool isTopLevel) +ReindexIndex(RangeVar *indexRelation, ReindexOptions *options, bool isTopLevel) { struct ReindexIndexCallbackState state; Oid indOid; @@ -2509,10 +2514,11 @@ ReindexIndex(RangeVar *indexRelation, int options, bool isTopLevel) * upgrade the lock, but that's OK, because other sessions can't hold * locks on our temporary table. */ - state.options = options; + state.options = (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + memcpy(state.options, options, sizeof(ReindexOptions)); state.locked_table_oid = InvalidOid; indOid = RangeVarGetRelidExtended(indexRelation, - (options & REINDEXOPT_CONCURRENTLY) != 0 ? + (options->flags & REINDEXOPT_CONCURRENTLY) != 0 ? ShareUpdateExclusiveLock : AccessExclusiveLock, 0, RangeVarCallbackForReindexIndex, @@ -2527,12 +2533,17 @@ ReindexIndex(RangeVar *indexRelation, int options, bool isTopLevel) if (relkind == RELKIND_PARTITIONED_INDEX) ReindexPartitions(indOid, options, isTopLevel); - else if ((options & REINDEXOPT_CONCURRENTLY) != 0 && + else if ((options->flags & REINDEXOPT_CONCURRENTLY) != 0 && persistence != RELPERSISTENCE_TEMP) ReindexRelationConcurrently(indOid, options); else - reindex_index(indOid, false, persistence, - options | REINDEXOPT_REPORT_PROGRESS); + { + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |= REINDEXOPT_REPORT_PROGRESS; + reindex_index(indOid, false, persistence, &newoptions); + } } /* @@ -2547,13 +2558,14 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, char relkind; struct ReindexIndexCallbackState *state = arg; LOCKMODE table_lockmode; + ReindexOptions *options = state->options; /* * Lock level here should match table lock in reindex_index() for * non-concurrent case and table locks used by index_concurrently_*() for * concurrent case. */ - table_lockmode = ((state->options & REINDEXOPT_CONCURRENTLY) != 0) ? + table_lockmode = (options->flags & REINDEXOPT_CONCURRENTLY) != 0 ? ShareUpdateExclusiveLock : ShareLock; /* @@ -2611,7 +2623,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, * Recreate all indexes of a table (and of its toast table, if any) */ Oid -ReindexTable(RangeVar *relation, int options, bool isTopLevel) +ReindexTable(RangeVar *relation, ReindexOptions *options, bool isTopLevel) { Oid heapOid; bool result; @@ -2625,14 +2637,14 @@ ReindexTable(RangeVar *relation, int options, bool isTopLevel) * locks on our temporary table. */ heapOid = RangeVarGetRelidExtended(relation, - (options & REINDEXOPT_CONCURRENTLY) != 0 ? + (options->flags & REINDEXOPT_CONCURRENTLY) != 0 ? ShareUpdateExclusiveLock : ShareLock, 0, RangeVarCallbackOwnsTable, NULL); if (get_rel_relkind(heapOid) == RELKIND_PARTITIONED_TABLE) ReindexPartitions(heapOid, options, isTopLevel); - else if ((options & REINDEXOPT_CONCURRENTLY) != 0 && + else if ((options->flags & REINDEXOPT_CONCURRENTLY) != 0 && get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP) { result = ReindexRelationConcurrently(heapOid, options); @@ -2644,10 +2656,14 @@ ReindexTable(RangeVar *relation, int options, bool isTopLevel) } else { + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |= REINDEXOPT_REPORT_PROGRESS; result = reindex_relation(heapOid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, - options | REINDEXOPT_REPORT_PROGRESS); + &newoptions); if (!result) ereport(NOTICE, (errmsg("table \"%s\" has no indexes to reindex", @@ -2667,7 +2683,7 @@ ReindexTable(RangeVar *relation, int options, bool isTopLevel) */ void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, - int options) + ReindexOptions *options) { Oid objectOid; Relation relationRelation; @@ -2679,6 +2695,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, List *relids = NIL; int num_keys; bool concurrent_warning = false; + ReindexOptions *private_options; AssertArg(objectName); Assert(objectKind == REINDEX_OBJECT_SCHEMA || @@ -2686,7 +2703,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, objectKind == REINDEX_OBJECT_DATABASE); if (objectKind == REINDEX_OBJECT_SYSTEM && - (options & REINDEXOPT_CONCURRENTLY) != 0) + (options->flags & REINDEXOPT_CONCURRENTLY) != 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot reindex system catalogs concurrently"))); @@ -2794,7 +2811,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, * Skip system tables, since index_create() would reject indexing them * concurrently (and it would likely fail if we tried). */ - if ((options & REINDEXOPT_CONCURRENTLY) != 0 && + if ((options->flags & REINDEXOPT_CONCURRENTLY) != 0 && IsCatalogRelationOid(relid)) { if (!concurrent_warning) @@ -2825,11 +2842,20 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, table_endscan(scan); table_close(relationRelation, AccessShareLock); + /* + * Copy option set in the private context to be able to use them across + * multiple transactions. + */ + old = MemoryContextSwitchTo(private_context); + private_options = (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + memcpy(private_options, options, sizeof(ReindexOptions)); + MemoryContextSwitchTo(old); + /* * Process each relation listed in a separate transaction. Note that this * commits and then starts a new transaction immediately. */ - ReindexMultipleInternal(relids, options); + ReindexMultipleInternal(relids, private_options); MemoryContextDelete(private_context); } @@ -2860,17 +2886,19 @@ reindex_error_callback(void *arg) * by the caller. */ static void -ReindexPartitions(Oid relid, int options, bool isTopLevel) +ReindexPartitions(Oid relid, ReindexOptions *options, bool isTopLevel) { List *partitions = NIL; char relkind = get_rel_relkind(relid); char *relname = get_rel_name(relid); char *relnamespace = get_namespace_name(get_rel_namespace(relid)); MemoryContext reindex_context; + MemoryContext old_context; List *inhoids; ListCell *lc; ErrorContextCallback errcallback; ReindexErrorInfo errinfo; + ReindexOptions *private_options; Assert(relkind == RELKIND_PARTITIONED_INDEX || relkind == RELKIND_PARTITIONED_TABLE); @@ -2915,7 +2943,6 @@ ReindexPartitions(Oid relid, int options, bool isTopLevel) { Oid partoid = lfirst_oid(lc); char partkind = get_rel_relkind(partoid); - MemoryContext old_context; /* * This discards partitioned tables, partitioned indexes and foreign @@ -2933,11 +2960,20 @@ ReindexPartitions(Oid relid, int options, bool isTopLevel) MemoryContextSwitchTo(old_context); } + /* + * Copy option set in the private context to be able to use them across + * multiple transactions. + */ + old_context = MemoryContextSwitchTo(reindex_context); + private_options = (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + memcpy(private_options, options, sizeof(ReindexOptions)); + MemoryContextSwitchTo(old_context); + /* * Process each partition listed in a separate transaction. Note that * this commits and then starts a new transaction immediately. */ - ReindexMultipleInternal(partitions, options); + ReindexMultipleInternal(partitions, private_options); /* * Clean up working storage --- note we must do this after @@ -2955,7 +2991,7 @@ ReindexPartitions(Oid relid, int options, bool isTopLevel) * and starts a new transaction when finished. */ static void -ReindexMultipleInternal(List *relids, int options) +ReindexMultipleInternal(List *relids, ReindexOptions *options) { ListCell *l; @@ -2991,35 +3027,41 @@ ReindexMultipleInternal(List *relids, int options) Assert(relkind != RELKIND_PARTITIONED_INDEX && relkind != RELKIND_PARTITIONED_TABLE); - if ((options & REINDEXOPT_CONCURRENTLY) != 0 && + if ((options->flags & REINDEXOPT_CONCURRENTLY) != 0 && relpersistence != RELPERSISTENCE_TEMP) { - (void) ReindexRelationConcurrently(relid, - options | - REINDEXOPT_MISSING_OK); + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |= REINDEXOPT_MISSING_OK; + (void) ReindexRelationConcurrently(relid, &newoptions); /* ReindexRelationConcurrently() does the verbose output */ } else if (relkind == RELKIND_INDEX) { - reindex_index(relid, false, relpersistence, - options | - REINDEXOPT_REPORT_PROGRESS | - REINDEXOPT_MISSING_OK); + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |= + REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK; + reindex_index(relid, false, relpersistence, &newoptions); PopActiveSnapshot(); /* reindex_index() does the verbose output */ } else { bool result; + ReindexOptions newoptions; + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |= + REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK; result = reindex_relation(relid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, - options | - REINDEXOPT_REPORT_PROGRESS | - REINDEXOPT_MISSING_OK); + &newoptions); - if (result && (options & REINDEXOPT_VERBOSE)) + if (result && (options->flags & REINDEXOPT_VERBOSE) != 0) ereport(INFO, (errmsg("table \"%s.%s\" was reindexed", get_namespace_name(get_rel_namespace(relid)), @@ -3059,7 +3101,7 @@ ReindexMultipleInternal(List *relids, int options) * anyway, and a non-concurrent reindex is more efficient. */ static bool -ReindexRelationConcurrently(Oid relationOid, int options) +ReindexRelationConcurrently(Oid relationOid, ReindexOptions *options) { List *heapRelationIds = NIL; List *indexIds = NIL; @@ -3081,6 +3123,7 @@ ReindexRelationConcurrently(Oid relationOid, int options) PROGRESS_CREATEIDX_ACCESS_METHOD_OID }; int64 progress_vals[4]; + ReindexOptions *private_options; /* * Create a memory context that will survive forced transaction commits we @@ -3092,7 +3135,7 @@ ReindexRelationConcurrently(Oid relationOid, int options) "ReindexConcurrent", ALLOCSET_SMALL_SIZES); - if (options & REINDEXOPT_VERBOSE) + if ((options->flags & REINDEXOPT_VERBOSE) != 0) { /* Save data needed by REINDEX VERBOSE in private context */ oldcontext = MemoryContextSwitchTo(private_context); @@ -3105,6 +3148,16 @@ ReindexRelationConcurrently(Oid relationOid, int options) MemoryContextSwitchTo(oldcontext); } + /* + * Copy option set in the private context to be able to use them across + * multiple transactions. + */ + oldcontext = MemoryContextSwitchTo(private_context); + private_options = (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + memcpy(private_options, options, sizeof(ReindexOptions)); + options = private_options; + MemoryContextSwitchTo(oldcontext); + relkind = get_rel_relkind(relationOid); /* @@ -3137,7 +3190,7 @@ ReindexRelationConcurrently(Oid relationOid, int options) errmsg("cannot reindex system catalogs concurrently"))); /* Open relation to get its indexes */ - if ((options & REINDEXOPT_MISSING_OK) != 0) + if ((options->flags & REINDEXOPT_MISSING_OK) != 0) { heapRelation = try_table_open(relationOid, ShareUpdateExclusiveLock); @@ -3233,7 +3286,7 @@ ReindexRelationConcurrently(Oid relationOid, int options) case RELKIND_INDEX: { Oid heapId = IndexGetRelation(relationOid, - (options & REINDEXOPT_MISSING_OK) != 0); + (options->flags & REINDEXOPT_MISSING_OK) != 0); Relation heapRelation; /* if relation is missing, leave */ @@ -3262,7 +3315,7 @@ ReindexRelationConcurrently(Oid relationOid, int options) * to rebuild is not complete yet, and REINDEXOPT_MISSING_OK * should not be used once all the session locks are taken. */ - if ((options & REINDEXOPT_MISSING_OK) != 0) + if ((options->flags & REINDEXOPT_MISSING_OK) != 0) { heapRelation = try_table_open(heapId, ShareUpdateExclusiveLock); @@ -3754,7 +3807,7 @@ ReindexRelationConcurrently(Oid relationOid, int options) StartTransactionCommand(); /* Log what we did */ - if (options & REINDEXOPT_VERBOSE) + if ((options->flags & REINDEXOPT_VERBOSE) != 0) { if (relkind == RELKIND_INDEX) ereport(INFO, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 1fa9f19f08..7d6b321d75 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1854,6 +1854,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, { Oid heap_relid; Oid toast_relid; + ReindexOptions reindex_options = {0}; /* * This effectively deletes all rows in the table, and may be done @@ -1891,7 +1892,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, /* * Reconstruct the indexes to match, and we're done. */ - reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, 0); + reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, &reindex_options); } pgstat_count_truncate(rel); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 98270a1049..985450e8f8 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1916,17 +1916,17 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params) */ if (params->options & VACOPT_FULL) { - int cluster_options = 0; + ClusterOptions cluster_options = {0}; /* close relation before vacuuming, but hold lock until commit */ relation_close(onerel, NoLock); onerel = NULL; if ((params->options & VACOPT_VERBOSE) != 0) - cluster_options |= CLUOPT_VERBOSE; + cluster_options.flags |= CLUOPT_VERBOSE; /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */ - cluster_rel(relid, InvalidOid, cluster_options); + cluster_rel(relid, InvalidOid, &cluster_options); } else table_relation_vacuum(onerel, params, vac_strategy); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index a42ead7d69..d35499ce45 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -919,10 +919,10 @@ standard_ProcessUtility(PlannedStmt *pstmt, case T_ReindexStmt: { ReindexStmt *stmt = (ReindexStmt *) parsetree; - int options; + ReindexOptions *options; options = ReindexParseOptions(pstate, stmt); - if ((options & REINDEXOPT_CONCURRENTLY) != 0) + if ((options->flags & REINDEXOPT_CONCURRENTLY) != 0) PreventInTransactionBlock(isTopLevel, "REINDEX CONCURRENTLY"); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index bca37c536e..768f758fa0 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -347,6 +347,7 @@ ClosePortalStmt ClosePtrType Clump ClusterInfo +ClusterOptions ClusterStmt CmdType CoalesceExpr @@ -2050,6 +2051,7 @@ RegisNode RegisteredBgWorker ReindexErrorInfo ReindexObjectType +ReindexOptions ReindexStmt ReindexType RelFileNode
signature.asc
Description: PGP signature