citus/src/backend/distributed/commands/rename.c

157 lines
4.7 KiB
C

/*-------------------------------------------------------------------------
*
* rename.c
* Commands for renaming objects related to distributed tables
*
* Copyright (c) Citus Data, Inc.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "distributed/commands.h"
#include "distributed/commands/utility_hook.h"
#include "distributed/metadata_cache.h"
#include "nodes/parsenodes.h"
/* DistributeObjectOps */
static List * PreprocessRenameStmt(Node *node, const char *renameCommand);
static DistributeObjectOps Any_Rename = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessRenameStmt,
.postprocess = NULL,
.address = NULL,
};
REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_TABLE, Any_Rename);
REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_FOREIGN_TABLE,
Any_Rename);
REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_COLUMN, Any_Rename);
REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_TABCONSTRAINT,
Any_Rename);
REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_INDEX, Any_Rename);
/*
* PreprocessRenameStmt first determines whether a given rename statement involves
* a distributed table. If so (and if it is supported, i.e. renames a column),
* it creates a DDLJob to encapsulate information needed during the worker node
* portion of DDL execution before returning that DDLJob in a List. If no dis-
* tributed table is involved, this function returns NIL.
*/
static List *
PreprocessRenameStmt(Node *node, const char *renameCommand)
{
RenameStmt *renameStmt = castNode(RenameStmt, node);
Oid objectRelationId = InvalidOid; /* SQL Object OID */
Oid tableRelationId = InvalidOid; /* Relation OID, maybe not the same. */
/*
* 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) &&
!IsPolicyRenameStmt(renameStmt))
{
return NIL;
}
/*
* The lock levels here should be same as the ones taken in
* RenameRelation(), renameatt() and RenameConstraint(). However, since all
* three statements have identical lock levels, we just use a single statement.
*/
objectRelationId = RangeVarGetRelid(renameStmt->relation,
AccessExclusiveLock,
renameStmt->missing_ok);
/*
* If the table does not exist, don't do anything here to allow PostgreSQL
* to throw the appropriate error or notice message later.
*/
if (!OidIsValid(objectRelationId))
{
return NIL;
}
/* we have no planning to do unless the table is distributed */
switch (renameStmt->renameType)
{
case OBJECT_TABLE:
case OBJECT_FOREIGN_TABLE:
case OBJECT_COLUMN:
case OBJECT_TABCONSTRAINT:
case OBJECT_POLICY:
{
/* 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;
}
bool isDistributedRelation = IsDistributedTable(tableRelationId);
if (!isDistributedRelation)
{
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);
DDLJob *ddlJob = palloc0(sizeof(DDLJob));
ddlJob->targetRelationId = tableRelationId;
ddlJob->concurrentIndexCmd = false;
ddlJob->commandString = renameCommand;
ddlJob->taskList = DDLTaskList(tableRelationId, renameCommand);
return list_make1(ddlJob);
}
/*
* ErrorIfDistributedRenameStmt errors out if the corresponding rename statement
* operates on any part of a distributed table other than a column.
*
* 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.
*/
void
ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt)
{
if (IsAlterTableRenameStmt(renameStmt) &&
renameStmt->renameType == OBJECT_TABCONSTRAINT)
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("renaming constraints belonging to distributed tables is "
"currently unsupported")));
}
}