ClickHouse

Форк
0
99 строк · 3.5 Кб
1
#include <Interpreters/ActionsDAG.h>
2
#include <Processors/QueryPlan/ExpressionStep.h>
3
#include <Processors/QueryPlan/FillingStep.h>
4
#include <Processors/QueryPlan/Optimizations/Optimizations.h>
5
#include <Processors/QueryPlan/SortingStep.h>
6
#include <Common/Exception.h>
7
#include <DataTypes/IDataType.h>
8

9
namespace DB
10
{
11
namespace ErrorCodes
12
{
13
    extern const int LOGICAL_ERROR;
14
}
15
}
16

17
namespace
18
{
19

20
const DB::DataStream & getChildOutputStream(DB::QueryPlan::Node & node)
21
{
22
    if (node.children.size() != 1)
23
        throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Node \"{}\" is expected to have only one child.", node.step->getName());
24
    return node.children.front()->step->getOutputStream();
25
}
26

27
}
28

29
namespace DB::QueryPlanOptimizations
30
{
31

32
/// This is a check that nodes columns does not have the same name
33
/// This is ok for DAG, but may introduce a bug in a SotringStep cause columns are selected by name.
34
static bool areNodesConvertableToBlock(const ActionsDAG::NodeRawConstPtrs & nodes)
35
{
36
    std::unordered_set<std::string_view> names;
37
    for (const auto & node : nodes)
38
    {
39
        if (!names.emplace(node->result_name).second)
40
            return false;
41
    }
42

43
    return true;
44
}
45

46
size_t tryExecuteFunctionsAfterSorting(QueryPlan::Node * parent_node, QueryPlan::Nodes & nodes)
47
{
48
    if (parent_node->children.size() != 1)
49
        return 0;
50

51
    QueryPlan::Node * child_node = parent_node->children.front();
52

53
    auto & parent_step = parent_node->step;
54
    auto & child_step = child_node->step;
55
    auto * sorting_step = typeid_cast<SortingStep *>(parent_step.get());
56
    auto * expression_step = typeid_cast<ExpressionStep *>(child_step.get());
57

58
    if (!sorting_step || !expression_step)
59
        return 0;
60

61
    // Filling step position should be preserved
62
    if (!child_node->children.empty())
63
        if (typeid_cast<FillingStep *>(child_node->children.front()->step.get()))
64
            return 0;
65

66
    NameSet sort_columns;
67
    for (const auto & col : sorting_step->getSortDescription())
68
        sort_columns.insert(col.column_name);
69
    auto [needed_for_sorting, unneeded_for_sorting, _] = expression_step->getExpression()->splitActionsBySortingDescription(sort_columns);
70

71
    // No calculations can be postponed.
72
    if (unneeded_for_sorting->trivial())
73
        return 0;
74

75
    if (!areNodesConvertableToBlock(needed_for_sorting->getOutputs()) || !areNodesConvertableToBlock(unneeded_for_sorting->getInputs()))
76
        return 0;
77

78
    // Sorting (parent_node) -> Expression (child_node)
79
    auto & node_with_needed = nodes.emplace_back();
80
    std::swap(node_with_needed.children, child_node->children);
81
    child_node->children = {&node_with_needed};
82

83
    node_with_needed.step = std::make_unique<ExpressionStep>(getChildOutputStream(node_with_needed), std::move(needed_for_sorting));
84
    node_with_needed.step->setStepDescription(child_step->getStepDescription());
85
    // Sorting (parent_node) -> so far the origin Expression (child_node) -> NeededCalculations (node_with_needed)
86

87
    std::swap(parent_step, child_step);
88
    // so far the origin Expression (parent_node) -> Sorting (child_node) -> NeededCalculations (node_with_needed)
89

90
    sorting_step->updateInputStream(getChildOutputStream(*child_node));
91

92
    auto description = parent_step->getStepDescription();
93
    parent_step = std::make_unique<DB::ExpressionStep>(child_step->getOutputStream(), std::move(unneeded_for_sorting));
94
    parent_step->setStepDescription(description + " [lifted up part]");
95
    // UneededCalculations (parent_node) -> Sorting (child_node) -> NeededCalculations (node_with_needed)
96

97
    return 3;
98
}
99
}
100

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.