Refactor option handling of CLUSTER, REINDEX and VACUUM
authorMichael Paquier <michael@paquier.xyz>
Mon, 18 Jan 2021 05:03:10 +0000 (14:03 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 18 Jan 2021 05:03:10 +0000 (14:03 +0900)
This continues the work done in b5913f6.  All the options of those
commands are changed to use hex values rather than enums to reduce the
risk of compatibility bugs when introducing new options.  Each option
set is moved into a new structure that can be extended with more
non-boolean options (this was already the case of VACUUM).  The code of
REINDEX is restructured so as manual REINDEX commands go through a
single routine from utility.c, like VACUUM, to ease the allocation
handling of option parameters when a command needs to go through
multiple transactions.

This can be used as a base infrastructure for future patches related to
those commands, including reindex filtering and tablespace support.

Per discussion with people mentioned below, as well as Alvaro Herrera
and Peter Eisentraut.

Author: Michael Paquier, Justin Pryzby
Reviewed-by: Alexey Kondratov, Justin Pryzby
Discussion: https://postgr.es/m/X8riynBLwxAD9uKk@paquier.xyz

src/backend/catalog/index.c
src/backend/commands/cluster.c
src/backend/commands/indexcmds.c
src/backend/commands/tablecmds.c
src/backend/commands/vacuum.c
src/backend/tcop/utility.c
src/include/catalog/index.h
src/include/commands/cluster.h
src/include/commands/defrem.h
src/include/commands/vacuum.h
src/tools/pgindent/typedefs.list

index cffbc0ac388edf8809bab9a9d87c28841f3e731d..b8cd35e995d18620c5fce93a4592d4f915c82a73 100644 (file)
@@ -3594,7 +3594,7 @@ IndexGetRelation(Oid indexId, bool missing_ok)
  */
 void
 reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
-             int options)
+             ReindexParams *params)
 {
    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 = ((params->options & 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);
+                             (params->options & REINDEXOPT_MISSING_OK) != 0);
    /* if relation is missing, leave */
    if (!OidIsValid(heapId))
        return;
 
-   if ((options & REINDEXOPT_MISSING_OK) != 0)
+   if ((params->options & 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 ((params->options & 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, ReindexParams *params)
 {
    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 ((params->options & REINDEXOPT_MISSING_OK) != 0)
        rel = try_table_open(relid, ShareLock);
    else
        rel = table_open(relid, ShareLock);
@@ -3935,7 +3935,7 @@ reindex_relation(Oid relid, int flags, int options)
        }
 
        reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-                     persistence, options);
+                     persistence, params);
 
        CommandCounterIncrement();
 
@@ -3965,8 +3965,10 @@ 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));
+       ReindexParams newparams = *params;
+
+       newparams.options &= ~(REINDEXOPT_MISSING_OK);
+       result |= reindex_relation(toast_relid, flags, &newparams);
    }
 
    return result;
index d5eeb493ac45384dbd86fead3c60f0f8969be8e4..096a06f7b3b8d229ebbb85f8e78b518829fa3bbf 100644 (file)
@@ -103,7 +103,7 @@ void
 cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
 {
    ListCell   *lc;
-   int         options = 0;
+   ClusterParams params = {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);
+   params.options = (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, &params);
    }
    else
    {
@@ -234,14 +234,16 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
        foreach(rv, rvs)
        {
            RelToCluster *rvtc = (RelToCluster *) lfirst(rv);
+           ClusterParams cluster_params = params;
 
            /* Start a new transaction for each relation. */
            StartTransactionCommand();
            /* functions in indexes may want a snapshot set */
            PushActiveSnapshot(GetTransactionSnapshot());
            /* Do the job. */
+           cluster_params.options |= CLUOPT_RECHECK;
            cluster_rel(rvtc->tableOid, rvtc->indexOid,
-                       options | CLUOPT_RECHECK);
+                       &cluster_params);
            PopActiveSnapshot();
            CommitTransactionCommand();
        }
