| 40 | }; |
| 41 | |
| 42 | static SortingProperty applyOrder(QueryPlan::Node * parent, SortingProperty * properties, const QueryPlanOptimizationSettings & optimization_settings) |
| 43 | { |
| 44 | if (const auto * read_from_merge_tree = typeid_cast<ReadFromMergeTree *>(parent->step.get())) |
| 45 | return {read_from_merge_tree->getSortDescription(), SortingProperty::SortScope::Stream}; |
| 46 | |
| 47 | if (const auto * aggregating_step = typeid_cast<AggregatingStep *>(parent->step.get())) |
| 48 | { |
| 49 | /// TODO: here we can apply aggregation-in-order after some sorting. |
| 50 | |
| 51 | auto sort_description = aggregating_step->getSortDescription(); |
| 52 | if (!sort_description.empty()) |
| 53 | return {std::move(sort_description), SortingProperty::SortScope::Global}; |
| 54 | } |
| 55 | |
| 56 | if (auto * mergine_aggeregated = typeid_cast<MergingAggregatedStep *>(parent->step.get())) |
| 57 | { |
| 58 | enableMemoryBoundMerging(*parent); |
| 59 | |
| 60 | auto sort_description = mergine_aggeregated->getSortDescription(); |
| 61 | if (!sort_description.empty()) |
| 62 | return {std::move(sort_description), SortingProperty::SortScope::Global}; |
| 63 | } |
| 64 | |
| 65 | if (auto * distinct_step = typeid_cast<DistinctStep *>(parent->step.get())) |
| 66 | { |
| 67 | /// Do not apply distinct-in-order second time. |
| 68 | /// Also, prefer sorting from propertires against Distinct sorting description, |
| 69 | /// cause the last one might be shorter, or may haver additional monotonic functions. |
| 70 | if (optimization_settings.distinct_in_order && distinct_step->getSortDescription().empty() && |
| 71 | (properties->sort_scope == SortingProperty::SortScope::Global |
| 72 | || (distinct_step->isPreliminary() && properties->sort_scope == SortingProperty::SortScope::Stream))) |
| 73 | { |
| 74 | distinct_step->applyOrder(getCollationAwareSortPrefixInColumns(properties->sort_description, distinct_step->getColumnNames())); |
| 75 | } |
| 76 | |
| 77 | /// Distinct never breaks global order |
| 78 | if (properties->sort_scope == SortingProperty::SortScope::Global) |
| 79 | return *properties; |
| 80 | |
| 81 | /// Preliminary Distinct also does not break stream order |
| 82 | if (distinct_step->isPreliminary() && properties->sort_scope == SortingProperty::SortScope::Stream) |
| 83 | return *properties; |
| 84 | } |
| 85 | |
| 86 | if (auto * expression_step = typeid_cast<ExpressionStep *>(parent->step.get())) |
| 87 | { |
| 88 | applyActionsToSortDescription(properties->sort_description, expression_step->getExpression()); |
| 89 | return std::move(*properties); |
| 90 | } |
| 91 | |
| 92 | if (auto * filter_step = typeid_cast<FilterStep *>(parent->step.get())) |
| 93 | { |
| 94 | const auto & expr = filter_step->getExpression(); |
| 95 | const ActionsDAG::Node * out_to_skip = nullptr; |
| 96 | if (filter_step->removesFilterColumn()) |
| 97 | { |
| 98 | out_to_skip = expr.tryFindInOutputs(filter_step->getFilterColumnName()); |
| 99 | if (!out_to_skip) |
no test coverage detected