diff --git a/src/backend/distributed/commands/common.c b/src/backend/distributed/commands/common.c index a1c92c8d7..badf482ff 100644 --- a/src/backend/distributed/commands/common.c +++ b/src/backend/distributed/commands/common.c @@ -31,6 +31,13 @@ #include "distributed/worker_transaction.h" +static List * PreprocessAlterDistributedObjectStmtInternal(Node *stmt, + const char *queryString, + ProcessUtilityContext + processUtilityContext, + bool allowFromWorkers); + + /* * PostprocessCreateDistributedObjectFromCatalogStmt is a common function that can be used * for most objects during their creation phase. After the creation has happened locally @@ -104,9 +111,39 @@ PostprocessCreateDistributedObjectFromCatalogStmt(Node *stmt, const char *queryS /* - * PreprocessAlterDistributedObjectStmtFromCoordinator handles any updates to distributed - * objects by creating the fully qualified sql to apply to all workers after checking all - * predconditions that apply to propagating changes. + * PreprocessAlterDistributedObjectStmtFromCoordinator is a wrapper around + * PreprocessAlterDistributedObjectStmtInternal to be used when altering distributed + * objects that we allow altering only from the coordinator. + */ +List * +PreprocessAlterDistributedObjectStmtFromCoordinator(Node *stmt, const char *queryString, + ProcessUtilityContext + processUtilityContext) +{ + return PreprocessAlterDistributedObjectStmtInternal(stmt, queryString, + processUtilityContext, false); +} + + +/* + * PreprocessAlterDistributedObjectStmtFromCoordinator is a wrapper around + * PreprocessAlterDistributedObjectStmtInternal to be used when altering distributed + * objects that we allow altering only from the coordinator. + */ +List * +PreprocessAlterDistributedObjectStmtAnyNodes(Node *stmt, const char *queryString, + ProcessUtilityContext + processUtilityContext) +{ + return PreprocessAlterDistributedObjectStmtInternal(stmt, queryString, + processUtilityContext, true); +} + + +/* + * PreprocessAlterDistributedObjectStmtInternal handles any updates to distributed + * objects by creating the fully qualified sql to apply to all other nodes after checking + * all predconditions that apply to propagating changes. * * Preconditions are (in order): * - not in a CREATE/ALTER EXTENSION code block @@ -114,18 +151,18 @@ PostprocessCreateDistributedObjectFromCatalogStmt(Node *stmt, const char *queryS * - object being altered is distributed * - any object specific feature flag is turned on when a feature flag is available * - * Once we conclude to propagate the changes to the workers we make sure that the command - * has been executed on the coordinator and force any ongoing transaction to run in + * Once we conclude to propagate the changes to other nodes we make sure that the command + * has been executed on the local node and force any ongoing transaction to run in * sequential mode. If any of these steps fail we raise an error to inform the user. * * Lastly we recreate a fully qualified version of the original sql and prepare the tasks - * to send these sql commands to the workers. These tasks include instructions to prevent + * to send these sql commands to other nodes. These tasks include instructions to prevent * recursion of propagation with Citus' MX functionality. */ -List * -PreprocessAlterDistributedObjectStmtFromCoordinator(Node *stmt, const char *queryString, - ProcessUtilityContext - processUtilityContext) +static List * +PreprocessAlterDistributedObjectStmtInternal(Node *stmt, const char *queryString, + ProcessUtilityContext processUtilityContext, + bool allowFromWorkers) { const DistributeObjectOps *ops = GetDistributeObjectOps(stmt); Assert(ops != NULL); @@ -146,7 +183,15 @@ PreprocessAlterDistributedObjectStmtFromCoordinator(Node *stmt, const char *quer return NIL; } - EnsureCoordinator(); + if (allowFromWorkers) + { + EnsurePropagationToCoordinator(); + } + else + { + EnsureCoordinator(); + } + EnsureSequentialMode(ops->objectType); QualifyTreeNode(stmt); @@ -156,7 +201,7 @@ PreprocessAlterDistributedObjectStmtFromCoordinator(Node *stmt, const char *quer (void *) sql, ENABLE_DDL_PROPAGATION); - return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); + return NodeDDLTaskList(REMOTE_NODES, commands); } diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 2719f4d1e..ca26d3cb8 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -1190,7 +1190,7 @@ static DistributeObjectOps Routine_Rename = { static DistributeObjectOps Schema_AlterOwner = { .deparse = DeparseAlterSchemaOwnerStmt, .qualify = NULL, - .preprocess = PreprocessAlterDistributedObjectStmtFromCoordinator, + .preprocess = PreprocessAlterDistributedObjectStmtAnyNodes, .operationType = DIST_OPS_ALTER, .postprocess = NULL, .address = AlterSchemaOwnerStmtObjectAddress, @@ -1217,7 +1217,7 @@ static DistributeObjectOps Schema_Grant = { static DistributeObjectOps Schema_Rename = { .deparse = DeparseAlterSchemaRenameStmt, .qualify = NULL, - .preprocess = PreprocessAlterDistributedObjectStmtFromCoordinator, + .preprocess = PreprocessAlterDistributedObjectStmtAnyNodes, .postprocess = NULL, .objectType = OBJECT_SCHEMA, .operationType = DIST_OPS_ALTER, diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 1d06a28c1..a9589f0e5 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -191,6 +191,10 @@ extern List * PreprocessAlterDistributedObjectStmtFromCoordinator(Node *stmt, const char *queryString, ProcessUtilityContext processUtilityContext); +extern List * PreprocessAlterDistributedObjectStmtAnyNodes(Node *stmt, + const char *queryString, + ProcessUtilityContext + processUtilityContext); extern List * PostprocessAlterDistributedObjectStmtFromCoordinator(Node *stmt, const char *queryString); extern List * PreprocessDropDistributedObjectStmt(Node *node, const char *queryString, diff --git a/src/test/regress/expected/multi_mx_schema_support.out b/src/test/regress/expected/multi_mx_schema_support.out index 4e61d85d8..f3649d7b3 100644 --- a/src/test/regress/expected/multi_mx_schema_support.out +++ b/src/test/regress/expected/multi_mx_schema_support.out @@ -487,9 +487,16 @@ SELECT table_schema AS "Shards' Schema" (1 row) -- Show that altering distributed schema is not allowed on worker nodes +-- when the coordinator is not in the metadata. +SELECT COUNT(*)=0 FROM pg_dist_node WHERE groupid = 0; -- verify that the coordinator is not in the metadata + ?column? +--------------------------------------------------------------------- + t +(1 row) + ALTER SCHEMA mx_old_schema RENAME TO temp_mx_old_schema; -ERROR: operation is not allowed on this node -HINT: Connect to the coordinator and run it again. +ERROR: coordinator is not added to the metadata +HINT: Use SELECT citus_set_coordinator_host('') on coordinator to configure the coordinator hostname \c - - - :master_port ALTER TABLE mx_old_schema.table_set_schema SET SCHEMA mx_new_schema; SELECT objid::oid::regnamespace::text as "Distributed Schemas" diff --git a/src/test/regress/sql/multi_mx_schema_support.sql b/src/test/regress/sql/multi_mx_schema_support.sql index 7f1e5d0de..096687b18 100644 --- a/src/test/regress/sql/multi_mx_schema_support.sql +++ b/src/test/regress/sql/multi_mx_schema_support.sql @@ -321,6 +321,8 @@ SELECT table_schema AS "Shards' Schema" GROUP BY table_schema; -- Show that altering distributed schema is not allowed on worker nodes +-- when the coordinator is not in the metadata. +SELECT COUNT(*)=0 FROM pg_dist_node WHERE groupid = 0; -- verify that the coordinator is not in the metadata ALTER SCHEMA mx_old_schema RENAME TO temp_mx_old_schema; \c - - - :master_port