| 373 | } |
| 374 | |
| 375 | static void convertOrdinaryDatabaseToAtomic(LoggerPtr log, ContextMutablePtr context, const DatabasePtr & database, |
| 376 | const String & name, const String tmp_name) |
| 377 | { |
| 378 | /// It's kind of C++ script that creates temporary database with Atomic engine, |
| 379 | /// moves all tables to it, drops old database and then renames new one to old name. |
| 380 | |
| 381 | String name_quoted = backQuoteIfNeed(name); |
| 382 | String tmp_name_quoted = backQuoteIfNeed(tmp_name); |
| 383 | |
| 384 | LOG_INFO(log, "Will convert database {} from Ordinary to Atomic", name_quoted); |
| 385 | |
| 386 | { |
| 387 | auto create_database_query_context = Context::createCopy(context); |
| 388 | create_database_query_context->makeQueryContext(); |
| 389 | create_database_query_context->setCurrentQueryId(""); |
| 390 | |
| 391 | QueryScope query_scope; |
| 392 | if (!CurrentThread::getGroup()) |
| 393 | query_scope = QueryScope::create(create_database_query_context); |
| 394 | |
| 395 | String create_database_query = fmt::format("CREATE DATABASE IF NOT EXISTS {}", tmp_name_quoted); |
| 396 | |
| 397 | auto res = executeQuery(create_database_query, std::move(create_database_query_context), QueryFlags{ .internal = true }).second; |
| 398 | executeTrivialBlockIO(res, context); |
| 399 | } |
| 400 | |
| 401 | auto tmp_database = DatabaseCatalog::instance().getDatabase(tmp_name); |
| 402 | chassert(tmp_database->getEngineName() == "Atomic"); |
| 403 | |
| 404 | size_t num_tables = 0; |
| 405 | std::unordered_set<String> inner_mv_tables; |
| 406 | for (auto iterator = database->getTablesIterator(context); iterator->isValid(); iterator->next()) |
| 407 | { |
| 408 | ++num_tables; |
| 409 | auto id = iterator->table()->getStorageID(); |
| 410 | id.database_name = tmp_name; |
| 411 | /// We need some uuid for checkTableCanBeRenamed |
| 412 | id.uuid = UUIDHelpers::generateV4(); |
| 413 | iterator->table()->checkTableCanBeRenamed(id); |
| 414 | if (const auto * mv = dynamic_cast<const StorageMaterializedView *>(iterator->table().get())) |
| 415 | { |
| 416 | /// We should not rename inner tables of MVs, because MVs are responsible for renaming it... |
| 417 | if (mv->hasInnerTable()) |
| 418 | inner_mv_tables.emplace(mv->getTargetTable()->getStorageID().table_name); |
| 419 | } |
| 420 | } |
| 421 | |
| 422 | LOG_INFO(log, "Will move {} tables to {} (including {} inner tables of MVs)", num_tables, tmp_name_quoted, inner_mv_tables.size()); |
| 423 | |
| 424 | for (auto iterator = database->getTablesIterator(context); iterator->isValid(); iterator->next()) |
| 425 | { |
| 426 | auto id = iterator->table()->getStorageID(); |
| 427 | if (inner_mv_tables.contains(id.table_name)) |
| 428 | { |
| 429 | LOG_DEBUG(log, "Do not rename {}, because it will be renamed together with MV", id.getNameForLogs()); |
| 430 | continue; |
| 431 | } |
| 432 |
no test coverage detected