ClickHouse
67 строк · 2.7 Кб
1#include <Processors/QueryPlan/Optimizations/Optimizations.h>
2#include <Processors/QueryPlan/FilterStep.h>
3#include <Processors/QueryPlan/ExpressionStep.h>
4#include <Interpreters/ActionsDAG.h>
5
6namespace DB::QueryPlanOptimizations
7{
8
9size_t tryMergeExpressions(QueryPlan::Node * parent_node, QueryPlan::Nodes &)
10{
11if (parent_node->children.size() != 1)
12return false;
13
14QueryPlan::Node * child_node = parent_node->children.front();
15
16auto & parent = parent_node->step;
17auto & child = child_node->step;
18
19auto * parent_expr = typeid_cast<ExpressionStep *>(parent.get());
20auto * parent_filter = typeid_cast<FilterStep *>(parent.get());
21auto * child_expr = typeid_cast<ExpressionStep *>(child.get());
22
23if (parent_expr && child_expr)
24{
25const auto & child_actions = child_expr->getExpression();
26const auto & parent_actions = parent_expr->getExpression();
27
28/// We cannot combine actions with arrayJoin and stateful function because we not always can reorder them.
29/// Example: select rowNumberInBlock() from (select arrayJoin([1, 2]))
30/// Such a query will return two zeroes if we combine actions together.
31if (child_actions->hasArrayJoin() && parent_actions->hasStatefulFunctions())
32return 0;
33
34auto merged = ActionsDAG::merge(std::move(*child_actions), std::move(*parent_actions));
35
36auto expr = std::make_unique<ExpressionStep>(child_expr->getInputStreams().front(), merged);
37expr->setStepDescription("(" + parent_expr->getStepDescription() + " + " + child_expr->getStepDescription() + ")");
38
39parent_node->step = std::move(expr);
40parent_node->children.swap(child_node->children);
41return 1;
42}
43else if (parent_filter && child_expr)
44{
45const auto & child_actions = child_expr->getExpression();
46const auto & parent_actions = parent_filter->getExpression();
47
48if (child_actions->hasArrayJoin() && parent_actions->hasStatefulFunctions())
49return 0;
50
51auto merged = ActionsDAG::merge(std::move(*child_actions), std::move(*parent_actions));
52
53auto filter = std::make_unique<FilterStep>(child_expr->getInputStreams().front(),
54merged,
55parent_filter->getFilterColumnName(),
56parent_filter->removesFilterColumn());
57filter->setStepDescription("(" + parent_filter->getStepDescription() + " + " + child_expr->getStepDescription() + ")");
58
59parent_node->step = std::move(filter);
60parent_node->children.swap(child_node->children);
61return 1;
62}
63
64return 0;
65}
66
67}
68