From f4b90419aedff522745b5643bd2f5cf589413036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Tue, 20 Aug 2019 16:58:50 +0000 Subject: [PATCH] Raise an error when REINDEX TABLE or INDEX is invoked on a distributed relation --- src/backend/distributed/commands/index.c | 63 +++++++++++++++++++ .../distributed/commands/utility_hook.c | 5 ++ src/include/distributed/commands.h | 1 + .../expected/multi_index_statements.out | 14 +++++ .../expected/multi_index_statements_0.out | 14 +++++ .../regress/sql/multi_index_statements.sql | 14 +++++ 6 files changed, 111 insertions(+) diff --git a/src/backend/distributed/commands/index.c b/src/backend/distributed/commands/index.c index df14fa374..428c930c5 100644 --- a/src/backend/distributed/commands/index.c +++ b/src/backend/distributed/commands/index.c @@ -168,6 +168,69 @@ PlanIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand) } +/* + * ErrorIfReindexOnDistributedTable determines whether a given REINDEX + * involves a distributed table, & raises an error if so. + */ +void +ErrorIfReindexOnDistributedTable(ReindexStmt *ReindexStatement) +{ + Relation relation = NULL; + Oid relationId = InvalidOid; + bool isDistributedRelation = false; + LOCKMODE lockmode = AccessShareLock; + + /* + * We first check whether a distributed relation is affected. For that, we need to + * open the relation. + */ + if (ReindexStatement->relation == NULL) + { + /* ignore REINDEX SCHEMA, REINDEX SYSTEM, and REINDEX DATABASE */ + return; + } + + Assert(ReindexStatement->relkind == REINDEX_OBJECT_INDEX || + ReindexStatement->relkind == REINDEX_OBJECT_TABLE); + + /* + * XXX: Consider using RangeVarGetRelidExtended with a permission + * checking callback. Right now we'll acquire the lock before having + * checked permissions. + */ + if (ReindexStatement->kind == REINDEX_OBJECT_INDEX) + { + Oid indOid = RangeVarGetRelid(ReindexStatement->relation, + NoLock, false); + relation = index_open(indOid, lockmode); + relationId = IndexGetRelation(indOid, false); + } + else + { + relation = heap_openrv(ReindexStatement->relation, lockmode); + relationId = RelationGetRelid(relation); + } + + isDistributedRelation = IsDistributedTable(relationId); + + if (ReindexStatement->kind == REINDEX_OBJECT_INDEX) + { + index_close(relation, NoLock); + } + else + { + heap_close(relation, NoLock); + } + + if (isDistributedRelation) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg( + "REINDEX is not implemented for distributed relations"))); + } +} + + /* * PlanDropIndexStmt determines whether a given DROP INDEX statement involves * a distributed table. If so (and if the statement does not use unsupported diff --git a/src/backend/distributed/commands/utility_hook.c b/src/backend/distributed/commands/utility_hook.c index 7d684aad1..a8443a2e0 100644 --- a/src/backend/distributed/commands/utility_hook.c +++ b/src/backend/distributed/commands/utility_hook.c @@ -279,6 +279,11 @@ multi_ProcessUtility(PlannedStmt *pstmt, ddlJobs = PlanIndexStmt((IndexStmt *) parsetree, queryString); } + if (IsA(parsetree, ReindexStmt)) + { + ErrorIfReindexOnDistributedTable((ReindexStmt *) parsetree); + } + if (IsA(parsetree, DropStmt)) { DropStmt *dropStatement = (DropStmt *) parsetree; diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 84ad27b23..9e5970be6 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -52,6 +52,7 @@ extern List * PlanGrantStmt(GrantStmt *grantStmt); extern bool IsIndexRenameStmt(RenameStmt *renameStmt); extern List * PlanIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand); +extern void ErrorIfReindexOnDistributedTable(ReindexStmt *ReindexStatement); extern List * PlanDropIndexStmt(DropStmt *dropIndexStatement, const char *dropIndexCommand); extern void PostProcessIndexStmt(IndexStmt *indexStmt); diff --git a/src/test/regress/expected/multi_index_statements.out b/src/test/regress/expected/multi_index_statements.out index 0a6ed4614..9a64dab13 100644 --- a/src/test/regress/expected/multi_index_statements.out +++ b/src/test/regress/expected/multi_index_statements.out @@ -204,6 +204,20 @@ SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_t public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) (16 rows) +-- +-- REINDEX +-- +SET citus.log_remote_commands to on; +SET client_min_messages = LOG; +REINDEX INDEX lineitem_orderkey_index; +ERROR: REINDEX is not implemented for distributed relations +REINDEX TABLE lineitem; +ERROR: REINDEX is not implemented for distributed relations +REINDEX SCHEMA public; +REINDEX DATABASE regression; +REINDEX SYSTEM regression; +SET citus.log_remote_commands to off; +RESET client_min_messages; -- -- DROP INDEX -- diff --git a/src/test/regress/expected/multi_index_statements_0.out b/src/test/regress/expected/multi_index_statements_0.out index daa6d71b4..ccd0d1e68 100644 --- a/src/test/regress/expected/multi_index_statements_0.out +++ b/src/test/regress/expected/multi_index_statements_0.out @@ -205,6 +205,20 @@ SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_t public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) (15 rows) +-- +-- REINDEX +-- +SET citus.log_remote_commands to on; +SET client_min_messages = LOG; +REINDEX INDEX lineitem_orderkey_index; +ERROR: REINDEX is not implemented for distributed relations +REINDEX TABLE lineitem; +ERROR: REINDEX is not implemented for distributed relations +REINDEX SCHEMA public; +REINDEX DATABASE regression; +REINDEX SYSTEM regression; +SET citus.log_remote_commands to off; +RESET client_min_messages; -- -- DROP INDEX -- diff --git a/src/test/regress/sql/multi_index_statements.sql b/src/test/regress/sql/multi_index_statements.sql index 148f7e860..d1ea0bf93 100644 --- a/src/test/regress/sql/multi_index_statements.sql +++ b/src/test/regress/sql/multi_index_statements.sql @@ -113,6 +113,20 @@ CREATE INDEX ON lineitem (l_orderkey); -- Verify that none of failed indexes got created on the master node SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname; +-- +-- REINDEX +-- + +SET citus.log_remote_commands to on; +SET client_min_messages = LOG; +REINDEX INDEX lineitem_orderkey_index; +REINDEX TABLE lineitem; +REINDEX SCHEMA public; +REINDEX DATABASE regression; +REINDEX SYSTEM regression; +SET citus.log_remote_commands to off; +RESET client_min_messages; + -- -- DROP INDEX --