| 1892 | } |
| 1893 | |
| 1894 | void InterpreterSystemQuery::dropDatabaseReplica(ASTSystemQuery & query) |
| 1895 | { |
| 1896 | if (query.replica.empty()) |
| 1897 | throw Exception(ErrorCodes::BAD_ARGUMENTS, "Replica name is empty"); |
| 1898 | |
| 1899 | auto component_guard = Coordination::setCurrentComponent("InterpreterSystemQuery::dropDatabaseReplica"); |
| 1900 | const String full_replica_name |
| 1901 | = query.shard.empty() ? query.replica : DatabaseReplicated::getFullReplicaName(query.shard, query.replica); |
| 1902 | const fs::path & query_replica_zk_path = fs::path(query.replica_zk_path); |
| 1903 | auto check_not_local_replica |
| 1904 | = [](const DatabaseReplicated * replicated, const String & full_replica_name_, const fs::path & query_replica_zk_path_) |
| 1905 | { |
| 1906 | if (!query_replica_zk_path_.empty() && fs::path(replicated->getZooKeeperPath()) != query_replica_zk_path_) |
| 1907 | return; |
| 1908 | if (replicated->getFullReplicaName() != full_replica_name_) |
| 1909 | return; |
| 1910 | |
| 1911 | throw Exception(ErrorCodes::TABLE_WAS_NOT_DROPPED, "There is a local database {}, which has the same path in ZooKeeper " |
| 1912 | "and the same replica name. Please check the path in query. " |
| 1913 | "If you want to drop replica of this database, use `DROP DATABASE`", replicated->getDatabaseName()); |
| 1914 | }; |
| 1915 | |
| 1916 | if (query.database) |
| 1917 | { |
| 1918 | getContext()->checkAccess(AccessType::SYSTEM_DROP_REPLICA, query.getDatabase()); |
| 1919 | DatabasePtr database = DatabaseCatalog::instance().getDatabase(query.getDatabase()); |
| 1920 | if (auto * replicated = dynamic_cast<DatabaseReplicated *>(database.get())) |
| 1921 | { |
| 1922 | check_not_local_replica(replicated, full_replica_name, query_replica_zk_path); |
| 1923 | if (query.with_tables) |
| 1924 | dropStorageReplicasFromDatabase(query.replica, database); |
| 1925 | DatabaseReplicated::dropReplica( |
| 1926 | replicated, replicated->getZooKeeperName(), replicated->getZooKeeperPath(), query.shard, query.replica, /*throw_if_noop*/ true); |
| 1927 | } |
| 1928 | else |
| 1929 | throw Exception(ErrorCodes::BAD_ARGUMENTS, "Database {} is not Replicated, cannot drop replica", query.getDatabase()); |
| 1930 | LOG_TRACE(log, "Dropped replica {} of Replicated database {}", query.replica, backQuoteIfNeed(database->getDatabaseName())); |
| 1931 | } |
| 1932 | else if (query.is_drop_whole_replica) |
| 1933 | { |
| 1934 | auto databases = DatabaseCatalog::instance().getDatabases(GetDatabasesOptions{.with_remote_databases = false}); |
| 1935 | auto access = getContext()->getAccess(); |
| 1936 | bool access_is_granted_globally = access->isGranted(AccessType::SYSTEM_DROP_REPLICA); |
| 1937 | |
| 1938 | for (auto & elem : databases) |
| 1939 | { |
| 1940 | DatabasePtr & database = elem.second; |
| 1941 | auto * replicated = dynamic_cast<DatabaseReplicated *>(database.get()); |
| 1942 | if (!replicated) |
| 1943 | continue; |
| 1944 | if (!access_is_granted_globally && !access->isGranted(AccessType::SYSTEM_DROP_REPLICA, elem.first)) |
| 1945 | { |
| 1946 | LOG_INFO(log, "Access {} denied, skipping database {}", "SYSTEM DROP REPLICA", elem.first); |
| 1947 | continue; |
| 1948 | } |
| 1949 | |
| 1950 | check_not_local_replica(replicated, full_replica_name, query_replica_zk_path); |
| 1951 | if (query.with_tables) |
nothing calls this directly
no test coverage detected