@@ -272,11 +274,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, ClusterParams *params)
 {
    Relation    OldHeap;
-   bool        verbose = ((options & CLUOPT_VERBOSE) != 0);
-   bool        recheck = ((options & CLUOPT_RECHECK) != 0);
+   bool        verbose = ((params->options & CLUOPT_VERBOSE) != 0);
+   bool        recheck = ((params->options & CLUOPT_RECHECK) != 0);
 
    /* Check for user-requested abort. */
    CHECK_FOR_INTERRUPTS();
@@ -1355,6 +1357,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
    ObjectAddress object;
    Oid         mapped_tables[4];
    int         reindex_flags;
+   ReindexParams reindex_params = {0};
    int         i;
 
    /* Report that we are now swapping relation files */
@@ -1412,7 +1415,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_params);
 
    /* Report that we are now doing clean up */
    pgstat_progress_update_param(PROGRESS_CLUSTER_PHASE,
index 1b71859020c8f4b572c5414c75bc6f018f5d0674..f9f3ff3b629b30017c25958a3c4df8772d3d94de 100644 (file)
@@ -86,12 +86,21 @@ static char *ChooseIndexName(const char *tabname, Oid namespaceId,
                             bool primary, bool isconstraint);
 static char *ChooseIndexNameAddition(List *colnames);
 static List *ChooseIndexColumnNames(List *indexElems);
+static void ReindexIndex(RangeVar *indexRelation, ReindexParams *params,
+                        bool isTopLevel);
 static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
                                            Oid relId, Oid oldRelId, void *arg);
+static Oid ReindexTable(RangeVar *relation, ReindexParams *params,
+                        bool isTopLevel);
+static void ReindexMultipleTables(const char *objectName,
+                                 ReindexObjectType objectKind, ReindexParams *params);
 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, ReindexParams *params,
+                             bool isTopLevel);
+static void ReindexMultipleInternal(List *relids,
+                                   ReindexParams *params);
+static bool ReindexRelationConcurrently(Oid relationOid,
+                                       ReindexParams *params);
 static void update_relispartition(Oid relationId, bool newval);
 static inline void set_indexsafe_procflags(void);
 
@@ -100,7 +109,7 @@ static inline void set_indexsafe_procflags(void);
  */
 struct ReindexIndexCallbackState
 {
-   int         options;        /* options from statement */
+   ReindexParams params;       /* options from statement */
    Oid         locked_table_oid;   /* tracks previously locked table */
 };
 
@@ -2452,14 +2461,17 @@ ChooseIndexColumnNames(List *indexElems)
 }
 
 /*
- * ReindexParseOptions
- *     Parse list of REINDEX options, returning a bitmask of ReindexOption.
+ * ExecReindex
+ *
+ * Primary entry point for manual REINDEX commands.  This is mainly a
+ * preparation wrapper for the real operations that will happen in
+ * each subroutine of REINDEX.
  */
-int
-ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt)
+void
+ExecReindex(ParseState *pstate, ReindexStmt *stmt, bool isTopLevel)
 {
+   ReindexParams params = {0};
    ListCell   *lc;
-   int         options = 0;
    bool        concurrently = false;
    bool        verbose = false;
 
@@ -2480,19 +2492,51 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt)
                     parser_errposition(pstate, opt->location)));
    }
 
-   options =
+   if (concurrently)
+       PreventInTransactionBlock(isTopLevel,
+                                 "REINDEX CONCURRENTLY");
+
+   params.options =
        (verbose ? REINDEXOPT_VERBOSE : 0) |
        (concurrently ? REINDEXOPT_CONCURRENTLY : 0);
 
