aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Processors/QueryPlan/Optimizations/liftUpUnion.cpp
blob: 35d8b1a35e43368cd2355bebc556641e33c52222 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <Processors/QueryPlan/Optimizations/Optimizations.h>
#include <Processors/QueryPlan/UnionStep.h>
#include <Processors/QueryPlan/ExpressionStep.h>
#include <Interpreters/ActionsDAG.h>

namespace DB::QueryPlanOptimizations
{

size_t tryLiftUpUnion(QueryPlan::Node * parent_node, QueryPlan::Nodes & nodes)
{
    if (parent_node->children.empty())
        return 0;

    QueryPlan::Node * child_node = parent_node->children.front();
    auto & parent = parent_node->step;
    auto & child = child_node->step;

    auto * union_step = typeid_cast<UnionStep *>(child.get());
    if (!union_step)
        return 0;

    if (auto * expression = typeid_cast<ExpressionStep *>(parent.get()))
    {
        /// Union does not change header.
        /// We can push down expression and update header.
        auto union_input_streams = child->getInputStreams();
        for (auto & input_stream : union_input_streams)
            input_stream.header = expression->getOutputStream().header;

        ///                    - Something
        /// Expression - Union - Something
        ///                    - Something

        child = std::make_unique<UnionStep>(union_input_streams, union_step->getMaxThreads());

        std::swap(parent, child);
        std::swap(parent_node->children, child_node->children);
        std::swap(parent_node->children.front(), child_node->children.front());

        ///       - Expression - Something
        /// Union - Something
        ///       - Something

        for (size_t i = 1; i < parent_node->children.size(); ++i)
        {
            auto & expr_node = nodes.emplace_back();
            expr_node.children.push_back(parent_node->children[i]);
            parent_node->children[i] = &expr_node;

            expr_node.step = std::make_unique<ExpressionStep>(
                expr_node.children.front()->step->getOutputStream(),
                expression->getExpression()->clone());
        }

        ///       - Expression - Something
        /// Union - Expression - Something
        ///       - Expression - Something

        return 3;
    }

    return 0;
}

}