1#include <Storages/ReadInOrderOptimizer.h>
2#include <Storages/MergeTree/MergeTreeData.h>
3#include <Interpreters/AnalyzedJoin.h>
4#include <Functions/IFunction.h>
5
6namespace DB
7{
8
9namespace ErrorCodes
10{
11 extern const int LOGICAL_ERROR;
12}
13
14
15ReadInOrderOptimizer::ReadInOrderOptimizer(
16 const ManyExpressionActions & elements_actions_,
17 const SortDescription & required_sort_description_,
18 const SyntaxAnalyzerResultPtr & syntax_result)
19 : elements_actions(elements_actions_)
20 , required_sort_description(required_sort_description_)
21{
22 if (elements_actions.size() != required_sort_description.size())
23 throw Exception("Sizes of sort description and actions are mismatched", ErrorCodes::LOGICAL_ERROR);
24
25 /// Do not analyze joined columns.
26 /// They may have aliases and come to descriprion as is.
27 /// We can mismatch them with order key columns at stage of fetching columns.
28 for (const auto & elem : syntax_result->array_join_result_to_source)
29 forbidden_columns.insert(elem.first);
30}
31
32InputSortingInfoPtr ReadInOrderOptimizer::getInputOrder(const StoragePtr & storage) const
33{
34 const MergeTreeData * merge_tree = dynamic_cast<const MergeTreeData *>(storage.get());
35 if (!merge_tree || !merge_tree->hasSortingKey())
36 return {};
37
38 SortDescription order_key_prefix_descr;
39 int read_direction = required_sort_description.at(0).direction;
40
41 const auto & sorting_key_columns = merge_tree->getSortingKeyColumns();
42 size_t prefix_size = std::min(required_sort_description.size(), sorting_key_columns.size());
43
44 for (size_t i = 0; i < prefix_size; ++i)
45 {
46 if (forbidden_columns.count(required_sort_description[i].column_name))
47 break;
48
49 /// Optimize in case of exact match with order key element
50 /// or in some simple cases when order key element is wrapped into monotonic function.
51 int current_direction = required_sort_description[i].direction;
52 if (required_sort_description[i].column_name == sorting_key_columns[i] && current_direction == read_direction)
53 order_key_prefix_descr.push_back(required_sort_description[i]);
54 else
55 {
56 /// Allow only one simple monotonic functions with one argument
57 bool found_function = false;
58 for (const auto & action : elements_actions[i]->getActions())
59 {
60 if (action.type != ExpressionAction::APPLY_FUNCTION)
61 continue;
62
63 if (found_function)
64 {
65 current_direction = 0;
66 break;
67 }
68 else
69 found_function = true;
70
71 if (action.argument_names.size() != 1 || action.argument_names.at(0) != sorting_key_columns[i])
72 {
73 current_direction = 0;
74 break;
75 }
76
77 const auto & func = *action.function_base;
78 if (!func.hasInformationAboutMonotonicity())
79 {
80 current_direction = 0;
81 break;
82 }
83
84 auto monotonicity = func.getMonotonicityForRange(*func.getArgumentTypes().at(0), {}, {});
85 if (!monotonicity.is_monotonic)
86 {
87 current_direction = 0;
88 break;
89 }
90 else if (!monotonicity.is_positive)
91 current_direction *= -1;
92 }
93
94 if (!found_function)
95 current_direction = 0;
96
97 if (!current_direction || (i > 0 && current_direction != read_direction))
98 break;
99
100 if (i == 0)
101 read_direction = current_direction;
102
103 order_key_prefix_descr.push_back(required_sort_description[i]);
104 }
105 }
106
107 if (order_key_prefix_descr.empty())
108 return {};
109
110 return std::make_shared<InputSortingInfo>(std::move(order_key_prefix_descr), read_direction);
111}
112
113}
114