ClickHouse

Форк
0
/
tupleToNameValuePairs.cpp 
137 строк · 4.6 Кб
1
#include <Functions/IFunction.h>
2
#include <Functions/FunctionFactory.h>
3
#include <Functions/FunctionHelpers.h>
4
#include <DataTypes/IDataType.h>
5
#include <DataTypes/DataTypeTuple.h>
6
#include <DataTypes/DataTypeArray.h>
7
#include <DataTypes/DataTypeString.h>
8
#include <Columns/ColumnTuple.h>
9
#include <Columns/ColumnArray.h>
10
#include <Columns/ColumnString.h>
11
#include <Columns/ColumnsNumber.h>
12
#include <Common/assert_cast.h>
13
#include <memory>
14

15
namespace DB
16
{
17
namespace ErrorCodes
18
{
19
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
20
}
21

22
namespace
23
{
24

25
/** Transform a named tuple into an array of pairs, where the first element
26
  * of the pair corresponds to the tuple field name and the second one to the
27
  * tuple value.
28
  */
29
class FunctionTupleToNameValuePairs : public IFunction
30
{
31
public:
32
    static constexpr auto name = "tupleToNameValuePairs";
33
    static FunctionPtr create(ContextPtr)
34
    {
35
        return std::make_shared<FunctionTupleToNameValuePairs>();
36
    }
37

38
    String getName() const override
39
    {
40
        return name;
41
    }
42

43
    size_t getNumberOfArguments() const override
44
    {
45
        return 1;
46
    }
47

48
    bool useDefaultImplementationForConstants() const override
49
    {
50
        return true;
51
    }
52

53
    bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override
54
    {
55
        return true;
56
    }
57

58

59
    DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
60
    {
61
        // get the type of all the fields in the tuple
62
        const IDataType * col = arguments[0].type.get();
63
        const DataTypeTuple * tuple = checkAndGetDataType<DataTypeTuple>(col);
64

65
        if (!tuple)
66
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
67
                            "First argument for function {} must be a tuple.",
68
                            getName());
69

70
        const auto & element_types = tuple->getElements();
71

72
        if (element_types.empty())
73
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
74
                            "The argument tuple for function {} must not be empty.",
75
                            getName());
76

77
        const auto & first_element_type = element_types[0];
78

79
        bool all_value_types_equal = std::all_of(element_types.begin() + 1,
80
                                                 element_types.end(),
81
                                                 [&](const auto &other)
82
                                                 {
83
                                                     return first_element_type->equals(*other);
84
                                                 });
85

86
        if (!all_value_types_equal)
87
        {
88
            throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
89
                            "The argument tuple for function {} must contain just one type.",
90
                            getName());
91
        }
92

93
        DataTypePtr tuple_name_type = std::make_shared<DataTypeString>();
94
        DataTypes item_data_types = {tuple_name_type,
95
                                     first_element_type};
96

97
        auto item_data_type = std::make_shared<DataTypeTuple>(item_data_types);
98

99
        return std::make_shared<DataTypeArray>(item_data_type);
100
    }
101

102
    ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
103
    {
104
        const IColumn * tuple_col = arguments[0].column.get();
105
        const DataTypeTuple * tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
106
        const auto * tuple_col_concrete = assert_cast<const ColumnTuple*>(tuple_col);
107

108
        auto keys = ColumnString::create();
109
        MutableColumnPtr values = tuple_col_concrete->getColumn(0).cloneEmpty();
110
        auto offsets = ColumnVector<UInt64>::create();
111
        for (size_t row = 0; row < tuple_col_concrete->size(); ++row)
112
        {
113
            for (size_t col = 0; col < tuple_col_concrete->tupleSize(); ++col)
114
            {
115
                const std::string & key = tuple->getElementNames()[col];
116
                const IColumn & value_column = tuple_col_concrete->getColumn(col);
117

118
                values->insertFrom(value_column, row);
119
                keys->insertData(key.data(), key.size());
120
            }
121
            offsets->insertValue(tuple_col_concrete->tupleSize() * (row + 1));
122
        }
123

124
        std::vector<ColumnPtr> tuple_columns = { std::move(keys), std::move(values) };
125
        auto tuple_column = ColumnTuple::create(std::move(tuple_columns));
126
        return ColumnArray::create(std::move(tuple_column), std::move(offsets));
127
    }
128
};
129

130
}
131

132
REGISTER_FUNCTION(TupleToNameValuePairs)
133
{
134
    factory.registerFunction<FunctionTupleToNameValuePairs>();
135
}
136

137
}
138

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

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

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

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