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

Code before:
static NamesAndTypesList getCommonVirtualsForFileLikeStorage()
{
    return {
        {"_path", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"_file", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"_size", makeNullable(std::make_shared<DataTypeUInt64>())},
        {"_time", makeNullable(std::make_shared<DataTypeDateTime>())},
        {"_etag", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"_tags", std::make_shared<DataTypeMap>(std::make_shared<DataTypeString>(), std::make_shared<DataTypeString>())},
        {"_data_lake_snapshot_version", makeNullable(std::make_shared<DataTypeUInt64>())},
        {"_row_number", makeNullable(std::make_shared<DataTypeInt64>())},
    };
}

NameSet getVirtualNamesForFileLikeStorage()
{
    return getCommonVirtualsForFileLikeStorage().getNameSet();
}

VirtualColumnsDescription getVirtualsForFileLikeStorage(
    ColumnsDescription & storage_columns,
    ContextPtr context,
    const std::optional<FormatSettings> & format_settings_,
    const std::string & path)
{
    VirtualColumnsDescription desc;

    auto add_virtual = [&](const NameAndTypePair & pair)
    {
        const auto & name = pair.getNameInStorage();
        if (storage_columns.has(name))
            return;

        const auto & type = pair.getTypeInStorage();
        desc.addEphemeral(name, type, "");
    };

    for (const auto & item : getCommonVirtualsForFileLikeStorage())
        add_virtual(item);

    if (!path.empty() && context->getSettingsRef()[Setting::use_hive_partitioning])
    {
        const auto format_settings = format_settings_ ? *format_settings_ : getFormatSettings(context);
        const auto map = HivePartitioningUtils::parseHivePartitioningKeysAndValues(path);
        for (const auto & item : map)
        {
            auto type = tryInferDataTypeByEscapingRule(std::string(item.second), format_settings, FormatSettings::EscapingRule::Raw, nullptr);
            if (type == nullptr)
                type = std::make_shared<DataTypeString>();
            if (type->canBeInsideLowCardinality())
                add_virtual({std::string(item.first), std::make_shared<DataTypeLowCardinality>(type)});

Review comment (security):
JAS: Imho, it is better to pass use_hive_partitioning setting as a parameter here, not to make unnecessary state injection

Code after:
        column = column->filter(*filter.data, -1);
    }
}

static NamesAndTypesList getCommonVirtualsForFileLikeStorage()
{
    return {
        {"_path", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"_file", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"_size", makeNullable(std::make_shared<DataTypeUInt64>())},
        {"_time", makeNullable(std::make_shared<DataTypeDateTime>())},
        {"_etag", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"_tags", std::make_shared<DataTypeMap>(std::make_shared<DataTypeString>(), std::make_shared<DataTypeString>())},
        {"_data_lake_snapshot_version", makeNullable(std::make_shared<DataTypeUInt64>())},
        {"_row_number", makeNullable(std::make_shared<DataTypeInt64>())},
    };
}

NameSet getVirtualNamesForFileLikeStorage()
{
    return getCommonVirtualsForFileLikeStorage().getNameSet();
}

VirtualColumnsDescription getVirtualsForFileLikeStorage(
    ColumnsDescription & storage_columns,
    ContextPtr context,
    const std::optional<FormatSettings> & format_settings,
    std::optional<PartitionStrategyFactory::StrategyType> partition_strategy,
    const std::string & path)
{
    VirtualColumnsDescription desc;

    auto add_virtual = [&](const NameAndTypePair & pair)
    {
        const auto & name = pair.getNameInStorage();
        if (storage_columns.has(name))
            return;

        const auto & type = pair.getTypeInStorage();
        desc.addEphemeral(name, type, "");
    };

    for (const auto & item : getCommonVirtualsForFileLikeStorage())
        add_virtual(item);

    if (!path.empty())
    {
        if (!partition_strategy.has_value())
            throw Exception(ErrorCodes::LOGICAL_ERROR, "Expected partition strategy to be specified");

        /// If partition_stategy == none, we add hive columns, if present, to virtual columns.