Optimize in case of exact match with order key element or in some simple cases when order key element is wrapped into monotonic function.
| 120 | /// Optimize in case of exact match with order key element |
| 121 | /// or in some simple cases when order key element is wrapped into monotonic function. |
| 122 | MatchResult matchSortDescriptionAndKey( |
| 123 | const ExpressionActions::Actions & actions, |
| 124 | const SortColumnDescription & sort_column, |
| 125 | const String & sorting_key_column) |
| 126 | { |
| 127 | /// If required order depend on collation, it cannot be matched with primary key order. |
| 128 | /// Because primary keys cannot have collations. |
| 129 | if (sort_column.collator) |
| 130 | return {}; |
| 131 | |
| 132 | MatchResult result{sort_column.direction, false}; |
| 133 | |
| 134 | /// For the path: order by (sort_column, ...) |
| 135 | if (sort_column.column_name == sorting_key_column) |
| 136 | return result; |
| 137 | |
| 138 | /// For the path: order by (function(sort_column), ...) |
| 139 | /// Allow only one simple monotonic functions with one argument |
| 140 | /// Why not allow multi monotonic functions? |
| 141 | bool found_function = false; |
| 142 | |
| 143 | for (const auto & action : actions) |
| 144 | { |
| 145 | if (action.node->type != ActionsDAG::ActionType::FUNCTION) |
| 146 | continue; |
| 147 | |
| 148 | if (found_function) |
| 149 | return {}; |
| 150 | |
| 151 | found_function = true; |
| 152 | if (action.node->children.size() != 1 || action.node->children.at(0)->result_name != sorting_key_column) |
| 153 | return {}; |
| 154 | |
| 155 | const auto & func = *action.node->function_base; |
| 156 | if (!func.hasInformationAboutMonotonicity()) |
| 157 | return {}; |
| 158 | |
| 159 | auto monotonicity = func.getMonotonicityForRange(*func.getArgumentTypes().at(0), {}, {}); |
| 160 | if (!monotonicity.is_monotonic) |
| 161 | return {}; |
| 162 | |
| 163 | /// If function is not strict monotonic, it can break order |
| 164 | /// if it's not last in the prefix of sort description. |
| 165 | /// E.g. if we have ORDER BY (d, u) -- ('2020-01-01', 1), ('2020-01-02', 0), ('2020-01-03', 1) |
| 166 | /// ORDER BY (toStartOfMonth(d), u) -- ('2020-01-01', 1), ('2020-01-01', 0), ('2020-01-01', 1) |
| 167 | if (!monotonicity.is_strict) |
| 168 | result.is_last_key = true; |
| 169 | |
| 170 | if (!monotonicity.is_positive) |
| 171 | result.direction *= -1; |
| 172 | } |
| 173 | |
| 174 | if (!found_function) |
| 175 | return {}; |
| 176 | |
| 177 | return result; |
| 178 | } |
| 179 |
no test coverage detected