| 189 | |
| 190 | |
| 191 | BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create) |
| 192 | { |
| 193 | String database_name = create.database; |
| 194 | if (database_name.empty()) |
| 195 | throw Exception("Database name is empty while creating database", ErrorCodes::BAD_ARGUMENTS); |
| 196 | |
| 197 | auto guard = DatabaseCatalog::instance().getDDLGuard(database_name, ""); |
| 198 | |
| 199 | /// Database can be created before or it can be created concurrently in another thread, while we were waiting in DDLGuard |
| 200 | if (DatabaseCatalog::instance().isDatabaseExist(database_name, getContext())) |
| 201 | { |
| 202 | if (create.if_not_exists) |
| 203 | return {}; |
| 204 | else |
| 205 | throw Exception("Database " + database_name + " already exists.", ErrorCodes::DATABASE_ALREADY_EXISTS); |
| 206 | } |
| 207 | |
| 208 | /// Will write file with database metadata, if needed. |
| 209 | String database_name_escaped = escapeForFileName(database_name); |
| 210 | fs::path metadata_path = fs::canonical(getContext()->getPath()); |
| 211 | fs::path metadata_file_tmp_path = metadata_path / "metadata" / (database_name_escaped + ".sql.tmp"); |
| 212 | fs::path metadata_file_path = metadata_path / "metadata" / (database_name_escaped + ".sql"); |
| 213 | |
| 214 | if (!create.storage && create.attach) |
| 215 | { |
| 216 | if (!fs::exists(metadata_file_path)) |
| 217 | throw Exception("Database engine must be specified for ATTACH DATABASE query", ErrorCodes::UNKNOWN_DATABASE_ENGINE); |
| 218 | /// Short syntax: try read database definition from file |
| 219 | auto ast = DatabaseOnDisk::parseQueryFromMetadata(nullptr, getContext(), metadata_file_path); |
| 220 | create = ast->as<ASTCreateQuery &>(); |
| 221 | if (!create.table.empty() || !create.storage) |
| 222 | throw Exception(ErrorCodes::INCORRECT_QUERY, "Metadata file {} contains incorrect CREATE DATABASE query", metadata_file_path.string()); |
| 223 | create.attach = true; |
| 224 | create.attach_short_syntax = true; |
| 225 | create.database = database_name; |
| 226 | } |
| 227 | else if (!create.storage) |
| 228 | { |
| 229 | /// For new-style databases engine is explicitly specified in .sql |
| 230 | /// When attaching old-style database during server startup, we must always use Ordinary engine |
| 231 | if (create.attach) |
| 232 | throw Exception("Database engine must be specified for ATTACH DATABASE query", ErrorCodes::UNKNOWN_DATABASE_ENGINE); |
| 233 | DefaultDatabaseEngine default_database_engine = (database_name == "default") ? DefaultDatabaseEngine::Atomic : getContext()->getSettingsRef().default_database_engine.value; |
| 234 | auto engine = std::make_shared<ASTFunction>(); |
| 235 | auto storage = std::make_shared<ASTStorage>(); |
| 236 | |
| 237 | // TODO: check here |
| 238 | if (default_database_engine == DefaultDatabaseEngine::Cnch) |
| 239 | engine->name = "Cnch"; |
| 240 | else if (default_database_engine == DefaultDatabaseEngine::Ordinary) |
| 241 | engine->name = "Ordinary"; |
| 242 | else if (default_database_engine == DefaultDatabaseEngine::Atomic) |
| 243 | engine->name = "Atomic"; |
| 244 | else |
| 245 | engine->name = "Memory"; |
| 246 | |
| 247 | engine->no_empty_args = true; |
| 248 | storage->set(storage->engine, engine); |
no test coverage detected