Repository: ClickHouse/ClickHouse
File: src/Interpreters/InterpreterCreateQuery.cpp (C++)

Code before:
try
{
    validateVirtualColumns(storage);
    checkForUnsupportedColumns(storage, mode);
}
catch (...)
{
    if (mode <= LoadingStrictnessLevel::CREATE)
    {
        try
        {
            storage.drop();
        }
        catch (...)
        {
            tryLogCurrentException("validateStorage");
        }
    }
    throw;
}

}

/// Ensures that for a given disk used with `table_disk`, at most one table is non-readonly. table_disk assumes no directory-level isolation
/// between tables on the same disk, so allowing multiple writable tables would risk data corruption.
static void validateTableDiskUniqueness(const MergeTreeData & merge_tree, ContextPtr context)
{
    for (const auto & disk : merge_tree.getDisks())
    {
        if (disk->isReadOnly())
            continue;

        const String & disk_name = disk->getName();

        for (const auto & [db_name, database] : DatabaseCatalog::instance().getDatabases({}))
        {
            for (auto it = database->getTablesIterator(context); it->isValid(); it->next())
            {
                auto table = it->table();
                if (!table)
                    continue;

                auto * existing_merge_tree = dynamic_cast<MergeTreeData *>(table.get());
                if (!existing_merge_tree)
                    continue;

                auto existing_settings = existing_merge_tree->getSettings();
                if (!(*existing_settings)[MergeTreeSetting::table_disk])
                    continue;

                for (const auto & existing_disk : existing_merge_tree->getDisks())

Review comment (refactor):
Let's move this code to `registerStorageMergeTree.cpp`

Code after:
catch (...)
{
    if (mode <= LoadingStrictnessLevel::CREATE)
    {
        try
        {
            storage.drop();
        }
        catch (...)
        {
            tryLogCurrentException("validateStorage");
        }
    }
    throw;
}

}

bool InterpreterCreateQuery::doCreateTable(ASTCreateQuery & create,
                                           const InterpreterCreateQuery::TableProperties & properties,
                                           DDLGuardPtr & ddl_guard, LoadingStrictnessLevel mode)
{
    if (create.isTemporary())
    {
        if (create.if_not_exists && getContext()->tryResolveStorageID({"", create.getTable()}, Context::ResolveExternal))
            return false;

        DatabasePtr database = DatabaseCatalog::instance().getDatabase(DatabaseCatalog::TEMPORARY_DATABASE);

        String temporary_table_name = create.getTable();
        auto creator = [&](const StorageID & table_id)
        {
            auto res = StorageFactory::instance().get(create,
                database->getTableDataPath(table_id.getTableName()),
                getContext(),
                getContext()->getGlobalContext(),
                properties.columns,
                properties.constraints,
                mode,
                is_restore_from_backup);
            validateStorage(*res, mode);
            return res;
        };
        auto temporary_table = TemporaryTableHolder(getContext(), creator, query_ptr);

        getContext()->getSessionContext()->addExternalTable(temporary_table_name, std::move(temporary_table));
        return true;
    }

    if (!ddl_guard && likely(need_ddl_guard))
        ddl_guard = DatabaseCatalog::instance().getDDLGuard(create.getDatabase(), create.getTable(), nullptr);