| 1442 | } |
| 1443 | |
| 1444 | bool InterpreterCreateQuery::doCreateTable(ASTCreateQuery & create, |
| 1445 | const InterpreterCreateQuery::TableProperties & properties) |
| 1446 | { |
| 1447 | std::unique_ptr<DDLGuard> guard; |
| 1448 | |
| 1449 | String data_path; |
| 1450 | DatabasePtr database; |
| 1451 | IntentLockPtr db_lock; |
| 1452 | IntentLockPtr tb_lock; |
| 1453 | |
| 1454 | |
| 1455 | bool need_add_to_database = !create.temporary; |
| 1456 | if (need_add_to_database) |
| 1457 | { |
| 1458 | /** If the request specifies IF NOT EXISTS, we allow concurrent CREATE queries (which do nothing). |
| 1459 | * If table doesn't exist, one thread is creating table, while others wait in DDLGuard. |
| 1460 | */ |
| 1461 | guard = DatabaseCatalog::instance().getDDLGuard(create.database, create.table); |
| 1462 | |
| 1463 | database = DatabaseCatalog::instance().getDatabase(create.database, getContext()); |
| 1464 | if (database->getEngineName().starts_with("Cnch")) |
| 1465 | { |
| 1466 | auto txn = getContext()->getCurrentTransaction(); |
| 1467 | if (!txn) |
| 1468 | throw Exception("Transaction not initialized", ErrorCodes::CNCH_TRANSACTION_NOT_INITIALIZED); |
| 1469 | /// May need to acquire kv lock before creating entry |
| 1470 | if (getContext()->getSettingsRef().bypass_ddl_db_lock) |
| 1471 | { |
| 1472 | tb_lock = txn->createIntentLock(IntentLock::TB_LOCK_PREFIX, database->getDatabaseName(), create.table); |
| 1473 | tb_lock->lock(); |
| 1474 | } |
| 1475 | else |
| 1476 | { |
| 1477 | db_lock = txn->createIntentLock(IntentLock::DB_LOCK_PREFIX, database->getDatabaseName()); |
| 1478 | tb_lock = txn->createIntentLock(IntentLock::TB_LOCK_PREFIX, database->getDatabaseName(), create.table); |
| 1479 | std::lock(*db_lock, *tb_lock); |
| 1480 | } |
| 1481 | } |
| 1482 | assertOrSetUUID(create, database); |
| 1483 | |
| 1484 | String storage_name = create.is_dictionary ? "Dictionary" : "Table"; |
| 1485 | auto storage_already_exists_error_code = create.is_dictionary ? ErrorCodes::DICTIONARY_ALREADY_EXISTS : ErrorCodes::TABLE_ALREADY_EXISTS; |
| 1486 | |
| 1487 | /// Table can be created before or it can be created concurrently in another thread, while we were waiting in DDLGuard. |
| 1488 | if (database->isTableExist(create.table, getContext())) |
| 1489 | { |
| 1490 | /// TODO Check structure of table |
| 1491 | if (create.if_not_exists) |
| 1492 | return false; |
| 1493 | else if (create.replace_view) |
| 1494 | { |
| 1495 | /// when executing CREATE OR REPLACE VIEW, drop current existing view |
| 1496 | auto drop_ast = std::make_shared<ASTDropQuery>(); |
| 1497 | drop_ast->database = create.database; |
| 1498 | drop_ast->table = create.table; |
| 1499 | drop_ast->no_ddl_lock = true; |
| 1500 | |
| 1501 | auto drop_context = Context::createCopy(context); |
nothing calls this directly
no test coverage detected