Repository: ClickHouse/ClickHouse
File: src/Databases/DataLake/ICatalog.cpp (C++)

Code before:
    auto capitalize_first_letter = [] (const std::string & s)
    {
        auto result = Poco::toLower(s);
        if (!result.empty())
            result[0] = std::toupper(result[0]);
        return result;
    };

    std::string storage_type_str = type;
    auto pos = storage_type_str.find("://");
    if (pos != std::string::npos)
    {
        // convert s3://, file://, etc. to s3, file etc.
        storage_type_str = storage_type_str.substr(0,pos);
    }
    if (capitalize_first_letter(storage_type_str) == "File")
        storage_type_str = "Local";
    else if (capitalize_first_letter(storage_type_str) == "S3a" || storage_type_str == "oss" || storage_type_str == "gs")
        storage_type_str = "S3";
    else if (storage_type_str == "abfss") /// Azure Blob File System Secure
        storage_type_str = "Azure";

    auto storage_type = magic_enum::enum_cast<StorageType>(capitalize_first_letter(storage_type_str));

    if (!storage_type)
    {
        throw DB::Exception(
            DB::ErrorCodes::NOT_IMPLEMENTED,
            "Unsupported storage type: {}", storage_type_str);
    }

    return *storage_type;
}

void TableMetadata::setLocation(const std::string & location_)
{
    if (!with_location)
        throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Data location was not requested");

    /// Location has format:
    /// s3://<bucket>/path/to/table/data.
    /// We want to split s3://<bucket> and path/to/table/data.

    auto pos = location_.find("://");
    if (pos == std::string::npos)
        throw DB::Exception(DB::ErrorCodes::NOT_IMPLEMENTED, "Unexpected location format: {}", location_);

    // pos+3 to account for ://
    storage_type_str = location_.substr(0, pos+3);
    auto pos_to_bucket = pos + std::strlen("://");
    auto pos_to_path = location_.substr(pos_to_bucket).find('/');

Review comment (bug):
maybe we can use "failpoints" and replace `storage_type_str` with "gs"... I understand the stupidity of such approach, but the complexity of integration test scares me even more. 

Code after:
            "Unexpected path format: {}", location);
    }

    return parseStorageTypeFromString(location.substr(0, pos));
}

StorageType parseStorageTypeFromString(const std::string & type)
{
    auto capitalize_first_letter = [] (const std::string & s)
    {
        auto result = Poco::toLower(s);
        if (!result.empty())
            result[0] = std::toupper(result[0]);
        return result;
    };

    std::string storage_type_str = type;
    auto pos = storage_type_str.find("://");
    if (pos != std::string::npos)
    {
        // convert s3://, file://, etc. to s3, file etc.
        storage_type_str = storage_type_str.substr(0,pos);
    }
    if (capitalize_first_letter(storage_type_str) == "File")
        storage_type_str = "Local";
    else if (capitalize_first_letter(storage_type_str) == "S3a" || storage_type_str == "oss" || storage_type_str == "gs")
    {
        fiu_do_on(DB::FailPoints::database_iceberg_gcs,
        {
            throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Google cloud storage converts to S3");
        });
        storage_type_str = "S3";
    }
    else if (storage_type_str == "abfss") /// Azure Blob File System Secure
        storage_type_str = "Azure";

    auto storage_type = magic_enum::enum_cast<StorageType>(capitalize_first_letter(storage_type_str));

    if (!storage_type)
    {
        throw DB::Exception(
            DB::ErrorCodes::NOT_IMPLEMENTED,
            "Unsupported storage type: {}", storage_type_str);
    }

    return *storage_type;
}

void TableMetadata::setLocation(const std::string & location_)
{
    if (!with_location)