| 455 | } |
| 456 | |
| 457 | BlockIO InterpreterDropQuery::executeToDatabaseImpl(const ASTDropQuery & query, DatabasePtr & database, std::vector<UUID> & uuids_to_wait) |
| 458 | { |
| 459 | if (query.kind != ASTDropQuery::Kind::Detach && query.kind != ASTDropQuery::Kind::Drop && query.kind != ASTDropQuery::Kind::Truncate) |
| 460 | return {}; |
| 461 | |
| 462 | const auto & database_name = query.getDatabase(); |
| 463 | auto ddl_guard = DatabaseCatalog::instance().getDDLGuard(database_name, "", nullptr); |
| 464 | |
| 465 | database = tryGetDatabase(database_name, query.if_exists); |
| 466 | if (!database) |
| 467 | return {}; |
| 468 | |
| 469 | bool drop = query.kind == ASTDropQuery::Kind::Drop; |
| 470 | bool truncate = query.kind == ASTDropQuery::Kind::Truncate; |
| 471 | |
| 472 | getContext()->checkAccess(AccessType::DROP_DATABASE, database_name); |
| 473 | |
| 474 | auto * const db_replicated = dynamic_cast<DatabaseReplicated *>(database.get()); |
| 475 | if (truncate && db_replicated) |
| 476 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "TRUNCATE DATABASE is not implemented for replicated databases"); |
| 477 | |
| 478 | if (query.kind == ASTDropQuery::Kind::Detach && query.permanently) |
| 479 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "DETACH PERMANENTLY is not implemented for databases"); |
| 480 | |
| 481 | if (query.if_empty) |
| 482 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "DROP IF EMPTY is not implemented for databases"); |
| 483 | |
| 484 | if (!truncate && database->hasReplicationThread()) |
| 485 | database->stopReplication(); |
| 486 | |
| 487 | if (database->shouldBeEmptyOnDetach()) |
| 488 | { |
| 489 | /// Cancel restarting replicas in that database, wait for remaining RESTART queries to finish. |
| 490 | /// So it will not startup tables concurrently with the flushAndPrepareForShutdown call below. |
| 491 | auto restart_replica_lock = DatabaseCatalog::instance().getLockForDropDatabase(database_name); |
| 492 | |
| 493 | ASTDropQuery query_for_table; |
| 494 | query_for_table.kind = query.kind; |
| 495 | // For truncate operation on database, drop the tables |
| 496 | if (truncate) |
| 497 | query_for_table.kind = query.has_tables ? ASTDropQuery::Kind::Truncate : ASTDropQuery::Kind::Drop; |
| 498 | if (database->getDisk()->isReadOnly()) |
| 499 | query_for_table.kind = ASTDropQuery::Detach; |
| 500 | query_for_table.if_exists = true; |
| 501 | query_for_table.if_empty = false; |
| 502 | query_for_table.setDatabase(database_name); |
| 503 | query_for_table.sync = query.sync; |
| 504 | |
| 505 | /// If we have a TRUNCATE TABLES .. LIKE, we should not truncate all tables, |
| 506 | /// the logic regarding finding suitable tables is a bit below |
| 507 | if (!truncate || !query.has_tables || query.like.empty()) |
| 508 | { |
| 509 | /// Flush should not be done if shouldBeEmptyOnDetach() == false, |
| 510 | /// since in this case getTablesIterator() may do some additional work, |
| 511 | /// see DatabaseMaterialized...SQL::getTablesIterator() |
| 512 | auto table_context = Context::createCopy(getContext()); |
| 513 | table_context->setInternalQuery(true); |
| 514 |
nothing calls this directly
no test coverage detected