1 | #include <Columns/ColumnTuple.h> |
2 | #include <DataStreams/ColumnGathererStream.h> |
3 | #include <IO/WriteBufferFromString.h> |
4 | #include <IO/Operators.h> |
5 | #include <ext/map.h> |
6 | #include <ext/range.h> |
7 | #include <Common/typeid_cast.h> |
8 | #include <Common/assert_cast.h> |
9 | #include <Core/Field.h> |
10 | |
11 | |
12 | namespace DB |
13 | { |
14 | |
15 | namespace ErrorCodes |
16 | { |
17 | extern const int ILLEGAL_COLUMN; |
18 | extern const int NOT_IMPLEMENTED; |
19 | extern const int CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE; |
20 | } |
21 | |
22 | |
23 | std::string ColumnTuple::getName() const |
24 | { |
25 | WriteBufferFromOwnString res; |
26 | res << "Tuple(" ; |
27 | bool is_first = true; |
28 | for (const auto & column : columns) |
29 | { |
30 | if (!is_first) |
31 | res << ", " ; |
32 | is_first = false; |
33 | res << column->getName(); |
34 | } |
35 | res << ")" ; |
36 | return res.str(); |
37 | } |
38 | |
39 | ColumnTuple::ColumnTuple(MutableColumns && mutable_columns) |
40 | { |
41 | columns.reserve(mutable_columns.size()); |
42 | for (auto & column : mutable_columns) |
43 | { |
44 | if (isColumnConst(*column)) |
45 | throw Exception{"ColumnTuple cannot have ColumnConst as its element" , ErrorCodes::ILLEGAL_COLUMN}; |
46 | |
47 | columns.push_back(std::move(column)); |
48 | } |
49 | } |
50 | |
51 | ColumnTuple::Ptr ColumnTuple::create(const Columns & columns) |
52 | { |
53 | for (const auto & column : columns) |
54 | if (isColumnConst(*column)) |
55 | throw Exception{"ColumnTuple cannot have ColumnConst as its element" , ErrorCodes::ILLEGAL_COLUMN}; |
56 | |
57 | auto column_tuple = ColumnTuple::create(MutableColumns()); |
58 | column_tuple->columns.assign(columns.begin(), columns.end()); |
59 | |
60 | return column_tuple; |
61 | } |
62 | |
63 | ColumnTuple::Ptr ColumnTuple::create(const TupleColumns & columns) |
64 | { |
65 | for (const auto & column : columns) |
66 | if (isColumnConst(*column)) |
67 | throw Exception{"ColumnTuple cannot have ColumnConst as its element" , ErrorCodes::ILLEGAL_COLUMN}; |
68 | |
69 | auto column_tuple = ColumnTuple::create(MutableColumns()); |
70 | column_tuple->columns = columns; |
71 | |
72 | return column_tuple; |
73 | } |
74 | |
75 | MutableColumnPtr ColumnTuple::cloneEmpty() const |
76 | { |
77 | const size_t tuple_size = columns.size(); |
78 | MutableColumns new_columns(tuple_size); |
79 | for (size_t i = 0; i < tuple_size; ++i) |
80 | new_columns[i] = columns[i]->cloneEmpty(); |
81 | |
82 | return ColumnTuple::create(std::move(new_columns)); |
83 | } |
84 | |
85 | MutableColumnPtr ColumnTuple::cloneResized(size_t new_size) const |
86 | { |
87 | const size_t tuple_size = columns.size(); |
88 | MutableColumns new_columns(tuple_size); |
89 | for (size_t i = 0; i < tuple_size; ++i) |
90 | new_columns[i] = columns[i]->cloneResized(new_size); |
91 | |
92 | return ColumnTuple::create(std::move(new_columns)); |
93 | } |
94 | |
95 | Field ColumnTuple::operator[](size_t n) const |
96 | { |
97 | return ext::map<Tuple>(columns, [n] (const auto & column) { return (*column)[n]; }); |
98 | } |
99 | |
100 | void ColumnTuple::get(size_t n, Field & res) const |
101 | { |
102 | const size_t tuple_size = columns.size(); |
103 | Tuple tuple(tuple_size); |
104 | for (const auto i : ext::range(0, tuple_size)) |
105 | columns[i]->get(n, tuple[i]); |
106 | |
107 | res = tuple; |
108 | } |
109 | |
110 | StringRef ColumnTuple::getDataAt(size_t) const |
111 | { |
112 | throw Exception("Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); |
113 | } |
114 | |
115 | void ColumnTuple::insertData(const char *, size_t) |
116 | { |
117 | throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); |
118 | } |
119 | |
120 | void ColumnTuple::insert(const Field & x) |
121 | { |
122 | auto & tuple = DB::get<const Tuple &>(x); |
123 | |
124 | const size_t tuple_size = columns.size(); |
125 | if (tuple.size() != tuple_size) |
126 | throw Exception("Cannot insert value of different size into tuple" , ErrorCodes::CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE); |
127 | |
128 | for (size_t i = 0; i < tuple_size; ++i) |
129 | columns[i]->insert(tuple[i]); |
130 | } |
131 | |
132 | void ColumnTuple::insertFrom(const IColumn & src_, size_t n) |
133 | { |
134 | const ColumnTuple & src = assert_cast<const ColumnTuple &>(src_); |
135 | |
136 | const size_t tuple_size = columns.size(); |
137 | if (src.columns.size() != tuple_size) |
138 | throw Exception("Cannot insert value of different size into tuple" , ErrorCodes::CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE); |
139 | |
140 | for (size_t i = 0; i < tuple_size; ++i) |
141 | columns[i]->insertFrom(*src.columns[i], n); |
142 | } |
143 | |
144 | void ColumnTuple::insertDefault() |
145 | { |
146 | for (auto & column : columns) |
147 | column->insertDefault(); |
148 | } |
149 | |
150 | void ColumnTuple::popBack(size_t n) |
151 | { |
152 | for (auto & column : columns) |
153 | column->popBack(n); |
154 | } |
155 | |
156 | StringRef ColumnTuple::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const |
157 | { |
158 | StringRef res(begin, 0); |
159 | for (auto & column : columns) |
160 | { |
161 | auto value_ref = column->serializeValueIntoArena(n, arena, begin); |
162 | res.data = value_ref.data - res.size; |
163 | res.size += value_ref.size; |
164 | } |
165 | |
166 | return res; |
167 | } |
168 | |
169 | const char * ColumnTuple::deserializeAndInsertFromArena(const char * pos) |
170 | { |
171 | for (auto & column : columns) |
172 | pos = column->deserializeAndInsertFromArena(pos); |
173 | |
174 | return pos; |
175 | } |
176 | |
177 | void ColumnTuple::updateHashWithValue(size_t n, SipHash & hash) const |
178 | { |
179 | for (auto & column : columns) |
180 | column->updateHashWithValue(n, hash); |
181 | } |
182 | |
183 | void ColumnTuple::insertRangeFrom(const IColumn & src, size_t start, size_t length) |
184 | { |
185 | const size_t tuple_size = columns.size(); |
186 | for (size_t i = 0; i < tuple_size; ++i) |
187 | columns[i]->insertRangeFrom( |
188 | *assert_cast<const ColumnTuple &>(src).columns[i], |
189 | start, length); |
190 | } |
191 | |
192 | ColumnPtr ColumnTuple::filter(const Filter & filt, ssize_t result_size_hint) const |
193 | { |
194 | const size_t tuple_size = columns.size(); |
195 | Columns new_columns(tuple_size); |
196 | |
197 | for (size_t i = 0; i < tuple_size; ++i) |
198 | new_columns[i] = columns[i]->filter(filt, result_size_hint); |
199 | |
200 | return ColumnTuple::create(new_columns); |
201 | } |
202 | |
203 | ColumnPtr ColumnTuple::permute(const Permutation & perm, size_t limit) const |
204 | { |
205 | const size_t tuple_size = columns.size(); |
206 | Columns new_columns(tuple_size); |
207 | |
208 | for (size_t i = 0; i < tuple_size; ++i) |
209 | new_columns[i] = columns[i]->permute(perm, limit); |
210 | |
211 | return ColumnTuple::create(new_columns); |
212 | } |
213 | |
214 | ColumnPtr ColumnTuple::index(const IColumn & indexes, size_t limit) const |
215 | { |
216 | const size_t tuple_size = columns.size(); |
217 | Columns new_columns(tuple_size); |
218 | |
219 | for (size_t i = 0; i < tuple_size; ++i) |
220 | new_columns[i] = columns[i]->index(indexes, limit); |
221 | |
222 | return ColumnTuple::create(new_columns); |
223 | } |
224 | |
225 | ColumnPtr ColumnTuple::replicate(const Offsets & offsets) const |
226 | { |
227 | const size_t tuple_size = columns.size(); |
228 | Columns new_columns(tuple_size); |
229 | |
230 | for (size_t i = 0; i < tuple_size; ++i) |
231 | new_columns[i] = columns[i]->replicate(offsets); |
232 | |
233 | return ColumnTuple::create(new_columns); |
234 | } |
235 | |
236 | MutableColumns ColumnTuple::scatter(ColumnIndex num_columns, const Selector & selector) const |
237 | { |
238 | const size_t tuple_size = columns.size(); |
239 | std::vector<MutableColumns> scattered_tuple_elements(tuple_size); |
240 | |
241 | for (size_t tuple_element_idx = 0; tuple_element_idx < tuple_size; ++tuple_element_idx) |
242 | scattered_tuple_elements[tuple_element_idx] = columns[tuple_element_idx]->scatter(num_columns, selector); |
243 | |
244 | MutableColumns res(num_columns); |
245 | |
246 | for (size_t scattered_idx = 0; scattered_idx < num_columns; ++scattered_idx) |
247 | { |
248 | MutableColumns new_columns(tuple_size); |
249 | for (size_t tuple_element_idx = 0; tuple_element_idx < tuple_size; ++tuple_element_idx) |
250 | new_columns[tuple_element_idx] = std::move(scattered_tuple_elements[tuple_element_idx][scattered_idx]); |
251 | res[scattered_idx] = ColumnTuple::create(std::move(new_columns)); |
252 | } |
253 | |
254 | return res; |
255 | } |
256 | |
257 | int ColumnTuple::compareAt(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint) const |
258 | { |
259 | const size_t tuple_size = columns.size(); |
260 | for (size_t i = 0; i < tuple_size; ++i) |
261 | if (int res = columns[i]->compareAt(n, m, *assert_cast<const ColumnTuple &>(rhs).columns[i], nan_direction_hint)) |
262 | return res; |
263 | |
264 | return 0; |
265 | } |
266 | |
267 | template <bool positive> |
268 | struct ColumnTuple::Less |
269 | { |
270 | TupleColumns columns; |
271 | int nan_direction_hint; |
272 | |
273 | Less(const TupleColumns & columns_, int nan_direction_hint_) |
274 | : columns(columns_), nan_direction_hint(nan_direction_hint_) |
275 | { |
276 | } |
277 | |
278 | bool operator() (size_t a, size_t b) const |
279 | { |
280 | for (const auto & column : columns) |
281 | { |
282 | int res = column->compareAt(a, b, *column, nan_direction_hint); |
283 | if (res < 0) |
284 | return positive; |
285 | else if (res > 0) |
286 | return !positive; |
287 | } |
288 | return false; |
289 | } |
290 | }; |
291 | |
292 | void ColumnTuple::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const |
293 | { |
294 | size_t rows = size(); |
295 | res.resize(rows); |
296 | for (size_t i = 0; i < rows; ++i) |
297 | res[i] = i; |
298 | |
299 | if (limit >= rows) |
300 | limit = 0; |
301 | |
302 | if (limit) |
303 | { |
304 | if (reverse) |
305 | std::partial_sort(res.begin(), res.begin() + limit, res.end(), Less<false>(columns, nan_direction_hint)); |
306 | else |
307 | std::partial_sort(res.begin(), res.begin() + limit, res.end(), Less<true>(columns, nan_direction_hint)); |
308 | } |
309 | else |
310 | { |
311 | if (reverse) |
312 | std::sort(res.begin(), res.end(), Less<false>(columns, nan_direction_hint)); |
313 | else |
314 | std::sort(res.begin(), res.end(), Less<true>(columns, nan_direction_hint)); |
315 | } |
316 | } |
317 | |
318 | void ColumnTuple::gather(ColumnGathererStream & gatherer) |
319 | { |
320 | gatherer.gather(*this); |
321 | } |
322 | |
323 | void ColumnTuple::reserve(size_t n) |
324 | { |
325 | const size_t tuple_size = columns.size(); |
326 | for (size_t i = 0; i < tuple_size; ++i) |
327 | getColumn(i).reserve(n); |
328 | } |
329 | |
330 | size_t ColumnTuple::byteSize() const |
331 | { |
332 | size_t res = 0; |
333 | for (const auto & column : columns) |
334 | res += column->byteSize(); |
335 | return res; |
336 | } |
337 | |
338 | size_t ColumnTuple::allocatedBytes() const |
339 | { |
340 | size_t res = 0; |
341 | for (const auto & column : columns) |
342 | res += column->allocatedBytes(); |
343 | return res; |
344 | } |
345 | |
346 | void ColumnTuple::protect() |
347 | { |
348 | for (auto & column : columns) |
349 | column->protect(); |
350 | } |
351 | |
352 | void ColumnTuple::getExtremes(Field & min, Field & max) const |
353 | { |
354 | const size_t tuple_size = columns.size(); |
355 | |
356 | Tuple min_tuple(tuple_size); |
357 | Tuple max_tuple(tuple_size); |
358 | |
359 | for (const auto i : ext::range(0, tuple_size)) |
360 | columns[i]->getExtremes(min_tuple[i], max_tuple[i]); |
361 | |
362 | min = min_tuple; |
363 | max = max_tuple; |
364 | } |
365 | |
366 | void ColumnTuple::forEachSubcolumn(ColumnCallback callback) |
367 | { |
368 | for (auto & column : columns) |
369 | callback(column); |
370 | } |
371 | |
372 | bool ColumnTuple::structureEquals(const IColumn & rhs) const |
373 | { |
374 | if (auto rhs_tuple = typeid_cast<const ColumnTuple *>(&rhs)) |
375 | { |
376 | const size_t tuple_size = columns.size(); |
377 | if (tuple_size != rhs_tuple->columns.size()) |
378 | return false; |
379 | |
380 | for (const auto i : ext::range(0, tuple_size)) |
381 | if (!columns[i]->structureEquals(*rhs_tuple->columns[i])) |
382 | return false; |
383 | |
384 | return true; |
385 | } |
386 | else |
387 | return false; |
388 | } |
389 | |
390 | |
391 | } |
392 | |