Repository: ClickHouse/ClickHouse
File: src/Storages/ObjectStorage/StorageObjectStorage.cpp (C++)

Code before:
    /// I am not sure this is actually required, but just in case
    if (configuration->partition_strategy)
    {
        metadata.partition_key = configuration->partition_strategy->getPartitionKeyDescription();
    }

    setVirtuals(VirtualColumnUtils::getVirtualsForFileLikeStorage(
        metadata.columns,
        context,
        format_settings,
        configuration->partition_strategy_type,
        sample_path));

    setInMemoryMetadata(metadata);

    /// This will update metadata for table function which contains specific information about table
    /// state (e.g. for Iceberg). It is done because select queries for table functions are executed
    /// in a different way and clickhouse can execute without calling updateExternalDynamicMetadataIfExists.
    if (!do_lazy_init && is_table_function && configuration->needsUpdateForSchemaConsistency())
    {
        auto metadata_snapshot = configuration->getStorageSnapshotMetadata(context);
        setInMemoryMetadata(metadata_snapshot);
    }

    /// We don't need to process data lakes because tables may have "schema evolution" feature.
    if (!configuration->isDataLakeConfiguration() &&
        !columns_in_table_or_function_definition.empty() &&
        !is_table_function &&
        configuration_->format != "CSV" &&
        configuration_->format != "TSV" &&
        mode == LoadingStrictnessLevel::CREATE &&
        !do_lazy_init)
    {
        String sample_path_schema;
        std::optional<ColumnsDescription> schema_file;
        try
        {
            schema_file = resolveSchemaFromData(object_storage_, configuration_, {}, sample_path_schema, context);
        }
        catch (...)
        {
            tryLogCurrentException(log, "", LogsLevel::debug);
        }
        if (schema_file)
        {
            std::unordered_set<String> hive_parititioning_columns;
            for (const auto & column_name : hive_partition_columns_to_read_from_file_path.getNames())
                hive_parititioning_columns.insert(column_name);
            for (const auto & column : columns_in_table_or_function_definition)
                if (!schema_file->tryGet(column.name) && !hive_parititioning_columns.contains(column.name))
                {

Review comment (refactor):
Above if columns were explictly specified - we do `validateSupportedColumns`, why not move this check there and rename it to `validateColumns`?

Code after:
    ///    error. Unlike hive partitioning, we can't (?) just return these columns from
    ///    supportedPrewhereColumns() because at the time of the call the delta lake metadata hasn't
    ///    been read yet. So we should probably pass these columns to the parquet reader instead of
    ///    adding them outside.
    ///  * There's a bug in StorageObjectStorageSource::createReader: it makes a copy of
    ///    FormatFilterInfo, but for some reason unsets prewhere_info and row_level_filter_info.
    ///    There's probably no reason for this, and it should just copy those fields like the others.
    ///  * If the table contains files in different formats, with only some of them supporting
    ///    prewhere, things break.
    supports_prewhere = !configuration->isDataLakeConfiguration() && format_supports_prewhere;
    supports_tuple_elements = format_supports_prewhere;

    StorageInMemoryMetadata metadata;
    metadata.setColumns(columns);
    metadata.setConstraints(constraints_);
    metadata.setComment(comment);

    /// I am not sure this is actually required, but just in case
    if (configuration->partition_strategy)
    {
        metadata.partition_key = configuration->partition_strategy->getPartitionKeyDescription();
    }

    setVirtuals(VirtualColumnUtils::getVirtualsForFileLikeStorage(
        metadata.columns,
        context,
        format_settings,
        configuration->partition_strategy_type,
        sample_path));

    setInMemoryMetadata(metadata);

    /// This will update metadata for table function which contains specific information about table
    /// state (e.g. for Iceberg). It is done because select queries for table functions are executed
    /// in a different way and clickhouse can execute without calling updateExternalDynamicMetadataIfExists.
    if (!do_lazy_init && is_table_function && configuration->needsUpdateForSchemaConsistency())
    {
        auto metadata_snapshot = configuration->getStorageSnapshotMetadata(context);
        setInMemoryMetadata(metadata_snapshot);
    }

}

String StorageObjectStorage::getName() const
{
    return configuration->getEngineName();
}

bool StorageObjectStorage::prefersLargeBlocks() const
{
    return FormatFactory::instance().checkIfOutputFormatPrefersLargeBlocks(configuration->format);