1 | #include <DataTypes/DataTypeString.h> |
2 | #include <Columns/ColumnString.h> |
3 | #include <Columns/ColumnFixedString.h> |
4 | #include <Columns/ColumnArray.h> |
5 | #include <Functions/FunctionFactory.h> |
6 | #include <Functions/FunctionHelpers.h> |
7 | #include <ext/map.h> |
8 | |
9 | |
10 | namespace DB |
11 | { |
12 | |
13 | namespace ErrorCodes |
14 | { |
15 | extern const int ILLEGAL_COLUMN; |
16 | extern const int ILLEGAL_TYPE_OF_ARGUMENT; |
17 | } |
18 | |
19 | |
20 | /** Reverse the string as a sequence of bytes. |
21 | */ |
22 | struct ReverseImpl |
23 | { |
24 | static void vector(const ColumnString::Chars & data, |
25 | const ColumnString::Offsets & offsets, |
26 | ColumnString::Chars & res_data, |
27 | ColumnString::Offsets & res_offsets) |
28 | { |
29 | res_data.resize(data.size()); |
30 | res_offsets.assign(offsets); |
31 | size_t size = offsets.size(); |
32 | |
33 | ColumnString::Offset prev_offset = 0; |
34 | for (size_t i = 0; i < size; ++i) |
35 | { |
36 | for (size_t j = prev_offset; j < offsets[i] - 1; ++j) |
37 | res_data[j] = data[offsets[i] + prev_offset - 2 - j]; |
38 | res_data[offsets[i] - 1] = 0; |
39 | prev_offset = offsets[i]; |
40 | } |
41 | } |
42 | |
43 | static void vector_fixed(const ColumnString::Chars & data, size_t n, ColumnString::Chars & res_data) |
44 | { |
45 | res_data.resize(data.size()); |
46 | size_t size = data.size() / n; |
47 | |
48 | for (size_t i = 0; i < size; ++i) |
49 | for (size_t j = i * n; j < (i + 1) * n; ++j) |
50 | res_data[j] = data[(i * 2 + 1) * n - j - 1]; |
51 | } |
52 | }; |
53 | |
54 | |
55 | class FunctionReverse : public IFunction |
56 | { |
57 | public: |
58 | static constexpr auto name = "reverse" ; |
59 | static FunctionPtr create(const Context &) |
60 | { |
61 | return std::make_shared<FunctionReverse>(); |
62 | } |
63 | |
64 | String getName() const override |
65 | { |
66 | return name; |
67 | } |
68 | |
69 | size_t getNumberOfArguments() const override |
70 | { |
71 | return 1; |
72 | } |
73 | |
74 | bool isInjective(const Block &) override |
75 | { |
76 | return true; |
77 | } |
78 | |
79 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
80 | { |
81 | if (!isStringOrFixedString(arguments[0]) |
82 | && !isArray(arguments[0])) |
83 | throw Exception( |
84 | "Illegal type " + arguments[0]->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); |
85 | |
86 | return arguments[0]; |
87 | } |
88 | |
89 | bool useDefaultImplementationForConstants() const override { return true; } |
90 | |
91 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t) override |
92 | { |
93 | const ColumnPtr column = block.getByPosition(arguments[0]).column; |
94 | if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get())) |
95 | { |
96 | auto col_res = ColumnString::create(); |
97 | ReverseImpl::vector(col->getChars(), col->getOffsets(), col_res->getChars(), col_res->getOffsets()); |
98 | block.getByPosition(result).column = std::move(col_res); |
99 | } |
100 | else if (const ColumnFixedString * col_fixed = checkAndGetColumn<ColumnFixedString>(column.get())) |
101 | { |
102 | auto col_res = ColumnFixedString::create(col_fixed->getN()); |
103 | ReverseImpl::vector_fixed(col_fixed->getChars(), col_fixed->getN(), col_res->getChars()); |
104 | block.getByPosition(result).column = std::move(col_res); |
105 | } |
106 | else |
107 | throw Exception( |
108 | "Illegal column " + block.getByPosition(arguments[0]).column->getName() + " of argument of function " + getName(), |
109 | ErrorCodes::ILLEGAL_COLUMN); |
110 | } |
111 | }; |
112 | |
113 | |
114 | /// Also works with arrays. |
115 | class ReverseOverloadResolver : public IFunctionOverloadResolverImpl |
116 | { |
117 | public: |
118 | static constexpr auto name = "reverse" ; |
119 | static FunctionOverloadResolverImplPtr create(const Context & context) { return std::make_unique<ReverseOverloadResolver>(context); } |
120 | |
121 | explicit ReverseOverloadResolver(const Context & context_) : context(context_) {} |
122 | |
123 | String getName() const override { return name; } |
124 | size_t getNumberOfArguments() const override { return 1; } |
125 | |
126 | FunctionBaseImplPtr build(const ColumnsWithTypeAndName & arguments, const DataTypePtr & return_type) const override |
127 | { |
128 | if (isArray(arguments.at(0).type)) |
129 | return FunctionOverloadResolverAdaptor(FunctionFactory::instance().getImpl("arrayReverse" , context)).buildImpl(arguments); |
130 | else |
131 | return std::make_unique<DefaultFunction>( |
132 | FunctionReverse::create(context), |
133 | ext::map<DataTypes>(arguments, [](const auto & elem) { return elem.type; }), |
134 | return_type); |
135 | } |
136 | |
137 | DataTypePtr getReturnType(const DataTypes & arguments) const override |
138 | { |
139 | return arguments.at(0); |
140 | } |
141 | |
142 | private: |
143 | const Context & context; |
144 | }; |
145 | |
146 | |
147 | void registerFunctionReverse(FunctionFactory & factory) |
148 | { |
149 | factory.registerFunction<ReverseOverloadResolver>(FunctionFactory::CaseInsensitive); |
150 | } |
151 | |
152 | } |
153 | |