1 | #include "FunctionArrayMapped.h" |
2 | #include <Functions/FunctionFactory.h> |
3 | |
4 | |
5 | namespace DB |
6 | { |
7 | |
8 | /** Sort arrays, by values of its elements, or by values of corresponding elements of calculated expression (known as "schwartzsort"). |
9 | */ |
10 | template <bool positive> |
11 | struct ArraySortImpl |
12 | { |
13 | static bool needBoolean() { return false; } |
14 | static bool needExpression() { return false; } |
15 | static bool needOneArray() { return false; } |
16 | |
17 | static DataTypePtr getReturnType(const DataTypePtr & /*expression_return*/, const DataTypePtr & array_element) |
18 | { |
19 | return std::make_shared<DataTypeArray>(array_element); |
20 | } |
21 | |
22 | struct Less |
23 | { |
24 | const IColumn & column; |
25 | |
26 | Less(const IColumn & column_) : column(column_) {} |
27 | |
28 | bool operator()(size_t lhs, size_t rhs) const |
29 | { |
30 | if (positive) |
31 | return column.compareAt(lhs, rhs, column, 1) < 0; |
32 | else |
33 | return column.compareAt(lhs, rhs, column, -1) > 0; |
34 | } |
35 | }; |
36 | |
37 | static ColumnPtr execute(const ColumnArray & array, ColumnPtr mapped) |
38 | { |
39 | const ColumnArray::Offsets & offsets = array.getOffsets(); |
40 | |
41 | size_t size = offsets.size(); |
42 | size_t nested_size = array.getData().size(); |
43 | IColumn::Permutation permutation(nested_size); |
44 | |
45 | for (size_t i = 0; i < nested_size; ++i) |
46 | permutation[i] = i; |
47 | |
48 | ColumnArray::Offset current_offset = 0; |
49 | for (size_t i = 0; i < size; ++i) |
50 | { |
51 | auto next_offset = offsets[i]; |
52 | std::sort(&permutation[current_offset], &permutation[next_offset], Less(*mapped)); |
53 | current_offset = next_offset; |
54 | } |
55 | |
56 | return ColumnArray::create(array.getData().permute(permutation, 0), array.getOffsetsPtr()); |
57 | } |
58 | }; |
59 | |
60 | struct NameArraySort { static constexpr auto name = "arraySort" ; }; |
61 | struct NameArrayReverseSort { static constexpr auto name = "arrayReverseSort" ; }; |
62 | |
63 | using FunctionArraySort = FunctionArrayMapped<ArraySortImpl<true>, NameArraySort>; |
64 | using FunctionArrayReverseSort = FunctionArrayMapped<ArraySortImpl<false>, NameArrayReverseSort>; |
65 | |
66 | void registerFunctionsArraySort(FunctionFactory & factory) |
67 | { |
68 | factory.registerFunction<FunctionArraySort>(); |
69 | factory.registerFunction<FunctionArrayReverseSort>(); |
70 | } |
71 | |
72 | } |
73 | |
74 | |