| 198 | |
| 199 | |
| 200 | BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create) |
| 201 | { |
| 202 | auto component_guard = Coordination::setCurrentComponent("InterpreterCreateQuery::createDatabase"); |
| 203 | String database_name = create.getDatabase(); |
| 204 | |
| 205 | auto guard = DatabaseCatalog::instance().getDDLGuard(database_name, "", nullptr); |
| 206 | |
| 207 | /// Database can be created before or it can be created concurrently in another thread, while we were waiting in DDLGuard |
| 208 | if (DatabaseCatalog::instance().isDatabaseExist(database_name)) |
| 209 | { |
| 210 | if (create.if_not_exists) |
| 211 | return {}; |
| 212 | throw Exception(ErrorCodes::DATABASE_ALREADY_EXISTS, "Database {} already exists.", database_name); |
| 213 | } |
| 214 | |
| 215 | auto db_num_limit = getContext()->getGlobalContext()->getServerSettings()[ServerSetting::max_database_num_to_throw].value; |
| 216 | if (db_num_limit > 0 && !internal) |
| 217 | { |
| 218 | size_t db_count = DatabaseCatalog::instance().getDatabases(GetDatabasesOptions{.with_remote_databases = true}).size(); |
| 219 | std::initializer_list<std::string_view> system_databases = |
| 220 | { |
| 221 | DatabaseCatalog::TEMPORARY_DATABASE, |
| 222 | DatabaseCatalog::SYSTEM_DATABASE, |
| 223 | DatabaseCatalog::INFORMATION_SCHEMA, |
| 224 | DatabaseCatalog::INFORMATION_SCHEMA_UPPERCASE, |
| 225 | }; |
| 226 | |
| 227 | for (const auto & system_database : system_databases) |
| 228 | { |
| 229 | if (db_count > 0 && DatabaseCatalog::instance().isDatabaseExist(std::string(system_database))) |
| 230 | --db_count; |
| 231 | } |
| 232 | |
| 233 | if (db_count >= db_num_limit) |
| 234 | throw Exception(ErrorCodes::TOO_MANY_DATABASES, |
| 235 | "Too many databases. " |
| 236 | "The limit (server configuration parameter `max_database_num_to_throw`) is set to {}, the current number of databases is {}", |
| 237 | db_num_limit, db_count); |
| 238 | } |
| 239 | |
| 240 | auto default_db_disk = getContext()->getDatabaseDisk(); |
| 241 | |
| 242 | /// Will write file with database metadata, if needed. |
| 243 | default_db_disk->createDirectories(DatabaseCatalog::getMetadataDirPath()); |
| 244 | auto metadata_file_path = DatabaseCatalog::getMetadataFilePath(database_name); |
| 245 | auto metadata_tmp_file_path = DatabaseCatalog::getMetadataTmpFilePath(database_name); |
| 246 | |
| 247 | fs::path metadata_path; |
| 248 | if (!create.storage && create.attach) |
| 249 | { |
| 250 | if (!default_db_disk->existsFile(metadata_file_path)) |
| 251 | throw Exception(ErrorCodes::UNKNOWN_DATABASE_ENGINE, "Database engine must be specified for ATTACH DATABASE query"); |
| 252 | /// Short syntax: try read database definition from file |
| 253 | auto ast = DatabaseOnDisk::parseQueryFromMetadata(nullptr, getContext(), default_db_disk, metadata_file_path); |
| 254 | create = ast->as<ASTCreateQuery &>(); |
| 255 | if (create.table || !create.storage) |
| 256 | throw Exception(ErrorCodes::INCORRECT_QUERY, "Metadata file {} contains incorrect CREATE DATABASE query", metadata_file_path.string()); |
| 257 | create.attach = true; |
nothing calls this directly
no test coverage detected