agora inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedFrom: Julien Rouhaud <julien.rouhaud@free.fr>
Subject: [PATCH v1] Add a new COLLATION option to REINDEX.
Date: Thu, 3 Dec 2020 15:54:42 +0800
---
doc/src/sgml/ref/reindex.sgml | 13 +++++
src/backend/catalog/index.c | 59 +++++++++++++++++++++-
src/backend/commands/indexcmds.c | 12 +++--
src/backend/utils/cache/relcache.c | 43 ++++++++++++++++
src/include/catalog/index.h | 6 ++-
src/include/utils/relcache.h | 1 +
src/test/regress/expected/create_index.out | 10 ++++
src/test/regress/sql/create_index.sql | 10 ++++
8 files changed, 149 insertions(+), 5 deletions(-)
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 6e1cf06713..eb8da9c070 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -25,6 +25,7 @@ REINDEX [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] { IN
<phrase>where <replaceable class="parameter">option</replaceable> can be one of:</phrase>
+ COLLATION [ <replaceable class="parameter">text</replaceable> ]
CONCURRENTLY [ <replaceable class="parameter">boolean</replaceable> ]
VERBOSE [ <replaceable class="parameter">boolean</replaceable> ]
</synopsis>
@@ -168,6 +169,18 @@ REINDEX [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] { IN
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>COLLATION</literal></term>
+ <listitem>
+ <para>
+ This option can be used to filter the list of indexes to rebuild. The
+ only allowed value is <literal>'not_current'</literal>, which will only
+ process indexes that depend on a collation version different than the
+ current one.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>CONCURRENTLY</literal></term>
<listitem>
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 731610c701..7d941f40af 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -99,6 +99,12 @@ typedef struct
Oid pendingReindexedIndexes[FLEXIBLE_ARRAY_MEMBER];
} SerializedReindexState;
+typedef struct
+{
+ Oid relid; /* targetr index oid */
+ bool deprecated; /* depends on at least on deprected collation? */
+} IndexHasDeprecatedColl;
+
/* non-export function prototypes */
static bool relationHasPrimaryKey(Relation rel);
static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
@@ -1349,6 +1355,57 @@ index_check_collation_versions(Oid relid)
list_free(context.warned_colls);
}
+/*
+ * Detect if an index depends on at least one deprecated collation.
+ * This is a callback for visitDependenciesOf().
+ */
+static bool
+do_check_index_has_deprecated_collation(const ObjectAddress *otherObject,
+ const char *version,
+ char **new_version,
+ void *data)
+{
+ IndexHasDeprecatedColl *context = data;
+ char *current_version;
+
+ /* We only care about dependencies on collations. */
+ if (otherObject->classId != CollationRelationId)
+ return false;
+
+ /* Fast exit if we already found a deprecated collation version. */
+ if (context->deprecated)
+ return false;
+
+ /* Ask the provider for the current version. Give up if unsupported. */
+ current_version = get_collation_version_for_oid(otherObject->objectId);
+ if (!current_version)
+ return false;
+
+ if (!version || strcmp(version, current_version) != 0)
+ context->deprecated = true;
+
+ return false;
+}
+
+bool
+index_has_deprecated_collation(Oid relid)
+{
+ ObjectAddress object;
+ IndexHasDeprecatedColl context;
+
+ object.classId = RelationRelationId;
+ object.objectId = relid;
+ object.objectSubId = 0;
+
+ context.relid = relid;
+ context.deprecated = false;
+
+ visitDependenciesOf(&object, &do_check_index_has_deprecated_collation,
+ &context);
+
+ return context.deprecated;
+}
+
/*
* Update the version for collations. A callback for visitDependenciesOf().
*/
@@ -3886,7 +3943,7 @@ reindex_relation(Oid relid, int flags, int options)
* relcache to get this with a sequential scan if ignoring system
* indexes.)
*/
- indexIds = RelationGetIndexList(rel);
+ indexIds = RelationGetIndexListFiltered(rel, options);
if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
{
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 14d24b3cc4..2477ad6c74 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -2462,6 +2462,7 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt)
int options = 0;
bool concurrently = false;
bool verbose = false;
+ bool coll_filter = false;
/* Parse option list */
foreach(lc, stmt->params)
@@ -2472,6 +2473,9 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt)
verbose = defGetBoolean(opt);
else if (strcmp(opt->defname, "concurrently") == 0)
concurrently = defGetBoolean(opt);
+ else if ((strcmp(opt->defname, "collation") == 0)
+ && (strcmp(defGetString(opt), "not_current") == 0))
+ coll_filter = true;
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -2482,7 +2486,8 @@ ReindexParseOptions(ParseState *pstate, ReindexStmt *stmt)
options =
(verbose ? REINDEXOPT_VERBOSE : 0) |
- (concurrently ? REINDEXOPT_CONCURRENTLY : 0);
+ (concurrently ? REINDEXOPT_CONCURRENTLY : 0) |
+ (coll_filter ? REINDEXOPT_COLL_NOT_CURRENT : 0);
return options;
}
@@ -3150,7 +3155,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
ShareUpdateExclusiveLock);
/* Add all the valid indexes of relation to list */
- foreach(lc, RelationGetIndexList(heapRelation))
+ foreach(lc, RelationGetIndexListFiltered(heapRelation, options))
{
Oid cellOid = lfirst_oid(lc);
Relation indexRelation = index_open(cellOid,
@@ -3196,7 +3201,8 @@ ReindexRelationConcurrently(Oid relationOid, int options)
MemoryContextSwitchTo(oldcontext);
- foreach(lc2, RelationGetIndexList(toastRelation))
+ foreach(lc2, RelationGetIndexListFiltered(toastRelation,
+ options))
{
Oid cellOid = lfirst_oid(lc2);
Relation indexRelation = index_open(cellOid,
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 66393becfb..9045dce2d7 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4609,6 +4609,49 @@ RelationGetIndexList(Relation relation)
return result;
}
+/*
+ * RelationGetIndexListFiltered -- get a filtered list of indexes on this
+ * relation.
+ *
+ * Calls RelationGetIndexList and filters out the result as required by the
+ * caller. The filters are cumulative, although for now the only supported
+ * filter is for indexes that don't depend on deprecated collation version.
+ */
+List *
+RelationGetIndexListFiltered(Relation relation, int options)
+{
+ List *result,
+ *full_list;
+ ListCell *lc;
+
+ full_list = RelationGetIndexList(relation);
+
+ /* Fast exit if no filtering was asked, or if the list if empty. */
+ if (!reindexHasFilter(options) || full_list == NIL)
+ return full_list;
+
+ result = NIL;
+ foreach(lc, full_list)
+ {
+ Oid indexOid = lfirst_oid(lc);
+
+ /*
+ * The caller wants to discard indexes that don't depend on a
+ * deprecated collation version.
+ */
+ if ((options & REINDEXOPT_COLL_NOT_CURRENT) != 0)
+ {
+ if (!index_has_deprecated_collation(indexOid))
+ continue;
+ }
+
+ /* Index passed all filters, keep it */
+ result = lappend_oid(result, indexOid);
+ }
+
+ return result;
+}
+
/*
* RelationGetStatExtList
* get a list of OIDs of statistics objects on this relation
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index c041628049..9f2bb60343 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -35,9 +35,12 @@ typedef enum ReindexOption
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 */
+ REINDEXOPT_CONCURRENTLY = 1 << 3, /* concurrent mode */
+ REINDEXOPT_COLL_NOT_CURRENT = 1 << 4
} ReindexOption;
+#define reindexHasFilter(x) ((x & REINDEXOPT_COLL_NOT_CURRENT) != 0)
+
/* state info for validate_index bulkdelete callback */
typedef struct ValidateIndexState
{
@@ -131,6 +134,7 @@ extern void FormIndexDatum(IndexInfo *indexInfo,
bool *isnull);
extern void index_check_collation_versions(Oid relid);
+extern bool index_has_deprecated_collation(Oid relid);
extern void index_update_collation_versions(Oid relid, Oid coll);
extern void index_build(Relation heapRelation,
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 9a85b7dd57..4ef02c9851 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -45,6 +45,7 @@ extern void RelationClose(Relation relation);
*/
extern List *RelationGetFKeyList(Relation relation);
extern List *RelationGetIndexList(Relation relation);
+extern List *RelationGetIndexListFiltered(Relation relation, int options);
extern List *RelationGetStatExtList(Relation relation);
extern Oid RelationGetPrimaryKeyIndex(Relation relation);
extern Oid RelationGetReplicaIndex(Relation relation);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index fc6afab58a..39a5b91d1a 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2018,6 +2018,16 @@ INFO: index "reindex_verbose_pkey" was reindexed
\set VERBOSITY default
DROP TABLE reindex_verbose;
--
+-- REINDEX (COLLATION 'not_current')
+--
+CREATE TABLE reindex_coll(id integer primary key);
+\set VERBOSITY terse \\ -- suppress machine-dependent details
+-- no suitable index should be found
+REINDEX (COLLATION 'not_current') TABLE reindex_coll;
+NOTICE: table "reindex_coll" has no indexes to reindex
+\set VERBOSITY default
+DROP TABLE reindex_coll;
+--
-- REINDEX CONCURRENTLY
--
CREATE TABLE concur_reindex_tab (c1 int);
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 824cb9f9e8..99f45c0d02 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -790,6 +790,16 @@ REINDEX (VERBOSE) TABLE reindex_verbose;
\set VERBOSITY default
DROP TABLE reindex_verbose;
+--
+-- REINDEX (COLLATION 'not_current')
+--
+CREATE TABLE reindex_coll(id integer primary key);
+\set VERBOSITY terse \\ -- suppress machine-dependent details
+-- no suitable index should be found
+REINDEX (COLLATION 'not_current') TABLE reindex_coll;
+\set VERBOSITY default
+DROP TABLE reindex_coll;
+
--
-- REINDEX CONCURRENTLY
--
--
2.20.1
--UugvWAfsgieZRqgk--
view thread (24+ messages) latest in thread
Message-ID: <no-message-id-1863097@localhost>
Permalink: ../../no-message-id-1863097@localhost/
Also on: postgresql.org/message-id/no-message-id-1863097@localhost
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: julien.rouhaud@free.fr
Subject: Re: [PATCH v1] Add a new COLLATION option to REINDEX.
In-Reply-To: <no-message-id-1863097@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox