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

Code before:
    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);
    }
    if (!configuration->isDataLakeConfiguration() && !columns_in_table_or_function_definition.empty())
    {
        String sample_path_schema;   
        std::optional<ColumnsDescription> schema_file;
        try
        {
            schema_file = resolveSchemaFromData(object_storage_, configuration_, {}, sample_path_schema, context);
        }
        catch (...)
        {
            tryLogCurrentException(log);
        }
        if (schema_file)
        {
            if (schema_file->size() != columns_in_table_or_function_definition.size())
                throw Exception(ErrorCodes::BAD_ARGUMENTS, "Number of columns mismatch in schema and file {} {}", schema_file->size(), columns_in_table_or_function_definition.size());
            for (const auto & column : *schema_file)
                if (!columns_in_table_or_function_definition.tryGet(column.name))
                    throw Exception(ErrorCodes::BAD_ARGUMENTS, "Cannot find column in schema {}", column.name);
        }
    }
}

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

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

bool StorageObjectStorage::parallelizeOutputAfterReading(ContextPtr context) const
{
    return FormatFactory::instance().checkParallelizeOutputAfterReading(configuration->format, context);
}

bool StorageObjectStorage::supportsSubsetOfColumns(const ContextPtr & context) const
{
    return FormatFactory::instance().checkIfFormatSupportsSubsetOfColumns(configuration->format, context, format_settings);

Review comment (suggestion):
I think this is normal to read a subset of columns? E.g. in clickhose a table is defined with a subset of actual  s3 file columns because a user does not want to read them all

Code after:
    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);
}

bool StorageObjectStorage::parallelizeOutputAfterReading(ContextPtr context) const
{
    return FormatFactory::instance().checkParallelizeOutputAfterReading(configuration->format, context);
}

bool StorageObjectStorage::supportsSubsetOfColumns(const ContextPtr & context) const
{
    return FormatFactory::instance().checkIfFormatSupportsSubsetOfColumns(configuration->format, context, format_settings);
}