be/src/exprs/function/array/function_array_difference.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <fmt/format.h> |
21 | | #include <glog/logging.h> |
22 | | #include <stddef.h> |
23 | | |
24 | | #include <algorithm> |
25 | | #include <boost/iterator/iterator_facade.hpp> |
26 | | #include <memory> |
27 | | #include <ostream> |
28 | | #include <string> |
29 | | #include <utility> |
30 | | |
31 | | #include "common/status.h" |
32 | | #include "core/assert_cast.h" |
33 | | #include "core/block/block.h" |
34 | | #include "core/block/column_numbers.h" |
35 | | #include "core/block/column_with_type_and_name.h" |
36 | | #include "core/column/column.h" |
37 | | #include "core/column/column_array.h" |
38 | | #include "core/column/column_array_view.h" |
39 | | #include "core/column/column_decimal.h" |
40 | | #include "core/column/column_nullable.h" |
41 | | #include "core/column/column_vector.h" |
42 | | #include "core/data_type/data_type.h" |
43 | | #include "core/data_type/data_type_array.h" |
44 | | #include "core/data_type/data_type_nullable.h" |
45 | | #include "core/data_type/data_type_number.h" |
46 | | #include "core/types.h" |
47 | | #include "exec/common/util.hpp" |
48 | | #include "exprs/aggregate/aggregate_function.h" |
49 | | #include "exprs/function/function.h" |
50 | | |
51 | | namespace doris { |
52 | | class FunctionContext; |
53 | | } // namespace doris |
54 | | |
55 | | namespace doris { |
56 | | |
57 | | class FunctionArrayDifference : public IFunction { |
58 | | public: |
59 | | static constexpr auto name = "array_difference"; |
60 | | |
61 | 2 | static FunctionPtr create() { return std::make_shared<FunctionArrayDifference>(); } |
62 | | |
63 | 1 | String get_name() const override { return name; } |
64 | | |
65 | 1 | bool is_variadic() const override { return false; } |
66 | | |
67 | 0 | size_t get_number_of_arguments() const override { return 1; } |
68 | | |
69 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
70 | 0 | DCHECK(arguments[0]->get_primitive_type() == TYPE_ARRAY) |
71 | 0 | << "argument for function: " << name << " should be DataTypeArray but it has type " |
72 | 0 | << arguments[0]->get_name() << "."; |
73 | 0 | auto nested_type = assert_cast<const DataTypeArray&>(*(arguments[0])).get_nested_type(); |
74 | 0 | bool is_nullable = nested_type->is_nullable(); |
75 | | |
76 | | //return type is promoted to prevent result overflow |
77 | | //like: input is int32 ---> return type will be int64 |
78 | 0 | DataTypePtr return_type = nullptr; |
79 | 0 | switch (nested_type->get_primitive_type()) { |
80 | 0 | case TYPE_BOOLEAN: |
81 | 0 | case TYPE_TINYINT: |
82 | 0 | return_type = std::make_shared<DataTypeInt16>(); |
83 | 0 | break; |
84 | 0 | case TYPE_SMALLINT: |
85 | 0 | return_type = std::make_shared<DataTypeInt32>(); |
86 | 0 | break; |
87 | 0 | case TYPE_INT: |
88 | 0 | return_type = std::make_shared<DataTypeInt64>(); |
89 | 0 | break; |
90 | 0 | case TYPE_BIGINT: |
91 | 0 | case TYPE_LARGEINT: |
92 | 0 | return_type = std::make_shared<DataTypeInt128>(); |
93 | 0 | break; |
94 | 0 | case TYPE_FLOAT: |
95 | 0 | case TYPE_DOUBLE: |
96 | 0 | return_type = std::make_shared<DataTypeFloat64>(); |
97 | 0 | break; |
98 | 0 | case TYPE_DECIMAL32: |
99 | 0 | case TYPE_DECIMAL64: |
100 | 0 | case TYPE_DECIMALV2: |
101 | 0 | case TYPE_DECIMAL128I: |
102 | 0 | case TYPE_DECIMAL256: |
103 | 0 | return arguments[0]; |
104 | 0 | default: |
105 | 0 | break; |
106 | 0 | } |
107 | 0 | if (return_type) { |
108 | 0 | return std::make_shared<DataTypeArray>(is_nullable ? make_nullable(return_type) |
109 | 0 | : return_type); |
110 | 0 | } |
111 | 0 | throw doris::Exception(ErrorCode::INVALID_ARGUMENT, |
112 | 0 | "Function of {}, return type get wrong: and input argument is: {}", |
113 | 0 | name, arguments[0]->get_name()); |
114 | 0 | } |
115 | | |
116 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
117 | 0 | uint32_t result, size_t input_rows_count) const override { |
118 | 0 | const ColumnWithTypeAndName& arg = block.get_by_position(arguments[0]); |
119 | 0 | auto res_column = _execute_non_nullable(arg, input_rows_count); |
120 | 0 | if (!res_column) { |
121 | 0 | return Status::RuntimeError( |
122 | 0 | fmt::format("unsupported types for function {}({})", get_name(), |
123 | 0 | block.get_by_position(arguments[0]).type->get_name())); |
124 | 0 | } |
125 | 0 | DCHECK_EQ(arg.column->size(), res_column->size()); |
126 | 0 | block.replace_by_position(result, std::move(res_column)); |
127 | 0 | return Status::OK(); |
128 | 0 | } |
129 | | |
130 | | private: |
131 | | template <typename Element, typename Result> |
132 | | NO_SANITIZE_UNDEFINED static void impl(const Element* __restrict src, Result* __restrict dst, |
133 | 0 | size_t begin, size_t end) { |
134 | 0 | if (begin < end) { |
135 | 0 | Element prev_element = src[begin]; |
136 | 0 | dst[begin] = {}; |
137 | 0 | for (size_t curr_pos = begin + 1; curr_pos < end; ++curr_pos) { |
138 | 0 | Element curr_element = src[curr_pos]; |
139 | 0 | dst[curr_pos] = |
140 | 0 | static_cast<Result>(curr_element) - static_cast<Result>(prev_element); |
141 | 0 | prev_element = curr_element; |
142 | 0 | } |
143 | 0 | } |
144 | 0 | } Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIhsEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIasEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIsiEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIilEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIlnEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implInnEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIfdEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implIddEEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implINS_7DecimalIiEES3_EEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implINS_7DecimalIlEES3_EEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implINS_12Decimal128V3ES2_EEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implINS_14DecimalV2ValueES2_EEvPKT_PT0_mm Unexecuted instantiation: _ZN5doris23FunctionArrayDifference4implINS_7DecimalIN4wide7integerILm256EiEEEES6_EEvPKT_PT0_mm |
145 | | |
146 | | template <PrimitiveType Element, PrimitiveType Result> |
147 | 0 | ColumnPtr _execute_number_expanded(const ColumnArrayView<Element>& array_view) const { |
148 | 0 | using ColVecResult = typename PrimitiveTypeTraits<Result>::ColumnType; |
149 | 0 | typename ColVecResult::MutablePtr res_nested = nullptr; |
150 | |
|
151 | 0 | const auto& src_data = array_view.element_data.data; |
152 | 0 | if constexpr (is_decimal(Result)) { |
153 | 0 | res_nested = ColVecResult::create(0, src_data.get_scale()); |
154 | 0 | } else { |
155 | 0 | res_nested = ColVecResult::create(); |
156 | 0 | } |
157 | 0 | auto size = array_view.element_data.size(); |
158 | 0 | typename ColVecResult::Container& res_values = res_nested->get_data(); |
159 | 0 | res_values.resize(size); |
160 | |
|
161 | 0 | size_t pos = 0; |
162 | 0 | for (auto offset : array_view.offsets) { |
163 | 0 | impl(src_data.data(), res_values.data(), pos, offset); |
164 | 0 | pos = offset; |
165 | 0 | } |
166 | 0 | auto null_map_col = ColumnUInt8::create(size, 0); |
167 | 0 | auto& null_map_col_data = null_map_col->get_data(); |
168 | 0 | VectorizedUtils::update_null_map(null_map_col_data, array_view.nested_null_map); |
169 | 0 | for (size_t row = 0; row < array_view.offsets.size(); ++row) { |
170 | 0 | auto off = array_view.offsets[row - 1]; |
171 | 0 | auto len = array_view.offsets[row] - off; |
172 | 0 | auto nested_pos = len ? len - 1 : 0; |
173 | 0 | for (; nested_pos > 0; --nested_pos) { |
174 | 0 | if (null_map_col_data[nested_pos + off - 1]) { |
175 | 0 | null_map_col_data[nested_pos + off] = 1; |
176 | 0 | } |
177 | 0 | } |
178 | 0 | } |
179 | 0 | return ColumnNullable::create(std::move(res_nested), std::move(null_map_col)); |
180 | 0 | } Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE2ELS2_4EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE3ELS2_4EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE4ELS2_5EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE5ELS2_6EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE6ELS2_7EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE7ELS2_7EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE8ELS2_9EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE9ELS2_9EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE28ELS2_28EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE29ELS2_29EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE30ELS2_30EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE20ELS2_20EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE Unexecuted instantiation: _ZNK5doris23FunctionArrayDifference24_execute_number_expandedILNS_13PrimitiveTypeE35ELS2_35EEENS_3COWINS_7IColumnEE13immutable_ptrIS4_EERKNS_15ColumnArrayViewIXT_EEE |
181 | | |
182 | | ColumnPtr _execute_non_nullable(const ColumnWithTypeAndName& arg, |
183 | 0 | size_t input_rows_count) const { |
184 | | // check array nested column type and get data |
185 | 0 | auto left_column = arg.column->convert_to_full_column_if_const(); |
186 | 0 | const auto& array_column = reinterpret_cast<const ColumnArray&>(*left_column); |
187 | 0 | const auto& offsets = array_column.get_offsets(); |
188 | 0 | DCHECK(offsets.size() == input_rows_count); |
189 | |
|
190 | 0 | ColumnPtr res = nullptr; |
191 | 0 | auto left_element_type = |
192 | 0 | remove_nullable(assert_cast<const DataTypeArray&>(*arg.type).get_nested_type()); |
193 | 0 | switch (left_element_type->get_primitive_type()) { |
194 | 0 | case TYPE_BOOLEAN: |
195 | 0 | res = _execute_number_expanded<TYPE_BOOLEAN, TYPE_SMALLINT>( |
196 | 0 | ColumnArrayView<TYPE_BOOLEAN>::create(left_column)); |
197 | 0 | break; |
198 | 0 | case TYPE_TINYINT: |
199 | 0 | res = _execute_number_expanded<TYPE_TINYINT, TYPE_SMALLINT>( |
200 | 0 | ColumnArrayView<TYPE_TINYINT>::create(left_column)); |
201 | 0 | break; |
202 | 0 | case TYPE_SMALLINT: |
203 | 0 | res = _execute_number_expanded<TYPE_SMALLINT, TYPE_INT>( |
204 | 0 | ColumnArrayView<TYPE_SMALLINT>::create(left_column)); |
205 | 0 | break; |
206 | 0 | case TYPE_INT: |
207 | 0 | res = _execute_number_expanded<TYPE_INT, TYPE_BIGINT>( |
208 | 0 | ColumnArrayView<TYPE_INT>::create(left_column)); |
209 | 0 | break; |
210 | 0 | case TYPE_BIGINT: |
211 | 0 | res = _execute_number_expanded<TYPE_BIGINT, TYPE_LARGEINT>( |
212 | 0 | ColumnArrayView<TYPE_BIGINT>::create(left_column)); |
213 | 0 | break; |
214 | 0 | case TYPE_LARGEINT: |
215 | 0 | res = _execute_number_expanded<TYPE_LARGEINT, TYPE_LARGEINT>( |
216 | 0 | ColumnArrayView<TYPE_LARGEINT>::create(left_column)); |
217 | 0 | break; |
218 | 0 | case TYPE_FLOAT: |
219 | 0 | res = _execute_number_expanded<TYPE_FLOAT, TYPE_DOUBLE>( |
220 | 0 | ColumnArrayView<TYPE_FLOAT>::create(left_column)); |
221 | 0 | break; |
222 | 0 | case TYPE_DOUBLE: |
223 | 0 | res = _execute_number_expanded<TYPE_DOUBLE, TYPE_DOUBLE>( |
224 | 0 | ColumnArrayView<TYPE_DOUBLE>::create(left_column)); |
225 | 0 | break; |
226 | 0 | case TYPE_DECIMAL32: |
227 | 0 | res = _execute_number_expanded<TYPE_DECIMAL32, TYPE_DECIMAL32>( |
228 | 0 | ColumnArrayView<TYPE_DECIMAL32>::create(left_column)); |
229 | 0 | break; |
230 | 0 | case TYPE_DECIMAL64: |
231 | 0 | res = _execute_number_expanded<TYPE_DECIMAL64, TYPE_DECIMAL64>( |
232 | 0 | ColumnArrayView<TYPE_DECIMAL64>::create(left_column)); |
233 | 0 | break; |
234 | 0 | case TYPE_DECIMAL128I: |
235 | 0 | res = _execute_number_expanded<TYPE_DECIMAL128I, TYPE_DECIMAL128I>( |
236 | 0 | ColumnArrayView<TYPE_DECIMAL128I>::create(left_column)); |
237 | 0 | break; |
238 | 0 | case TYPE_DECIMALV2: |
239 | 0 | res = _execute_number_expanded<TYPE_DECIMALV2, TYPE_DECIMALV2>( |
240 | 0 | ColumnArrayView<TYPE_DECIMALV2>::create(left_column)); |
241 | 0 | break; |
242 | 0 | case TYPE_DECIMAL256: |
243 | 0 | res = _execute_number_expanded<TYPE_DECIMAL256, TYPE_DECIMAL256>( |
244 | 0 | ColumnArrayView<TYPE_DECIMAL256>::create(left_column)); |
245 | 0 | break; |
246 | 0 | default: |
247 | 0 | return nullptr; |
248 | 0 | } |
249 | 0 | return ColumnArray::create(res, array_column.get_offsets_ptr()); |
250 | 0 | } |
251 | | }; |
252 | | |
253 | | } // namespace doris |