1#include <DataTypes/DataTypeString.h>
2#include <DataTypes/DataTypesNumber.h>
3#include <Functions/IFunctionImpl.h>
4#include <Functions/FunctionHelpers.h>
5#include <Columns/ColumnVector.h>
6#include <Columns/ColumnString.h>
7#include <Columns/ColumnFixedString.h>
8#include <Columns/ColumnArray.h>
9
10
11namespace DB
12{
13
14namespace ErrorCodes
15{
16 extern const int ILLEGAL_COLUMN;
17 extern const int ILLEGAL_TYPE_OF_ARGUMENT;
18}
19
20
21template <typename Impl, typename Name, typename ResultType>
22class FunctionStringOrArrayToT : public IFunction
23{
24public:
25 static constexpr auto name = Name::name;
26 static FunctionPtr create(const Context &)
27 {
28 return std::make_shared<FunctionStringOrArrayToT>();
29 }
30
31 String getName() const override
32 {
33 return name;
34 }
35
36 size_t getNumberOfArguments() const override
37 {
38 return 1;
39 }
40
41 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
42 {
43 if (!isStringOrFixedString(arguments[0])
44 && !isArray(arguments[0]))
45 throw Exception("Illegal type " + arguments[0]->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
46
47 return std::make_shared<DataTypeNumber<ResultType>>();
48 }
49
50 bool useDefaultImplementationForConstants() const override { return true; }
51
52 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
53 {
54 const ColumnPtr column = block.getByPosition(arguments[0]).column;
55 if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
56 {
57 auto col_res = ColumnVector<ResultType>::create();
58
59 typename ColumnVector<ResultType>::Container & vec_res = col_res->getData();
60 vec_res.resize(col->size());
61 Impl::vector(col->getChars(), col->getOffsets(), vec_res);
62
63 block.getByPosition(result).column = std::move(col_res);
64 }
65 else if (const ColumnFixedString * col_fixed = checkAndGetColumn<ColumnFixedString>(column.get()))
66 {
67 if (Impl::is_fixed_to_constant)
68 {
69 ResultType res = 0;
70 Impl::vector_fixed_to_constant(col_fixed->getChars(), col_fixed->getN(), res);
71
72 block.getByPosition(result).column = block.getByPosition(result).type->createColumnConst(col_fixed->size(), toField(res));
73 }
74 else
75 {
76 auto col_res = ColumnVector<ResultType>::create();
77
78 typename ColumnVector<ResultType>::Container & vec_res = col_res->getData();
79 vec_res.resize(col_fixed->size());
80 Impl::vector_fixed_to_vector(col_fixed->getChars(), col_fixed->getN(), vec_res);
81
82 block.getByPosition(result).column = std::move(col_res);
83 }
84 }
85 else if (const ColumnArray * col_arr = checkAndGetColumn<ColumnArray>(column.get()))
86 {
87 auto col_res = ColumnVector<ResultType>::create();
88
89 typename ColumnVector<ResultType>::Container & vec_res = col_res->getData();
90 vec_res.resize(col_arr->size());
91 Impl::array(col_arr->getOffsets(), vec_res);
92
93 block.getByPosition(result).column = std::move(col_res);
94 }
95 else
96 throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName() + " of argument of function " + getName(),
97 ErrorCodes::ILLEGAL_COLUMN);
98 }
99};
100
101}
102