ClickHouse

Форк
0
/
CastOverloadResolver.cpp 
147 строк · 5.7 Кб
1
#include <Functions/FunctionFactory.h>
2
#include <Functions/CastOverloadResolver.h>
3
#include <Functions/FunctionHelpers.h>
4
#include <DataTypes/DataTypeFactory.h>
5
#include <DataTypes/DataTypeNullable.h>
6
#include <Columns/ColumnString.h>
7
#include <Interpreters/parseColumnsListForTableFunction.h>
8
#include <Interpreters/Context.h>
9

10

11
namespace DB
12
{
13

14
namespace ErrorCodes
15
{
16
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
17
}
18

19
FunctionBasePtr createFunctionBaseCast(
20
    ContextPtr context,
21
    const char * name,
22
    const ColumnsWithTypeAndName & arguments,
23
    const DataTypePtr & return_type,
24
    std::optional<CastDiagnostic> diagnostic,
25
    CastType cast_type);
26

27

28
/** CastInternal does not preserve nullability of the data type,
29
  * i.e. CastInternal(toNullable(toInt8(1)) as Int32) will be Int32(1).
30
  *
31
  * Cast preserves nullability according to setting `cast_keep_nullable`,
32
  * i.e. Cast(toNullable(toInt8(1)) as Int32) will be Nullable(Int32(1)) if `cast_keep_nullable` == 1.
33
  */
34
class CastOverloadResolverImpl : public IFunctionOverloadResolver
35
{
36
public:
37
    const char * getNameImpl() const
38
    {
39
        if (cast_type == CastType::accurate)
40
            return "accurateCast";
41
        if (cast_type == CastType::accurateOrNull)
42
            return "accurateCastOrNull";
43
        if (internal)
44
            return "_CAST";
45
        else
46
            return "CAST";
47
    }
48

49
    String getName() const override
50
    {
51
        return getNameImpl();
52
    }
53

54
    size_t getNumberOfArguments() const override { return 2; }
55

56
    ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
57

58
    explicit CastOverloadResolverImpl(ContextPtr context_, CastType cast_type_, bool internal_, std::optional<CastDiagnostic> diagnostic_, bool keep_nullable_, const DataTypeValidationSettings & data_type_validation_settings_)
59
        : context(context_)
60
        , cast_type(cast_type_)
61
        , internal(internal_)
62
        , diagnostic(std::move(diagnostic_))
63
        , keep_nullable(keep_nullable_)
64
        , data_type_validation_settings(data_type_validation_settings_)
65
    {
66
    }
67

68
    static FunctionOverloadResolverPtr create(ContextPtr context, CastType cast_type, bool internal, std::optional<CastDiagnostic> diagnostic)
69
    {
70
        if (internal)
71
        {
72
            return std::make_unique<CastOverloadResolverImpl>(context, cast_type, internal, diagnostic, false /*keep_nullable*/, DataTypeValidationSettings{});
73
        }
74
        else
75
        {
76
            const auto & settings_ref = context->getSettingsRef();
77
            return std::make_unique<CastOverloadResolverImpl>(context, cast_type, internal, diagnostic, settings_ref.cast_keep_nullable, DataTypeValidationSettings(settings_ref));
78
        }
79
    }
80

81
protected:
82
    FunctionBasePtr buildImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & return_type) const override
83
    {
84
        return createFunctionBaseCast(context, getNameImpl(), arguments, return_type, diagnostic, cast_type);
85
    }
86

87
    DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
88
    {
89
        const auto & column = arguments.back().column;
90
        if (!column)
91
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Second argument to {} must be a constant string describing type. "
92
                "Instead there is non-constant column of type {}", getName(), arguments.back().type->getName());
93

94
        const auto * type_col = checkAndGetColumnConst<ColumnString>(column.get());
95
        if (!type_col)
96
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Second argument to {} must be a constant string describing type. "
97
                "Instead there is a column with the following structure: {}", getName(), column->dumpStructure());
98

99
        DataTypePtr type = DataTypeFactory::instance().get(type_col->getValue<String>());
100
        validateDataType(type, data_type_validation_settings);
101

102
        if (cast_type == CastType::accurateOrNull)
103
        {
104
            /// Variant handles NULLs by itself during conversions.
105
            if (!isVariant(type))
106
                return makeNullable(type);
107
        }
108

109
        if (internal)
110
            return type;
111

112
        if (keep_nullable && arguments.front().type->isNullable() && type->canBeInsideNullable())
113
            return makeNullable(type);
114

115
        return type;
116
    }
117

118
    bool useDefaultImplementationForNulls() const override { return false; }
119
    bool useDefaultImplementationForNothing() const override { return false; }
120
    bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }
121

122
private:
123
    ContextPtr context;
124
    CastType cast_type;
125
    bool internal;
126
    std::optional<CastDiagnostic> diagnostic;
127
    bool keep_nullable;
128
    DataTypeValidationSettings data_type_validation_settings;
129
};
130

131

132
FunctionOverloadResolverPtr createInternalCastOverloadResolver(CastType type, std::optional<CastDiagnostic> diagnostic)
133
{
134
    return CastOverloadResolverImpl::create(ContextPtr{}, type, true, diagnostic);
135
}
136

137
REGISTER_FUNCTION(CastOverloadResolvers)
138
{
139
    factory.registerFunction("_CAST", [](ContextPtr context){ return CastOverloadResolverImpl::create(context, CastType::nonAccurate, true, {}); }, {}, FunctionFactory::CaseInsensitive);
140
    /// Note: "internal" (not affected by null preserving setting) versions of accurate cast functions are unneeded.
141

142
    factory.registerFunction("CAST", [](ContextPtr context){ return CastOverloadResolverImpl::create(context, CastType::nonAccurate, false, {}); }, {}, FunctionFactory::CaseInsensitive);
143
    factory.registerFunction("accurateCast", [](ContextPtr context){ return CastOverloadResolverImpl::create(context, CastType::accurate, false, {}); }, {});
144
    factory.registerFunction("accurateCastOrNull", [](ContextPtr context){ return CastOverloadResolverImpl::create(context, CastType::accurateOrNull, false, {}); }, {});
145
}
146

147
}
148

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.