Implement ALTER INDEX ... RENAME TO ...

The command is now distributed among the shards when the table is
distributed. To that effect, we fill in the DDLJob's targetRelationId with
the OID of the table for which the index is defined, rather than the OID of
the index itself.
pull/1948/head
Dimitri Fontaine 2018-01-11 18:05:51 +01:00
parent aee0be881b
commit 17266e3301
3 changed files with 126 additions and 12 deletions

View File

@ -155,6 +155,7 @@ static void ErrorIfUnsupportedForeignConstraint(Relation relation,
static char * ExtractNewExtensionVersion(Node *parsetree); static char * ExtractNewExtensionVersion(Node *parsetree);
static void CreateLocalTable(RangeVar *relation, char *nodeName, int32 nodePort); static void CreateLocalTable(RangeVar *relation, char *nodeName, int32 nodePort);
static bool IsAlterTableRenameStmt(RenameStmt *renameStmt); static bool IsAlterTableRenameStmt(RenameStmt *renameStmt);
static bool IsIndexRenameStmt(RenameStmt *renameStmt);
static bool AlterInvolvesPartitionColumn(AlterTableStmt *alterTableStatement, static bool AlterInvolvesPartitionColumn(AlterTableStmt *alterTableStatement,
AlterTableCmd *command); AlterTableCmd *command);
static void ExecuteDistributedDDLJob(DDLJob *ddlJob); static void ExecuteDistributedDDLJob(DDLJob *ddlJob);
@ -1371,11 +1372,17 @@ PlanAlterTableStmt(AlterTableStmt *alterTableStatement, const char *alterTableCo
static List * static List *
PlanRenameStmt(RenameStmt *renameStmt, const char *renameCommand) PlanRenameStmt(RenameStmt *renameStmt, const char *renameCommand)
{ {
Oid relationId = InvalidOid; Oid objectRelationId = InvalidOid; /* SQL Object OID */
Oid tableRelationId = InvalidOid; /* Relation OID, maybe not the same. */
bool isDistributedRelation = false; bool isDistributedRelation = false;
DDLJob *ddlJob = NULL; DDLJob *ddlJob = NULL;
if (!IsAlterTableRenameStmt(renameStmt)) /*
* We only support some of the PostgreSQL supported RENAME statements, and
* our list include only renaming table and index (related) objects.
*/
if (!IsAlterTableRenameStmt(renameStmt) &&
!IsIndexRenameStmt(renameStmt))
{ {
return NIL; return NIL;
} }
@ -1385,32 +1392,70 @@ PlanRenameStmt(RenameStmt *renameStmt, const char *renameCommand)
* RenameRelation(), renameatt() and RenameConstraint(). However, since all * RenameRelation(), renameatt() and RenameConstraint(). However, since all
* three statements have identical lock levels, we just use a single statement. * three statements have identical lock levels, we just use a single statement.
*/ */
relationId = RangeVarGetRelid(renameStmt->relation, AccessExclusiveLock, objectRelationId = RangeVarGetRelid(renameStmt->relation,
AccessExclusiveLock,
renameStmt->missing_ok); renameStmt->missing_ok);
/* /*
* If the table does not exist, don't do anything here to allow PostgreSQL * If the table does not exist, don't do anything here to allow PostgreSQL
* to throw the appropriate error or notice message later. * to throw the appropriate error or notice message later.
*/ */
if (!OidIsValid(relationId)) if (!OidIsValid(objectRelationId))
{ {
return NIL; return NIL;
} }
/* we have no planning to do unless the table is distributed */ /* we have no planning to do unless the table is distributed */
isDistributedRelation = IsDistributedTable(relationId); switch (renameStmt->renameType)
{
case OBJECT_TABLE:
case OBJECT_COLUMN:
case OBJECT_TABCONSTRAINT:
{
/* the target object is our tableRelationId. */
tableRelationId = objectRelationId;
break;
}
case OBJECT_INDEX:
{
/*
* here, objRelationId points to the index relation entry, and we
* are interested into the entry of the table on which the index is
* defined.
*/
tableRelationId = IndexGetRelation(objectRelationId, false);
break;
}
default:
/*
* Nodes that are not supported by Citus: we pass-through to the
* main PostgreSQL executor. Any Citus-supported RenameStmt
* renameType must appear above in the switch, explicitly.
*/
return NIL;
}
isDistributedRelation = IsDistributedTable(tableRelationId);
if (!isDistributedRelation) if (!isDistributedRelation)
{ {
return NIL; return NIL;
} }
/*
* We might ERROR out on some commands, but only for Citus tables where
* isDistributedRelation is true. That's why this test comes this late in
* the function.
*/
ErrorIfUnsupportedRenameStmt(renameStmt); ErrorIfUnsupportedRenameStmt(renameStmt);
ddlJob = palloc0(sizeof(DDLJob)); ddlJob = palloc0(sizeof(DDLJob));
ddlJob->targetRelationId = relationId; ddlJob->targetRelationId = tableRelationId;
ddlJob->concurrentIndexCmd = false; ddlJob->concurrentIndexCmd = false;
ddlJob->commandString = renameCommand; ddlJob->commandString = renameCommand;
ddlJob->taskList = DDLTaskList(relationId, renameCommand); ddlJob->taskList = DDLTaskList(tableRelationId, renameCommand);
return list_make1(ddlJob); return list_make1(ddlJob);
} }
@ -2733,14 +2778,14 @@ OptionsSpecifyOwnedBy(List *optionList, Oid *ownedByTableId)
* ErrorIfDistributedRenameStmt errors out if the corresponding rename statement * ErrorIfDistributedRenameStmt errors out if the corresponding rename statement
* operates on any part of a distributed table other than a column. * operates on any part of a distributed table other than a column.
* *
* Note: This function handles only those rename statements which operate on tables. * Note: This function handles RenameStmt applied to relations handed by Citus.
* At the moment of writing this comment, it could be either tables or indexes.
*/ */
static void static void
ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt) ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt)
{ {
Assert(IsAlterTableRenameStmt(renameStmt)); if (IsAlterTableRenameStmt(renameStmt) &&
renameStmt->renameType == OBJECT_TABCONSTRAINT)
if (renameStmt->renameType == OBJECT_TABCONSTRAINT)
{ {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("renaming constraints belonging to distributed tables is " errmsg("renaming constraints belonging to distributed tables is "
@ -2860,6 +2905,26 @@ IsAlterTableRenameStmt(RenameStmt *renameStmt)
} }
/*
* IsIndexRenameStmt returns whether the passed-in RenameStmt is the following
* form:
*
* - ALTER INDEX RENAME
*/
static bool
IsIndexRenameStmt(RenameStmt *renameStmt)
{
bool isIndexRenameStmt = false;
if (renameStmt->renameType == OBJECT_INDEX)
{
isIndexRenameStmt = true;
}
return isIndexRenameStmt;
}
/* /*
* AlterInvolvesPartitionColumn checks if the given alter table command * AlterInvolvesPartitionColumn checks if the given alter table command
* involves relation's partition column. * involves relation's partition column.

View File

@ -375,6 +375,21 @@ ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' ORDER BY relname; SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' ORDER BY relname;
\c - - - :master_port \c - - - :master_port
-- verify that we can rename indexes on distributed tables
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
ALTER INDEX temp_index_1 RENAME TO idx_lineitem_linenumber;
-- verify rename is performed
SELECT relname FROM pg_class WHERE relname = 'idx_lineitem_linenumber';
-- show rename worked on one worker, too
\c - - - :worker_1_port
SELECT relname FROM pg_class WHERE relname LIKE 'idx_lineitem_linenumber%%' ORDER BY relname;
\c - - - :master_port
-- now get rid of the index
DROP INDEX idx_lineitem_linenumber;
-- verify that we don't intercept DDL commands if propagation is turned off -- verify that we don't intercept DDL commands if propagation is turned off
SET citus.enable_ddl_propagation to false; SET citus.enable_ddl_propagation to false;

View File

@ -844,6 +844,40 @@ SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' ORDER BY relna
(15 rows) (15 rows)
\c - - - :master_port \c - - - :master_port
-- verify that we can rename indexes on distributed tables
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
ALTER INDEX temp_index_1 RENAME TO idx_lineitem_linenumber;
-- verify rename is performed
SELECT relname FROM pg_class WHERE relname = 'idx_lineitem_linenumber';
relname
-------------------------
idx_lineitem_linenumber
(1 row)
-- show rename worked on one worker, too
\c - - - :worker_1_port
SELECT relname FROM pg_class WHERE relname LIKE 'idx_lineitem_linenumber%%' ORDER BY relname;
relname
--------------------------------
idx_lineitem_linenumber_220000
idx_lineitem_linenumber_220001
idx_lineitem_linenumber_220002
idx_lineitem_linenumber_220003
idx_lineitem_linenumber_220004
idx_lineitem_linenumber_220005
idx_lineitem_linenumber_220006
idx_lineitem_linenumber_220007
idx_lineitem_linenumber_220008
idx_lineitem_linenumber_220010
idx_lineitem_linenumber_220011
idx_lineitem_linenumber_220012
idx_lineitem_linenumber_220013
idx_lineitem_linenumber_220014
(14 rows)
\c - - - :master_port
-- now get rid of the index
DROP INDEX idx_lineitem_linenumber;
-- verify that we don't intercept DDL commands if propagation is turned off -- verify that we don't intercept DDL commands if propagation is turned off
SET citus.enable_ddl_propagation to false; SET citus.enable_ddl_propagation to false;
-- table rename statement can be performed on the coordinator only now -- table rename statement can be performed on the coordinator only now