mirror of https://github.com/citusdata/citus.git
115 lines
2.9 KiB
C
115 lines
2.9 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* cluster.c
|
|
* Commands for CLUSTER statement
|
|
*
|
|
* Copyright (c) Citus Data, Inc.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "distributed/pg_version_constants.h"
|
|
|
|
#include "commands/defrem.h"
|
|
|
|
#include "catalog/namespace.h"
|
|
#include "distributed/commands.h"
|
|
#include "distributed/commands/utility_hook.h"
|
|
#include "distributed/listutils.h"
|
|
#include "distributed/metadata_cache.h"
|
|
|
|
|
|
static bool IsClusterStmtVerbose_compat(ClusterStmt *clusterStmt);
|
|
|
|
/*
|
|
* PreprocessClusterStmt first determines whether a given cluster statement involves
|
|
* a distributed table. If so (and if it is supported, i.e. no verbose), 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
|
|
* distributed table is involved, this function returns NIL.
|
|
*/
|
|
List *
|
|
PreprocessClusterStmt(Node *node, const char *clusterCommand,
|
|
ProcessUtilityContext processUtilityContext)
|
|
{
|
|
ClusterStmt *clusterStmt = castNode(ClusterStmt, node);
|
|
bool missingOK = false;
|
|
DDLJob *ddlJob = NULL;
|
|
|
|
if (clusterStmt->relation == NULL)
|
|
{
|
|
ereport(WARNING, (errmsg("not propagating CLUSTER command to worker nodes"),
|
|
errhint("Provide a specific table in order to CLUSTER "
|
|
"distributed tables.")));
|
|
|
|
return NIL;
|
|
}
|
|
|
|
/* PostgreSQL uses access exclusive lock for CLUSTER command */
|
|
Oid relationId = RangeVarGetRelid(clusterStmt->relation, AccessExclusiveLock,
|
|
missingOK);
|
|
|
|
/*
|
|
* 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(relationId))
|
|
{
|
|
return NIL;
|
|
}
|
|
|
|
/* we have no planning to do unless the table is distributed */
|
|
bool isCitusRelation = IsCitusTable(relationId);
|
|
if (!isCitusRelation)
|
|
{
|
|
return NIL;
|
|
}
|
|
|
|
#if PG_VERSION_NUM >= 120000
|
|
if (IsClusterStmtVerbose_compat(clusterStmt))
|
|
#else
|
|
if (clusterStmt->verbose)
|
|
#endif
|
|
{
|
|
ereport(ERROR, (errmsg("cannot run CLUSTER command"),
|
|
errdetail("VERBOSE option is currently unsupported "
|
|
"for distributed tables.")));
|
|
}
|
|
|
|
ddlJob = palloc0(sizeof(DDLJob));
|
|
ObjectAddressSet(ddlJob->targetObjectAddress, RelationRelationId, relationId);
|
|
ddlJob->metadataSyncCommand = clusterCommand;
|
|
ddlJob->taskList = DDLTaskList(relationId, clusterCommand);
|
|
|
|
return list_make1(ddlJob);
|
|
}
|
|
|
|
|
|
/*
|
|
* IsClusterStmtVerbose_compat returns true if the given statement
|
|
* is a cluster statement with verbose option.
|
|
*/
|
|
static bool
|
|
IsClusterStmtVerbose_compat(ClusterStmt *clusterStmt)
|
|
{
|
|
#if PG_VERSION_NUM < PG_VERSION_14
|
|
if (clusterStmt->options & CLUOPT_VERBOSE)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
#else
|
|
DefElem *opt = NULL;
|
|
foreach_ptr(opt, clusterStmt->params)
|
|
{
|
|
if (strcmp(opt->defname, "verbose") == 0)
|
|
{
|
|
return defGetBoolean(opt);
|
|
}
|
|
}
|
|
return false;
|
|
#endif
|
|
}
|