diff --git a/src/backend/distributed/commands/database.c b/src/backend/distributed/commands/database.c index c9279b661..fb684a687 100644 --- a/src/backend/distributed/commands/database.c +++ b/src/backend/distributed/commands/database.c @@ -293,14 +293,9 @@ PreprocessAlterDatabaseStmt(Node *node, const char *queryString, return NIL; } - /* Since ALTER DATABASE SET TABLESPACE statement is not supported */ - /* inside a transaction block, we need to send the command to the */ - /* main database directly to make it work */ - if (!IsSetTablespaceStatement(stmt)) - { - EnsureCoordinator(); - } + EnsurePropagationToCoordinator(); + EnsureAllObjectDependenciesExistOnAllNodes(list_make1(dbAddress)); SerializeDistributedDDLsOnObjectClassObject(OCLASS_DATABASE, stmt->dbname); char *sql = DeparseTreeNode((Node *) stmt); @@ -317,12 +312,12 @@ PreprocessAlterDatabaseStmt(Node *node, const char *queryString, * the transaction block. */ bool warnForPartialFailure = true; - return NontransactionalNodeDDLTaskList(NON_COORDINATOR_NODES, commands, + return NontransactionalNodeDDLTaskList(REMOTE_NODES, commands, warnForPartialFailure); } else { - return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); + return NodeDDLTaskList(REMOTE_NODES, commands); } } @@ -353,7 +348,9 @@ PreprocessAlterDatabaseRefreshCollStmt(Node *node, const char *queryString, return NIL; } - EnsureCoordinator(); + EnsurePropagationToCoordinator(); + EnsureAllObjectDependenciesExistOnAllNodes(list_make1(dbAddress)); + SerializeDistributedDDLsOnObjectClassObject(OCLASS_DATABASE, stmt->dbname); char *sql = DeparseTreeNode((Node *) stmt); @@ -362,7 +359,7 @@ PreprocessAlterDatabaseRefreshCollStmt(Node *node, const char *queryString, (void *) sql, ENABLE_DDL_PROPAGATION); - return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); + return NodeDDLTaskList(REMOTE_NODES, commands); } @@ -395,7 +392,8 @@ PreprocessAlterDatabaseRenameStmt(Node *node, const char *queryString, return NIL; } - EnsureCoordinator(); + EnsurePropagationToCoordinator(); + EnsureAllObjectDependenciesExistOnAllNodes(list_make1(dbAddress)); /* * Different than other ALTER DATABASE commands, we first acquire a lock @@ -429,7 +427,8 @@ PostprocessAlterDatabaseRenameStmt(Node *node, const char *queryString) return NIL; } - EnsureCoordinator(); + EnsurePropagationToCoordinator(); + EnsureAllObjectDependenciesExistOnAllNodes(list_make1(dbAddress)); char *sql = DeparseTreeNode((Node *) stmt); @@ -437,7 +436,7 @@ PostprocessAlterDatabaseRenameStmt(Node *node, const char *queryString) (void *) sql, ENABLE_DDL_PROPAGATION); - return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); + return NodeDDLTaskList(REMOTE_NODES, commands); } @@ -465,7 +464,8 @@ PreprocessAlterDatabaseSetStmt(Node *node, const char *queryString, return NIL; } - EnsureCoordinator(); + EnsurePropagationToCoordinator(); + EnsureAllObjectDependenciesExistOnAllNodes(list_make1(dbAddress)); SerializeDistributedDDLsOnObjectClassObject(OCLASS_DATABASE, stmt->dbname); char *sql = DeparseTreeNode((Node *) stmt); @@ -474,7 +474,7 @@ PreprocessAlterDatabaseSetStmt(Node *node, const char *queryString, (void *) sql, ENABLE_DDL_PROPAGATION); - return NodeDDLTaskList(NON_COORDINATOR_NODES, commands); + return NodeDDLTaskList(REMOTE_NODES, commands); } @@ -694,6 +694,31 @@ PreprocessDropDatabaseStmt(Node *node, const char *queryString, return dropDatabaseDDLJobList; } +List * +PreprocessAlterDatabaseOwnerStmt(Node *node, const char *queryString, + ProcessUtilityContext processUtilityContext){ + List *addresses = GetObjectAddressListFromParseTree(node, false, false); + + if (!ShouldPropagateAnyObject(addresses)) + { + return NIL; + } + EnsurePropagationToCoordinator(); + + AlterOwnerStmt *stmt = (AlterOwnerStmt *) node; + EnsureSequentialMode(stmt->objectType); + QualifyTreeNode(node); + char *databaseName = strVal((String *) stmt->object); + SerializeDistributedDDLsOnObjectClassObject(OCLASS_DATABASE, databaseName); + const char *sql = DeparseTreeNode((Node *) node); + + List *commands = list_make3(DISABLE_DDL_PROPAGATION, + (void *) sql, + ENABLE_DDL_PROPAGATION); + + return NodeDDLTaskList(REMOTE_NODES, commands); +} + /* * DropDatabaseStmtObjectAddress gets the ObjectAddress of the database that is the diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 5a62dd2c8..c40738cc2 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -468,7 +468,7 @@ static DistributeObjectOps Collation_Rename = { static DistributeObjectOps Database_AlterOwner = { .deparse = DeparseAlterDatabaseOwnerStmt, .qualify = NULL, - .preprocess = PreprocessAlterDistributedObjectStmt, + .preprocess = PreprocessAlterDatabaseOwnerStmt, .postprocess = PostprocessAlterDistributedObjectStmt, .objectType = OBJECT_DATABASE, .operationType = DIST_OPS_ALTER, diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 8ce5c72ac..62dc23684 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -234,6 +234,9 @@ extern List * PreprocessAlterDatabaseStmt(Node *node, const char *queryString, extern List * PreprocessAlterDatabaseRefreshCollStmt(Node *node, const char *queryString, ProcessUtilityContext processUtilityContext); +extern List * PreprocessAlterDatabaseOwnerStmt(Node *node, const char *queryString, + ProcessUtilityContext processUtilityContext); + extern List * GetDatabaseMetadataSyncCommands(Oid dbOid); diff --git a/src/test/regress/sql/alter_database_from_nonmain_db.sql b/src/test/regress/sql/alter_database_from_nonmain_db.sql index b8a99a495..7e075c07a 100644 --- a/src/test/regress/sql/alter_database_from_nonmain_db.sql +++ b/src/test/regress/sql/alter_database_from_nonmain_db.sql @@ -34,6 +34,16 @@ set citus.log_remote_commands = true; set citus.grep_remote_commands = "%ALTER DATABASE%"; alter database altered_database_renamed rename to "altered_database!'2"; + +alter database "altered_database!'2" with + ALLOW_CONNECTIONS true + CONNECTION LIMIT 0 + IS_TEMPLATE false; + +\c regression - - :worker_2_port +set citus.log_remote_commands = true; +set citus.grep_remote_commands = "%ALTER DATABASE%"; + alter database "altered_database!'2" with ALLOW_CONNECTIONS false CONNECTION LIMIT 1 @@ -43,6 +53,14 @@ alter database "altered_database!'2" with CONNECTION LIMIT 0 IS_TEMPLATE false; +alter database "altered_database!'2" rename to altered_database_renamed; + +alter database altered_database_renamed rename to "altered_database!'2"; + + + + + \c regression create role test_owner_non_main_db; @@ -56,9 +74,23 @@ alter database "altered_database!'2" owner to test_owner_non_main_db; set citus.log_remote_commands = true; set citus.grep_remote_commands = "%ALTER DATABASE%"; alter database "altered_database!'2" owner to CURRENT_USER; -alter database "altered_database!'2" set default_transaction_read_only = true; set default_transaction_read_only = false; +\c regression - - :worker_1_port +set citus.log_remote_commands = true; +set citus.grep_remote_commands = "%ALTER DATABASE%"; +alter database "altered_database!'2" owner to test_owner_non_main_db; +set default_transaction_read_only = false; + + +\c regression - - :master_port +set citus.log_remote_commands = true; +set citus.grep_remote_commands = "%ALTER DATABASE%"; +alter database "altered_database!'2" owner to CURRENT_USER; +set default_transaction_read_only = false; + + + \c test_alter_db_from_nonmain_db - - :worker_2_port set citus.log_remote_commands = true; set citus.grep_remote_commands = "%ALTER DATABASE%"; @@ -76,6 +108,9 @@ alter database "altered_database!'2" RESET TIME ZONE; alter database "altered_database!'2" SET TIME ZONE INTERVAL '-08:00' HOUR TO MINUTE; alter database "altered_database!'2" RESET TIME ZONE; alter database "altered_database!'2" set default_transaction_isolation = 'serializable'; +\c regression - - :worker_2_port +set citus.log_remote_commands = true; +set citus.grep_remote_commands = "%ALTER DATABASE%"; set default_transaction_isolation = 'read committed'; alter database "altered_database!'2" set default_transaction_isolation from current; alter database "altered_database!'2" set default_transaction_isolation to DEFAULT;