Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kreQe-0007f5-PI for pgsql-hackers@arkaria.postgresql.org; Tue, 22 Dec 2020 09:58:05 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kreQd-0002uZ-CF for pgsql-hackers@arkaria.postgresql.org; Tue, 22 Dec 2020 09:58:03 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kreQb-0002uS-Um for pgsql-hackers@lists.postgresql.org; Tue, 22 Dec 2020 09:58:03 +0000 Received: from new3-smtp.messagingengine.com ([66.111.4.229]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kreQS-0003rJ-VU for pgsql-hackers@lists.postgresql.org; Tue, 22 Dec 2020 09:58:01 +0000 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.nyi.internal (Postfix) with ESMTP id A70A9580233; Tue, 22 Dec 2020 04:57:49 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Tue, 22 Dec 2020 04:57:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paquier.xyz; h= date:from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm3; bh=Pv4v3LZkeBD97DEHTnscm72Gqti 688oCranocB6+Dao=; b=VxkCE28+ft+JUmuKYIYvyidGqxCx4CzpqTtiK5/hoRK RQ7L80z0vSADnAGkkiLYmNamDgHRhxosQvAOitfhGz65J+97CAIsqusqeHR7kpba 7j1WHA/04aLXq6cj2YApVTIHr41qtPhO3PXaSNFUEhFI8bp671A87PcT2NQ6QhTC zWv390yI5PEdnTotv7cQbByY2isZtW8G3o/6oRSq8NKUigRLDfGzsNvcEe0kCB5R 9unrVPxm4LdhS9nEF1cc4A+RLbzmH12jHNtb+YV7g2EMRWZHbZceZcsHh4UazL5f jUj48/ax3papz91JvHQSGwo71nZh5fCZYz7+hmVPajw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=Pv4v3L ZkeBD97DEHTnscm72Gqti688oCranocB6+Dao=; b=lIGl0pNb1ARDyF2HPo1WDX iSuXeen+ULL36WVWM6S1HagjhlGT/PELB81sA6vSY4ndpKm0Lh3bIgFCAnXtwZuX dx5+o93MJIiNqygnOiA6rDyBILq4yI/j5fm1M95jCvIzIWwj7tcgkTMN5CVLdgKS 2Bkj4RBqiujYzdcoYmskaL9TlfBYHPF5HOy5sT9Hb6ezQc9nosaYRZKWyoJ1UkzD 0AV/i5nEAYbzU6mU9gOAuVhAvFbjCjcve7rnuNX5UGO0M3CMdUcBwn+4mNxe5YJa eZllXEvWNE898CWXuOyWZjIS0p4AeXoGP2roi1eY7oJCSnSGYez9PCt5n6DInACg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvddtgedgtdelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne gfrhhlucfvnfffucdljedtmdenucfjughrpeffhffvuffkfhggtggujgesghdtreertddt vdenucfhrhhomhepofhitghhrggvlhcurfgrqhhuihgvrhcuoehmihgthhgrvghlsehprg hquhhivghrrdighiiiqeenucggtffrrghtthgvrhhnpedvgeduuefhtdeuleettdevjeeh heeiveeuieegleetgeeljeelieeuieehgeevhfenucfkphepudduuddruddtvddrudektd drudekheenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhm pehmihgthhgrvghlsehprghquhhivghrrdighiii X-ME-Proxy: Received: from paquier.xyz (ee0822lan1.rev.em-net.ne.jp [111.102.180.185]) by mail.messagingengine.com (Postfix) with ESMTPA id 2559E24005A; Tue, 22 Dec 2020 04:57:44 -0500 (EST) Date: Tue, 22 Dec 2020 18:57:41 +0900 From: Michael Paquier To: Justin Pryzby Cc: Alvaro Herrera , Peter Eisentraut , Alexey Kondratov , Masahiko Sawada , Steve Singer , pgsql-hackers@lists.postgresql.org, Robert Haas , Alexander Korotkov , Masahiko Sawada , Jose Luis Tallon Subject: Re: Allow CLUSTER, VACUUM FULL and REINDEX to change tablespace on the fly Message-ID: References: <7ec67c56-2377-cd05-51a0-691104404abe@enterprisedb.com> <20201216004517.GA18498@alvherre.pgsql> <20201222083204.GL30237@telsasoft.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="AH8BNNWAzIqByhE1" Content-Disposition: inline In-Reply-To: <20201222083204.GL30237@telsasoft.com> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --AH8BNNWAzIqByhE1 Content-Type: multipart/mixed; boundary="smhK4bMUIDbZnim9" Content-Disposition: inline --smhK4bMUIDbZnim9 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --smhK4bMUIDbZnim9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="refactor-utility-opts-michael-2.patch" Content-Transfer-Encoding: quoted-printable 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; =20 /* options for REINDEX */ -typedef enum ReindexOption +typedef struct ReindexOptions { - REINDEXOPT_VERBOSE =3D 1 << 0, /* print progress info */ - REINDEXOPT_REPORT_PROGRESS =3D 1 << 1, /* report pgstat progress */ - REINDEXOPT_MISSING_OK =3D 1 << 2, /* skip missing relations */ - REINDEXOPT_CONCURRENTLY =3D 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 */ =20 /* state info for validate_index bulkdelete callback */ typedef struct ValidateIndexState @@ -146,7 +149,7 @@ extern void index_set_state_flags(Oid indexId, IndexSta= teFlagsAction action); extern Oid IndexGetRelation(Oid indexId, bool missing_ok); =20 extern void reindex_index(Oid indexId, bool skip_constraint_checks, - char relpersistence, int options); + char relpersistence, ReindexOptions *options); =20 /* Flag bits for reindex_relation(): */ #define REINDEX_REL_PROCESS_TOAST 0x01 @@ -155,7 +158,7 @@ extern void reindex_index(Oid indexId, bool skip_constr= aint_checks, #define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08 #define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10 =20 -extern bool reindex_relation(Oid relid, int flags, int options); +extern bool reindex_relation(Oid relid, int flags, ReindexOptions *options= ); =20 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" =20 - /* 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 =3D 1 << 0, /* recheck relation state */ - CLUOPT_VERBOSE =3D 1 << 1 /* print progress info */ -} ClusterOption; + bits32 flags; /* bitmask of CLUSTEROPT_* */ +} ClusterOptions; =20 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 *option= s); 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_inter= nal); 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 =20 +#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 isTopL= evel); -extern Oid ReindexTable(RangeVar *relation, int options, bool isTopLevel); -extern void ReindexMultipleTables(const char *objectName, ReindexObjectTyp= e 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; =20 -typedef enum VacuumOption -{ - VACOPT_VACUUM =3D 1 << 0, /* do VACUUM */ - VACOPT_ANALYZE =3D 1 << 1, /* do ANALYZE */ - VACOPT_VERBOSE =3D 1 << 2, /* print progress info */ - VACOPT_FREEZE =3D 1 << 3, /* FREEZE option */ - VACOPT_FULL =3D 1 << 4, /* FULL (non-concurrent) vacuum */ - VACOPT_SKIP_LOCKED =3D 1 << 5, /* skip if cannot get lock */ - VACOPT_SKIPTOAST =3D 1 << 6, /* don't process the TOAST table, if any */ - VACOPT_DISABLE_PAGE_SKIPPING =3D 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 */ =20 /* * 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_check= s, char persistence, IndexInfo *indexInfo; volatile bool skipped_constraint =3D false; PGRUsage ru0; - bool progress =3D (options & REINDEXOPT_REPORT_PROGRESS) !=3D 0; + bool progress =3D ((options->flags & REINDEXOPT_REPORT_PROGRESS) !=3D 0); =20 pg_rusage_init(&ru0); =20 @@ -3611,12 +3611,12 @@ reindex_index(Oid indexId, bool skip_constraint_che= cks, char persistence, * we only need to be sure no schema or data changes are going on. */ heapId =3D IndexGetRelation(indexId, - (options & REINDEXOPT_MISSING_OK) !=3D 0); + (options->flags & REINDEXOPT_MISSING_OK) !=3D 0); /* if relation is missing, leave */ if (!OidIsValid(heapId)) return; =20 - if ((options & REINDEXOPT_MISSING_OK) !=3D 0) + if ((options->flags & REINDEXOPT_MISSING_OK) !=3D 0) heapRelation =3D try_table_open(heapId, ShareLock); else heapRelation =3D table_open(heapId, ShareLock); @@ -3792,7 +3792,7 @@ reindex_index(Oid indexId, bool skip_constraint_check= s, char persistence, } =20 /* Log what we did */ - if (options & REINDEXOPT_VERBOSE) + if ((options->flags & REINDEXOPT_VERBOSE) !=3D 0) ereport(INFO, (errmsg("index \"%s\" was reindexed", get_rel_name(indexId)), @@ -3846,7 +3846,7 @@ reindex_index(Oid indexId, bool skip_constraint_check= s, 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) !=3D 0) + if ((options->flags & REINDEXOPT_MISSING_OK) !=3D 0) rel =3D try_table_open(relid, ShareLock); else rel =3D 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 |=3D reindex_relation(toast_relid, flags, - options & ~(REINDEXOPT_MISSING_OK)); + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags &=3D ~(REINDEXOPT_MISSING_OK); + result |=3D reindex_relation(toast_relid, flags, &newoptions); } =20 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 =3D 0; + ClusterOptions options =3D {0}; bool verbose =3D false; =20 /* Parse option list */ @@ -121,7 +121,7 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isT= opLevel) parser_errposition(pstate, opt->location))); } =20 - options =3D (verbose ? CLUOPT_VERBOSE : 0); + options.flags =3D (verbose ? CLUOPT_VERBOSE : 0); =20 if (stmt->relation !=3D NULL) { @@ -192,7 +192,7 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isT= opLevel) table_close(rel, NoLock); =20 /* Do the job. */ - cluster_rel(tableOid, indexOid, options); + cluster_rel(tableOid, indexOid, &options); } else { @@ -234,6 +234,10 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool is= TopLevel) foreach(rv, rvs) { RelToCluster *rvtc =3D (RelToCluster *) lfirst(rv); + ClusterOptions cluster_options; + + memcpy(&cluster_options, &options, sizeof(ClusterOptions)); + cluster_options.flags |=3D CLUOPT_RECHECK; =20 /* Start a new transaction for each relation. */ StartTransactionCommand(); @@ -241,7 +245,7 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isT= opLevel) 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 i= sTopLevel) * 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 =3D ((options & CLUOPT_VERBOSE) !=3D 0); - bool recheck =3D ((options & CLUOPT_RECHECK) !=3D 0); + bool verbose =3D ((options->flags & CLUOPT_VERBOSE) !=3D 0); + bool recheck =3D ((options->flags & CLUOPT_RECHECK) !=3D 0); =20 /* 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 =3D {0}; int i; =20 /* 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); =20 - reindex_relation(OIDOldHeap, reindex_flags, 0); + reindex_relation(OIDOldHeap, reindex_flags, &reindex_options); =20 /* 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/indexc= mds.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); =20 @@ -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 */ }; =20 @@ -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 =3D 0; + ReindexOptions *options; bool concurrently =3D false; bool verbose =3D false; =20 + options =3D (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))); } =20 - options =3D + options->flags =3D (verbose ? REINDEXOPT_VERBOSE : 0) | (concurrently ? REINDEXOPT_CONCURRENTLY : 0); =20 @@ -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 isTopL= evel) { 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 =3D options; + state.options =3D (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + memcpy(state.options, options, sizeof(ReindexOptions)); state.locked_table_oid =3D InvalidOid; indOid =3D RangeVarGetRelidExtended(indexRelation, - (options & REINDEXOPT_CONCURRENTLY) !=3D 0 ? + (options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 ? ShareUpdateExclusiveLock : AccessExclusiveLock, 0, RangeVarCallbackForReindexIndex, @@ -2527,12 +2533,17 @@ ReindexIndex(RangeVar *indexRelation, int options, = bool isTopLevel) =20 if (relkind =3D=3D RELKIND_PARTITIONED_INDEX) ReindexPartitions(indOid, options, isTopLevel); - else if ((options & REINDEXOPT_CONCURRENTLY) !=3D 0 && + else if ((options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 && persistence !=3D RELPERSISTENCE_TEMP) ReindexRelationConcurrently(indOid, options); else - reindex_index(indOid, false, persistence, - options | REINDEXOPT_REPORT_PROGRESS); + { + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |=3D REINDEXOPT_REPORT_PROGRESS; + reindex_index(indOid, false, persistence, &newoptions); + } } =20 /* @@ -2547,13 +2558,14 @@ RangeVarCallbackForReindexIndex(const RangeVar *rel= ation, char relkind; struct ReindexIndexCallbackState *state =3D arg; LOCKMODE table_lockmode; + ReindexOptions *options =3D state->options; =20 /* * 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 =3D ((state->options & REINDEXOPT_CONCURRENTLY) !=3D 0) ? + table_lockmode =3D (options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 ? ShareUpdateExclusiveLock : ShareLock; =20 /* @@ -2611,7 +2623,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relat= ion, * 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 =3D RangeVarGetRelidExtended(relation, - (options & REINDEXOPT_CONCURRENTLY) !=3D 0 ? + (options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 ? ShareUpdateExclusiveLock : ShareLock, 0, RangeVarCallbackOwnsTable, NULL); =20 if (get_rel_relkind(heapOid) =3D=3D RELKIND_PARTITIONED_TABLE) ReindexPartitions(heapOid, options, isTopLevel); - else if ((options & REINDEXOPT_CONCURRENTLY) !=3D 0 && + else if ((options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 && get_rel_persistence(heapOid) !=3D RELPERSISTENCE_TEMP) { result =3D ReindexRelationConcurrently(heapOid, options); @@ -2644,10 +2656,14 @@ ReindexTable(RangeVar *relation, int options, bool = isTopLevel) } else { + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |=3D REINDEXOPT_REPORT_PROGRESS; result =3D 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 is= TopLevel) */ void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, - int options) + ReindexOptions *options) { Oid objectOid; Relation relationRelation; @@ -2679,6 +2695,7 @@ ReindexMultipleTables(const char *objectName, Reindex= ObjectType objectKind, List *relids =3D NIL; int num_keys; bool concurrent_warning =3D false; + ReindexOptions *private_options; =20 AssertArg(objectName); Assert(objectKind =3D=3D REINDEX_OBJECT_SCHEMA || @@ -2686,7 +2703,7 @@ ReindexMultipleTables(const char *objectName, Reindex= ObjectType objectKind, objectKind =3D=3D REINDEX_OBJECT_DATABASE); =20 if (objectKind =3D=3D REINDEX_OBJECT_SYSTEM && - (options & REINDEXOPT_CONCURRENTLY) !=3D 0) + (options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot reindex system catalogs concurrently"))); @@ -2794,7 +2811,7 @@ ReindexMultipleTables(const char *objectName, Reindex= ObjectType objectKind, * Skip system tables, since index_create() would reject indexing them * concurrently (and it would likely fail if we tried). */ - if ((options & REINDEXOPT_CONCURRENTLY) !=3D 0 && + if ((options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 && IsCatalogRelationOid(relid)) { if (!concurrent_warning) @@ -2825,11 +2842,20 @@ ReindexMultipleTables(const char *objectName, Reind= exObjectType objectKind, table_endscan(scan); table_close(relationRelation, AccessShareLock); =20 + /* + * Copy option set in the private context to be able to use them across + * multiple transactions. + */ + old =3D MemoryContextSwitchTo(private_context); + private_options =3D (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); =20 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 =3D NIL; char relkind =3D get_rel_relkind(relid); char *relname =3D get_rel_name(relid); char *relnamespace =3D get_namespace_name(get_rel_namespace(relid)); MemoryContext reindex_context; + MemoryContext old_context; List *inhoids; ListCell *lc; ErrorContextCallback errcallback; ReindexErrorInfo errinfo; + ReindexOptions *private_options; =20 Assert(relkind =3D=3D RELKIND_PARTITIONED_INDEX || relkind =3D=3D RELKIND_PARTITIONED_TABLE); @@ -2915,7 +2943,6 @@ ReindexPartitions(Oid relid, int options, bool isTopL= evel) { Oid partoid =3D lfirst_oid(lc); char partkind =3D get_rel_relkind(partoid); - MemoryContext old_context; =20 /* * This discards partitioned tables, partitioned indexes and foreign @@ -2933,11 +2960,20 @@ ReindexPartitions(Oid relid, int options, bool isTo= pLevel) MemoryContextSwitchTo(old_context); } =20 + /* + * Copy option set in the private context to be able to use them across + * multiple transactions. + */ + old_context =3D MemoryContextSwitchTo(reindex_context); + private_options =3D (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); =20 /* * Clean up working storage --- note we must do this after @@ -2955,7 +2991,7 @@ ReindexPartitions(Oid relid, int options, bool isTopL= evel) * and starts a new transaction when finished. */ static void -ReindexMultipleInternal(List *relids, int options) +ReindexMultipleInternal(List *relids, ReindexOptions *options) { ListCell *l; =20 @@ -2991,35 +3027,41 @@ ReindexMultipleInternal(List *relids, int options) Assert(relkind !=3D RELKIND_PARTITIONED_INDEX && relkind !=3D RELKIND_PARTITIONED_TABLE); =20 - if ((options & REINDEXOPT_CONCURRENTLY) !=3D 0 && + if ((options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0 && relpersistence !=3D RELPERSISTENCE_TEMP) { - (void) ReindexRelationConcurrently(relid, - options | - REINDEXOPT_MISSING_OK); + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |=3D REINDEXOPT_MISSING_OK; + (void) ReindexRelationConcurrently(relid, &newoptions); /* ReindexRelationConcurrently() does the verbose output */ } else if (relkind =3D=3D RELKIND_INDEX) { - reindex_index(relid, false, relpersistence, - options | - REINDEXOPT_REPORT_PROGRESS | - REINDEXOPT_MISSING_OK); + ReindexOptions newoptions; + + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |=3D + REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK; + reindex_index(relid, false, relpersistence, &newoptions); PopActiveSnapshot(); /* reindex_index() does the verbose output */ } else { bool result; + ReindexOptions newoptions; =20 + memcpy(&newoptions, options, sizeof(ReindexOptions)); + newoptions.flags |=3D + REINDEXOPT_REPORT_PROGRESS | REINDEXOPT_MISSING_OK; result =3D reindex_relation(relid, REINDEX_REL_PROCESS_TOAST | REINDEX_REL_CHECK_CONSTRAINTS, - options | - REINDEXOPT_REPORT_PROGRESS | - REINDEXOPT_MISSING_OK); + &newoptions); =20 - if (result && (options & REINDEXOPT_VERBOSE)) + if (result && (options->flags & REINDEXOPT_VERBOSE) !=3D 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 =3D NIL; List *indexIds =3D NIL; @@ -3081,6 +3123,7 @@ ReindexRelationConcurrently(Oid relationOid, int opti= ons) PROGRESS_CREATEIDX_ACCESS_METHOD_OID }; int64 progress_vals[4]; + ReindexOptions *private_options; =20 /* * Create a memory context that will survive forced transaction commits we @@ -3092,7 +3135,7 @@ ReindexRelationConcurrently(Oid relationOid, int opti= ons) "ReindexConcurrent", ALLOCSET_SMALL_SIZES); =20 - if (options & REINDEXOPT_VERBOSE) + if ((options->flags & REINDEXOPT_VERBOSE) !=3D 0) { /* Save data needed by REINDEX VERBOSE in private context */ oldcontext =3D MemoryContextSwitchTo(private_context); @@ -3105,6 +3148,16 @@ ReindexRelationConcurrently(Oid relationOid, int opt= ions) MemoryContextSwitchTo(oldcontext); } =20 + /* + * Copy option set in the private context to be able to use them across + * multiple transactions. + */ + oldcontext =3D MemoryContextSwitchTo(private_context); + private_options =3D (ReindexOptions *) palloc0(sizeof(ReindexOptions)); + memcpy(private_options, options, sizeof(ReindexOptions)); + options =3D private_options; + MemoryContextSwitchTo(oldcontext); + relkind =3D get_rel_relkind(relationOid); =20 /* @@ -3137,7 +3190,7 @@ ReindexRelationConcurrently(Oid relationOid, int opti= ons) errmsg("cannot reindex system catalogs concurrently"))); =20 /* Open relation to get its indexes */ - if ((options & REINDEXOPT_MISSING_OK) !=3D 0) + if ((options->flags & REINDEXOPT_MISSING_OK) !=3D 0) { heapRelation =3D try_table_open(relationOid, ShareUpdateExclusiveLock); @@ -3233,7 +3286,7 @@ ReindexRelationConcurrently(Oid relationOid, int opti= ons) case RELKIND_INDEX: { Oid heapId =3D IndexGetRelation(relationOid, - (options & REINDEXOPT_MISSING_OK) !=3D 0); + (options->flags & REINDEXOPT_MISSING_OK) !=3D 0); Relation heapRelation; =20 /* if relation is missing, leave */ @@ -3262,7 +3315,7 @@ ReindexRelationConcurrently(Oid relationOid, int opti= ons) * 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) !=3D 0) + if ((options->flags & REINDEXOPT_MISSING_OK) !=3D 0) { heapRelation =3D try_table_open(heapId, ShareUpdateExclusiveLock); @@ -3754,7 +3807,7 @@ ReindexRelationConcurrently(Oid relationOid, int opti= ons) StartTransactionCommand(); =20 /* Log what we did */ - if (options & REINDEXOPT_VERBOSE) + if ((options->flags & REINDEXOPT_VERBOSE) !=3D 0) { if (relkind =3D=3D RELKIND_INDEX) ereport(INFO, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablec= mds.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 =3D {0}; =20 /* * 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_option= s); } =20 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, VacuumPar= ams *params) */ if (params->options & VACOPT_FULL) { - int cluster_options =3D 0; + ClusterOptions cluster_options =3D {0}; =20 /* close relation before vacuuming, but hold lock until commit */ relation_close(onerel, NoLock); onerel =3D NULL; =20 if ((params->options & VACOPT_VERBOSE) !=3D 0) - cluster_options |=3D CLUOPT_VERBOSE; + cluster_options.flags |=3D CLUOPT_VERBOSE; =20 /* 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 =3D (ReindexStmt *) parsetree; - int options; + ReindexOptions *options; =20 options =3D ReindexParseOptions(pstate, stmt); - if ((options & REINDEXOPT_CONCURRENTLY) !=3D 0) + if ((options->flags & REINDEXOPT_CONCURRENTLY) !=3D 0) PreventInTransactionBlock(isTopLevel, "REINDEX CONCURRENTLY"); =20 diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs= =2Elist 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 --smhK4bMUIDbZnim9-- --AH8BNNWAzIqByhE1 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEG72nH6vTowiyblFKnvQgOdbyQH0FAl/hwxUACgkQnvQgOdby QH3sQw//YgiZYpbD+Mc3/KUnC7eCNTqDFgKMgFUk7CVqv/JstB4PX/WD9P9r3fg/ pkLce7JQ6WDpXa85ETC9+hpKlvDFbRXIp16dbeJ9sYEcJQh3k+jPTYyoVVEiLbvH xufL1ltqSBT0sjOX4YK+0s6cpFdVbwqU0/1uFOo1WeClg5EoEFaWYnL0Uw4ZH2Lx cndrpod4rLevA66FPTmUGpR1z758iTgKdcGHlP3HrGwOHyFRktJAcTD5PH2l4daW fCHsFVWosWBnP3Gc+lkIr7GrDh4qbb5+eWcRLw/TSIsQ23xwBUiYZkvvJdhc8PEl 0hoRX9tqb6LK5Ifr3QTJkny+3XWR/MejE3q+9ufEn6J22iHwlXIwhM1LPd82MCZb 7toMRcFCG87gaXeA0H371E0ZO0ZornxloL23ACbGBQGK5wieiC/9fkYqe2Q84qPS cRgVivx6C8eHTVkj9030mHn5ZqXVnAehUVcXlaZSas349rulLmTR7VMs5aCKRXfj BKDmGIOTJ7aIgkAKf8tUe2pU+WTEpJ214I50/NthigcpeybinoCnCCqli94Ubdrc Dxmhy6kqkAx4A/sQtUnT4ifqlUhC/0lmNTrHWOZa/0LlBsrqU48C2JK8tIEuPW43 Jx45/VgOLK7lHltijS6bJTCarbvBdk3++EGbdoHPpt6djzCmkCw= =UzPC -----END PGP SIGNATURE----- --AH8BNNWAzIqByhE1--