-   return options;
+   switch (stmt->kind)
+   {
+       case REINDEX_OBJECT_INDEX:
+           ReindexIndex(stmt->relation, &params, isTopLevel);
+           break;
+       case REINDEX_OBJECT_TABLE:
+           ReindexTable(stmt->relation, &params, isTopLevel);
+           break;
+       case REINDEX_OBJECT_SCHEMA:
+       case REINDEX_OBJECT_SYSTEM:
+       case REINDEX_OBJECT_DATABASE:
+
+           /*
+            * This cannot run inside a user transaction block; if we were
+            * inside a transaction, then its commit- and
+            * start-transaction-command calls would not have the intended
+            * effect!
+            */
+           PreventInTransactionBlock(isTopLevel,
+                                     (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
+                                     (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
+                                     "REINDEX DATABASE");
+           ReindexMultipleTables(stmt->name, stmt->kind, &params);
+           break;
+       default:
+           elog(ERROR, "unrecognized object type: %d",
+                (int) stmt->kind);
+           break;
+   }
 }
 
 /*
  * ReindexIndex
  *     Recreate a specific index.
  */
-void
-ReindexIndex(RangeVar *indexRelation, int options, bool isTopLevel)
+static void
+ReindexIndex(RangeVar *indexRelation, ReindexParams *params, bool isTopLevel)
 {
    struct ReindexIndexCallbackState state;
    Oid         indOid;
@@ -2509,10 +2553,10 @@ 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.params = *params;
    state.locked_table_oid = InvalidOid;
    indOid = RangeVarGetRelidExtended(indexRelation,
-                                     (options & REINDEXOPT_CONCURRENTLY) != 0 ?
+                                     (params->options & REINDEXOPT_CONCURRENTLY) != 0 ?
                                      ShareUpdateExclusiveLock : AccessExclusiveLock,
                                      0,
                                      RangeVarCallbackForReindexIndex,
@@ -2526,13 +2570,17 @@ ReindexIndex(RangeVar *indexRelation, int options, bool isTopLevel)
    relkind = get_rel_relkind(indOid);
 
    if (relkind == RELKIND_PARTITIONED_INDEX)
-       ReindexPartitions(indOid, options, isTopLevel);
-   else if ((options & REINDEXOPT_CONCURRENTLY) != 0 &&
+       ReindexPartitions(indOid, params, isTopLevel);
+   else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
             persistence != RELPERSISTENCE_TEMP)
-       ReindexRelationConcurrently(indOid, options);
+       ReindexRelationConcurrently(indOid, params);
    else
-       reindex_index(indOid, false, persistence,
-                     options | REINDEXOPT_REPORT_PROGRESS);
+   {
+       ReindexParams newparams = *params;
+
+       newparams.options |= REINDEXOPT_REPORT_PROGRESS;
+       reindex_index(indOid, false, persistence, &newparams);
+   }
 }
 
 /*
@@ -2553,7 +2601,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
     * non-concurrent case and table locks used by index_concurrently_*() for
     * concurrent case.
     */
-   table_lockmode = ((state->options & REINDEXOPT_CONCURRENTLY) != 0) ?
+   table_lockmode = (state->params.options & REINDEXOPT_CONCURRENTLY) != 0 ?
        ShareUpdateExclusiveLock : ShareLock;
 
    /*
@@ -2610,8 +2658,8 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  * ReindexTable
  *     Recreate all indexes of a table (and of its toast table, if any)
  */
-Oid
-ReindexTable(RangeVar *relation, int options, bool isTopLevel)
+static Oid
+ReindexTable(RangeVar *relation, ReindexParams *params, bool isTopLevel)
 {
    Oid         heapOid;
    bool        result;
@@ -2625,17 +2673,17 @@ ReindexTable(RangeVar *relation, int options, bool isTopLevel)
     * locks on our temporary table.
     */
    heapOid = RangeVarGetRelidExtended(relation,
-                                      (options & REINDEXOPT_CONCURRENTLY) != 0 ?
+                                      (params->options & 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 &&
+       ReindexPartitions(heapOid, params, isTopLevel);
+   else if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
             get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP)
    {
-       result = ReindexRelationConcurrently(heapOid, options);
+       result = ReindexRelationConcurrently(heapOid, params);
 
        if (!result)
            ereport(NOTICE,
@@ -2644,10 +2692,13 @@ ReindexTable(RangeVar *relation, int options, bool isTopLevel)
    }
    else
    {
+       ReindexParams newparams = *params;
+
+       newparams.options |= REINDEXOPT_REPORT_PROGRESS;
        result = reindex_relation(heapOid,
                                  REINDEX_REL_PROCESS_TOAST |
                                  REINDEX_REL_CHECK_CONSTRAINTS,
-                                 options | REINDEXOPT_REPORT_PROGRESS);
+                                 &newparams);
        if (!result)
            ereport(NOTICE,
                    (errmsg("table \"%s\" has no indexes to reindex",
@@ -2665,9 +2716,9 @@ ReindexTable(RangeVar *relation, int options, bool isTopLevel)
  * separate transaction, so we can release the lock on it right away.
  * That means this must not be called within a user transaction block!
  */
-void
+static void
 ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
-                     int options)
+                     ReindexParams *params)
 {
    Oid         objectOid;
    Relation    relationRelation;
@@ -2686,7 +2737,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
           objectKind == REINDEX_OBJECT_DATABASE);
 
    if (objectKind == REINDEX_OBJECT_SYSTEM &&
-       (options & REINDEXOPT_CONCURRENTLY) != 0)
+       (params->options & REINDEXOPT_CONCURRENTLY) != 0)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("cannot reindex system catalogs concurrently")));
@@ -2794,7 +2845,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 ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
            IsCatalogRelationOid(relid))
        {
            if (!concurrent_warning)
@@ -2829,7 +2880,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
     * Process each relation listed in a separate transaction.  Note that this
     * commits and then starts a new transaction immediately.
     */
-   ReindexMultipleInternal(relids, options);
+   ReindexMultipleInternal(relids, params);
 
    MemoryContextDelete(private_context);
 }
@@ -2860,7 +2911,7 @@ reindex_error_callback(void *arg)
  * by the caller.
  */
 static void
-ReindexPartitions(Oid relid, int options, bool isTopLevel)
+ReindexPartitions(Oid relid, ReindexParams *params, bool isTopLevel)
 {
    List       *partitions = NIL;
    char        relkind = get_rel_relkind(relid);
@@ -2937,7 +2988,7 @@ ReindexPartitions(Oid relid, int options, bool isTopLevel)
     * Process each partition listed in a separate transaction.  Note that
     * this commits and then starts a new transaction immediately.
     */
-   ReindexMultipleInternal(partitions, options);
+   ReindexMultipleInternal(partitions, params);
 
    /*
     * Clean up working storage --- note we must do this after
@@ -2955,7 +3006,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, ReindexParams *params)
 {
    ListCell   *l;
 
@@ -2991,35 +3042,38 @@ ReindexMultipleInternal(List *relids, int options)
        Assert(relkind != RELKIND_PARTITIONED_INDEX &&
               relkind != RELKIND_PARTITIONED_TABLE);
 
-       if ((options & REINDEXOPT_CONCURRENTLY) != 0 &&
+       if ((params->options & REINDEXOPT_CONCURRENTLY) != 0 &&
            relpersistence != RELPERSISTENCE_TEMP)
        {
-           (void) ReindexRelationConcurrently(relid,
-                                              options |
-                                              REINDEXOPT_MISSING_OK);
+           ReindexParams newparams = *params;
+
+           newparams.options |= REINDEXOPT_MISSING_OK;
+           (void) ReindexRelationConcurrently(relid, &newparams);
            /* ReindexRelationConcurrently() does the verbose output */
        }
        else if (relkind == RELKIND_INDEX)
        {
-           reindex_index(relid, false, relpersistence,
-                         options |
-                         REINDEXOPT_REPORT_PROGRESS |
-                         REINDEXOPT_MISSING_OK);
+           ReindexParams newparams = *params;
+
+           newparams.options |=
+               REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK;
+           reindex_index(relid, false, relpersistence, &newparams);
            PopActiveSnapshot();
            /* reindex_index() does the verbose output */
        }
        else
        {
            bool        result;
+           ReindexParams newparams = *params;
 
+           newparams.options |=
+               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);
+                                     &newparams);
 
-           if (result && (options & REINDEXOPT_VERBOSE))
+           if (result && (params->options & REINDEXOPT_VERBOSE) != 0)
                ereport(INFO,
                        (errmsg("table \"%s.%s\" was reindexed",
                                get_namespace_name(get_rel_namespace(relid)),
@@ -3059,7 +3113,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, ReindexParams *params)
 {
    typedef struct ReindexIndexInfo
    {
@@ -3099,7 +3153,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
                                            "ReindexConcurrent",
                                            ALLOCSET_SMALL_SIZES);
 
-   if (options & REINDEXOPT_VERBOSE)
+   if ((params->options & REINDEXOPT_VERBOSE) != 0)
    {
        /* Save data needed by REINDEX VERBOSE in private context */
        oldcontext = MemoryContextSwitchTo(private_context);
@@ -3144,7 +3198,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 ((params->options & REINDEXOPT_MISSING_OK) != 0)
                {
                    heapRelation = try_table_open(relationOid,
                                                  ShareUpdateExclusiveLock);
@@ -3251,7 +3305,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
        case RELKIND_INDEX:
            {
                Oid         heapId = IndexGetRelation(relationOid,
-                                                     (options & REINDEXOPT_MISSING_OK) != 0);
+                                                     (params->options & REINDEXOPT_MISSING_OK) != 0);
                Relation    heapRelation;
                ReindexIndexInfo *idx;
 
@@ -3281,7 +3335,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 ((params->options & REINDEXOPT_MISSING_OK) != 0)
                {
                    heapRelation = try_table_open(heapId,
                                                  ShareUpdateExclusiveLock);
@@ -3803,7 +3857,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
    StartTransactionCommand();
 
    /* Log what we did */
-   if (options & REINDEXOPT_VERBOSE)
+   if ((params->options & REINDEXOPT_VERBOSE) != 0)
    {
        if (relkind == RELKIND_INDEX)
            ereport(INFO,
index fd55bf4ac7dd9261cb9d40ab60ce077378d478a8..8687e9a97c5bbbf92b39eca438856caa9b1d27b1 100644 (file)
@@ -1854,6 +1854,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
        {
            Oid         heap_relid;
            Oid         toast_relid;
+           ReindexParams reindex_params = {0};
 
            /*
             * This effectively deletes all rows in the table, and may be done
@@ -1891,7 +1892,8 @@ 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_params);
        }
 
        pgstat_count_truncate(rel);
index b97d48ee01e3b4a752cf86bdf186dd3c29b67e77..462f9a0f8225cfa7331b3e393abbc35333186c64 100644 (file)
@@ -530,7 +530,7 @@ vacuum(List *relations, VacuumParams *params,
  * ANALYZE.
  */
 bool
-vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, int options)
+vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, bits32 options)
 {
    char       *relname;
 
@@ -604,7 +604,7 @@ vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, int options)
  * or locked, a log is emitted if possible.
  */
 Relation
-vacuum_open_relation(Oid relid, RangeVar *relation, int options,
+vacuum_open_relation(Oid relid, RangeVar *relation, bits32 options,
                     bool verbose, LOCKMODE lmode)
 {
    Relation    onerel;
@@ -1916,17 +1916,17 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
     */
    if (params->options & VACOPT_FULL)
    {
-       int         cluster_options = 0;
+       ClusterParams cluster_params = {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_params.options |= CLUOPT_VERBOSE;
 
        /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
-       cluster_rel(relid, InvalidOid, cluster_options);
+       cluster_rel(relid, InvalidOid, &cluster_params);
    }
    else
        table_relation_vacuum(onerel, params, vac_strategy);
index 53a511f1da81e0095c45572984ddf30c41e8e927..1d81071c35724a0c8db91b43bb2f40d4dc491ccd 100644 (file)
@@ -917,45 +917,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
            break;
 
        case T_ReindexStmt:
-           {
-               ReindexStmt *stmt = (ReindexStmt *) parsetree;
-               int         options;
-
-               options = ReindexParseOptions(pstate, stmt);
-               if ((options & REINDEXOPT_CONCURRENTLY) != 0)
-                   PreventInTransactionBlock(isTopLevel,
-                                             "REINDEX CONCURRENTLY");
-
-               switch (stmt->kind)
-               {
-                   case REINDEX_OBJECT_INDEX:
-                       ReindexIndex(stmt->relation, options, isTopLevel);
-                       break;
-                   case REINDEX_OBJECT_TABLE:
-                       ReindexTable(stmt->relation, options, isTopLevel);
-                       break;
-                   case REINDEX_OBJECT_SCHEMA:
-                   case REINDEX_OBJECT_SYSTEM:
-                   case REINDEX_OBJECT_DATABASE:
-
-                       /*
-                        * This cannot run inside a user transaction block; if
-                        * we were inside a transaction, then its commit- and
-                        * start-transaction-command calls would not have the
-                        * intended effect!
-                        */
-                       PreventInTransactionBlock(isTopLevel,
-                                                 (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
-                                                 (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
-                                                 "REINDEX DATABASE");
-                       ReindexMultipleTables(stmt->name, stmt->kind, options);
-                       break;
-                   default:
-                       elog(ERROR, "unrecognized object type: %d",
-                            (int) stmt->kind);
-                       break;
-               }
-           }
+           ExecReindex(pstate, (ReindexStmt *) parsetree, isTopLevel);
            break;
 
            /*
index 9904a76387a55b104e8de8124cef116f0c997aeb..266f8950dcc08b6cc1097ecc0686e4a9ab6561aa 100644 (file)
@@ -30,13 +30,16 @@ typedef enum
 } IndexStateFlagsAction;
 
 /* options for REINDEX */
-typedef enum ReindexOption
+typedef struct ReindexParams
 {
-   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      options;        /* bitmask of REINDEXOPT_* */
+} ReindexParams;
+
+/* flag bits for ReindexParams->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, ReindexParams *params);
 
 /* 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, ReindexParams *params);
 
 extern bool ReindexIsProcessingHeap(Oid heapOid);
 extern bool ReindexIsProcessingIndex(Oid indexOid);
index 401a0827aecff8c8907922632d7e0453a4b493a0..a941f2accdaed5ac7dbec463074f4d07562f462b 100644 (file)
 #include "utils/relcache.h"
 
 
+/* flag bits for ClusterParams->flags */
+#define CLUOPT_RECHECK 0x01        /* recheck relation state */
+#define CLUOPT_VERBOSE 0x02        /* print progress info */
+
 /* options for CLUSTER */
-typedef enum ClusterOption
+typedef struct ClusterParams
 {
-   CLUOPT_RECHECK = 1 << 0,    /* recheck relation state */
-   CLUOPT_VERBOSE = 1 << 1     /* print progress info */
-} ClusterOption;
+   bits32      options;        /* bitmask of CLUOPT_* */
+} ClusterParams;
 
 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, ClusterParams *params);
 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);
index e2d2a77ca49d589f83e36390b40e688c263d65db..1a79540c94deba58b998a12363f2792ab0d773ec 100644 (file)
@@ -34,11 +34,7 @@ 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 void ExecReindex(ParseState *pstate, ReindexStmt *stmt, bool isTopLevel);
 extern char *makeObjectName(const char *name1, const char *name2,
                            const char *label);
 extern char *ChooseRelationName(const char *name1, const char *name2,
index 857509287d76797830a8f47253c48f87ebd940df..191cbbd0049390e43f7ae8ba1b6eacca3d44e4cb 100644 (file)
@@ -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.
@@ -207,7 +205,7 @@ typedef enum VacOptTernaryValue
  */
 typedef struct VacuumParams
 {
-   int         options;        /* bitmask of VacuumOption */
+   bits32      options;        /* bitmask of VACOPT_* */
    int         freeze_min_age; /* min freeze age, -1 to use default */
    int         freeze_table_age;   /* age at which to scan whole table */
    int         multixact_freeze_min_age;   /* min multixact freeze age, -1 to
@@ -275,9 +273,10 @@ extern void vacuum_set_xid_limits(Relation rel,
 extern void vac_update_datfrozenxid(void);
 extern void vacuum_delay_point(void);
 extern bool vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple,
-                                    int options);
+                                    bits32 options);
 extern Relation vacuum_open_relation(Oid relid, RangeVar *relation,
-                                    int options, bool verbose, LOCKMODE lmode);
+                                    bits32 options, bool verbose,
+                                    LOCKMODE lmode);
 
 /* in commands/analyze.c */
 extern void analyze_rel(Oid relid, RangeVar *relation,
index fb57b8393f1774c120620b1308c3623704a2843d..943142ced8c197f0e8a4f0194da50911e12854ba 100644 (file)
@@ -347,6 +347,7 @@ ClosePortalStmt
 ClosePtrType
 Clump
 ClusterInfo
+ClusterParams
 ClusterStmt
 CmdType
 CoalesceExpr
@@ -2063,6 +2064,7 @@ RegisteredBgWorker
 ReindexErrorInfo
 ReindexIndexInfo
 ReindexObjectType
+ReindexParams
 ReindexStmt
 ReindexType
 RelFileNode