| 1040 | } |
| 1041 | |
| 1042 | void InterpreterSystemQuery::dropReplica(ASTSystemQuery & query) |
| 1043 | { |
| 1044 | if (query.replica.empty()) |
| 1045 | throw Exception("Replica name is empty", ErrorCodes::BAD_ARGUMENTS); |
| 1046 | |
| 1047 | if (!table_id.empty()) |
| 1048 | { |
| 1049 | getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA, table_id); |
| 1050 | StoragePtr table = DatabaseCatalog::instance().getTable(table_id, getContext()); |
| 1051 | |
| 1052 | if (!dropReplicaImpl(query, table)) |
| 1053 | throw Exception(ErrorCodes::BAD_ARGUMENTS, table_is_not_replicated.data(), table_id.getNameForLogs()); |
| 1054 | } |
| 1055 | else if (!query.database.empty()) |
| 1056 | { |
| 1057 | getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA, query.database); |
| 1058 | DatabasePtr database = DatabaseCatalog::instance().getDatabase(query.database, getContext()); |
| 1059 | for (auto iterator = database->getTablesIterator(getContext()); iterator->isValid(); iterator->next()) |
| 1060 | dropReplicaImpl(query, iterator->table()); |
| 1061 | LOG_TRACE(log, "Dropped replica {} from database {}", query.replica, backQuoteIfNeed(database->getDatabaseName())); |
| 1062 | } |
| 1063 | else if (query.is_drop_whole_replica) |
| 1064 | { |
| 1065 | getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA); |
| 1066 | auto databases = DatabaseCatalog::instance().getDatabases(getContext()); |
| 1067 | |
| 1068 | for (auto & elem : databases) |
| 1069 | { |
| 1070 | DatabasePtr & database = elem.second; |
| 1071 | for (auto iterator = database->getTablesIterator(getContext()); iterator->isValid(); iterator->next()) |
| 1072 | dropReplicaImpl(query, iterator->table()); |
| 1073 | LOG_TRACE(log, "Dropped replica {} from database {}", query.replica, backQuoteIfNeed(database->getDatabaseName())); |
| 1074 | } |
| 1075 | } |
| 1076 | else if (!query.replica_zk_path.empty()) |
| 1077 | { |
| 1078 | getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA); |
| 1079 | String remote_replica_path = fs::path(query.replica_zk_path) / "replicas" / query.replica; |
| 1080 | |
| 1081 | /// This check is actually redundant, but it may prevent from some user mistakes |
| 1082 | for (auto & elem : DatabaseCatalog::instance().getDatabases(getContext())) |
| 1083 | { |
| 1084 | DatabasePtr & database = elem.second; |
| 1085 | for (auto iterator = database->getTablesIterator(getContext()); iterator->isValid(); iterator->next()) |
| 1086 | { |
| 1087 | if (auto * storage_replicated = dynamic_cast<StorageReplicatedMergeTree *>(iterator->table().get())) |
| 1088 | { |
| 1089 | StorageReplicatedMergeTree::Status status; |
| 1090 | storage_replicated->getStatus(status); |
| 1091 | if (status.zookeeper_path == query.replica_zk_path) |
| 1092 | throw Exception("There is a local table " + storage_replicated->getStorageID().getNameForLogs() + |
| 1093 | ", which has the same table path in ZooKeeper. Please check the path in query. " |
| 1094 | "If you want to drop replica of this table, use `DROP TABLE` " |
| 1095 | "or `SYSTEM DROP REPLICA 'name' FROM db.table`", ErrorCodes::TABLE_WAS_NOT_DROPPED); |
| 1096 | } |
| 1097 | } |
| 1098 | } |
| 1099 |
no test coverage detected