std::shared_ptr SerializedPlanBuilder::buildType()

in cpp-ch/local-engine/Builder/SerializedPlanBuilder.cpp [222:307]


std::shared_ptr<substrait::Type> SerializedPlanBuilder::buildType(const DB::DataTypePtr & ch_type)
{
    const auto ch_type_wo_lowcardinality = DB::removeLowCardinality(ch_type);

    const auto * ch_type_nullable = checkAndGetDataType<DataTypeNullable>(ch_type_wo_lowcardinality.get());

    const bool is_nullable = (ch_type_nullable != nullptr);
    auto type_nullability
        = is_nullable ? substrait::Type_Nullability_NULLABILITY_NULLABLE : substrait::Type_Nullability_NULLABILITY_REQUIRED;

    const auto ch_type_without_nullable = DB::removeNullable(ch_type_wo_lowcardinality);
    const DB::WhichDataType which(ch_type_without_nullable);

    auto res = std::make_shared<substrait::Type>();
    if (which.isUInt8())
        res->mutable_bool_()->set_nullability(type_nullability);
    else if (which.isInt8())
        res->mutable_i8()->set_nullability(type_nullability);
    else if (which.isInt16())
        res->mutable_i16()->set_nullability(type_nullability);
    else if (which.isInt32())
        res->mutable_i32()->set_nullability(type_nullability);
    else if (which.isInt64())
        res->mutable_i64()->set_nullability(type_nullability);
    else if (which.isStringOrFixedString() || which.isAggregateFunction())
        res->mutable_binary()->set_nullability(type_nullability); /// Spark Binary type is more similiar to CH String type
    else if (which.isFloat32())
        res->mutable_fp32()->set_nullability(type_nullability);
    else if (which.isFloat64())
        res->mutable_fp64()->set_nullability(type_nullability);
    else if (which.isFloat64())
        res->mutable_fp64()->set_nullability(type_nullability);
    else if (which.isDateTime64())
    {
        const auto * ch_type_datetime64 = checkAndGetDataType<DataTypeDateTime64>(ch_type_without_nullable.get());
        if (ch_type_datetime64->getScale() != 6)
            throw Exception(ErrorCodes::UNKNOWN_TYPE, "Spark doesn't support converting from {}", ch_type->getName());
        res->mutable_timestamp()->set_nullability(type_nullability);
    }
    else if (which.isDate32())
        res->mutable_date()->set_nullability(type_nullability);
    else if (which.isDecimal())
    {
        if (which.isDecimal256())
            throw Exception(ErrorCodes::UNKNOWN_TYPE, "Spark doesn't support converting from {}", ch_type->getName());

        const auto scale = getDecimalScale(*ch_type_without_nullable);
        const auto precision = getDecimalPrecision(*ch_type_without_nullable);
        if (scale == 0 && precision == 0)
            throw Exception(ErrorCodes::UNKNOWN_TYPE, "Spark doesn't support converting from {}", ch_type->getName());

        res->mutable_decimal()->set_nullability(type_nullability);
        res->mutable_decimal()->set_scale(scale);
        res->mutable_decimal()->set_precision(precision);
    }
    else if (which.isTuple())
    {
        const auto * ch_tuple_type = checkAndGetDataType<DataTypeTuple>(ch_type_without_nullable.get());
        const auto & ch_field_types = ch_tuple_type->getElements();
        res->mutable_struct_()->set_nullability(type_nullability);
        for (const auto & ch_field_type : ch_field_types)
            res->mutable_struct_()->mutable_types()->Add(std::move(*buildType(ch_field_type)));
    }
    else if (which.isArray())
    {
        const auto * ch_array_type = checkAndGetDataType<DataTypeArray>(ch_type_without_nullable.get());
        const auto & ch_nested_type = ch_array_type->getNestedType();
        res->mutable_list()->set_nullability(type_nullability);
        *(res->mutable_list()->mutable_type()) = *buildType(ch_nested_type);
    }
    else if (which.isMap())
    {
        const auto & ch_map_type = checkAndGetDataType<DataTypeMap>(ch_type_without_nullable.get());
        const auto & ch_key_type = ch_map_type->getKeyType();
        const auto & ch_val_type = ch_map_type->getValueType();
        res->mutable_map()->set_nullability(type_nullability);
        *(res->mutable_map()->mutable_key()) = *buildType(ch_key_type);
        *(res->mutable_map()->mutable_value()) = *buildType(ch_val_type);
    }
    else if (which.isNothing())
        res->mutable_nothing();
    else
        throw Exception(ErrorCodes::UNKNOWN_TYPE, "Spark doesn't support converting from {}", ch_type->getName());

    return res;
}