ClickHouse

Форк
0
/
PlannerContext.cpp 
150 строк · 6.2 Кб
1
#include <Planner/PlannerContext.h>
2

3
#include <Analyzer/TableNode.h>
4
#include <Analyzer/ColumnNode.h>
5
#include <Analyzer/ConstantNode.h>
6
#include <Interpreters/Context.h>
7

8
namespace DB
9
{
10

11
namespace ErrorCodes
12
{
13
    extern const int LOGICAL_ERROR;
14
}
15

16
const ColumnIdentifier & GlobalPlannerContext::createColumnIdentifier(const QueryTreeNodePtr & column_node)
17
{
18
    const auto & column_node_typed = column_node->as<ColumnNode &>();
19
    auto column_source_node = column_node_typed.getColumnSource();
20

21
    return createColumnIdentifier(column_node_typed.getColumn(), column_source_node);
22
}
23

24
const ColumnIdentifier & GlobalPlannerContext::createColumnIdentifier(const NameAndTypePair & column, const QueryTreeNodePtr & column_source_node)
25
{
26
    std::string column_identifier;
27

28
    const auto & source_alias = column_source_node->getAlias();
29
    if (!source_alias.empty())
30
        column_identifier = source_alias + "." + column.name;
31
    else
32
        column_identifier = column.name;
33

34
    auto [it, inserted] = column_identifiers.emplace(column_identifier);
35
    if (!inserted)
36
        throw Exception(ErrorCodes::LOGICAL_ERROR, "Column identifier {} is already registered", column_identifier);
37

38
    assert(inserted);
39

40
    return *it;
41
}
42

43
bool GlobalPlannerContext::hasColumnIdentifier(const ColumnIdentifier & column_identifier)
44
{
45
    return column_identifiers.contains(column_identifier);
46
}
47

48
PlannerContext::PlannerContext(ContextMutablePtr query_context_, GlobalPlannerContextPtr global_planner_context_, const SelectQueryOptions & select_query_options_)
49
    : query_context(std::move(query_context_))
50
    , global_planner_context(std::move(global_planner_context_))
51
    , is_ast_level_optimization_allowed(!(query_context->getClientInfo().query_kind == ClientInfo::QueryKind::SECONDARY_QUERY || select_query_options_.ignore_ast_optimizations))
52
{}
53

54
PlannerContext::PlannerContext(ContextMutablePtr query_context_, PlannerContextPtr planner_context_)
55
    : query_context(std::move(query_context_))
56
    , global_planner_context(planner_context_->global_planner_context)
57
    , is_ast_level_optimization_allowed(planner_context_->is_ast_level_optimization_allowed)
58
{}
59

60
TableExpressionData & PlannerContext::getOrCreateTableExpressionData(const QueryTreeNodePtr & table_expression_node)
61
{
62
    auto [it, _] = table_expression_node_to_data.emplace(table_expression_node, TableExpressionData());
63
    return it->second;
64
}
65

66
const TableExpressionData & PlannerContext::getTableExpressionDataOrThrow(const QueryTreeNodePtr & table_expression_node) const
67
{
68
    auto table_expression_data_it = table_expression_node_to_data.find(table_expression_node);
69
    if (table_expression_data_it == table_expression_node_to_data.end())
70
        throw Exception(ErrorCodes::LOGICAL_ERROR,
71
            "Table expression {} is not registered in planner context",
72
            table_expression_node->formatASTForErrorMessage());
73

74
    return table_expression_data_it->second;
75
}
76

77
TableExpressionData & PlannerContext::getTableExpressionDataOrThrow(const QueryTreeNodePtr & table_expression_node)
78
{
79
    auto table_expression_data_it = table_expression_node_to_data.find(table_expression_node);
80
    if (table_expression_data_it == table_expression_node_to_data.end())
81
        throw Exception(ErrorCodes::LOGICAL_ERROR,
82
            "Table expression {} is not registered in planner context",
83
            table_expression_node->formatASTForErrorMessage());
84

85
    return table_expression_data_it->second;
86
}
87

88
const TableExpressionData * PlannerContext::getTableExpressionDataOrNull(const QueryTreeNodePtr & table_expression_node) const
89
{
90
    auto table_expression_data_it = table_expression_node_to_data.find(table_expression_node);
91
    if (table_expression_data_it == table_expression_node_to_data.end())
92
        return nullptr;
93

94
    return &table_expression_data_it->second;
95
}
96

97
TableExpressionData * PlannerContext::getTableExpressionDataOrNull(const QueryTreeNodePtr & table_expression_node)
98
{
99
    auto table_expression_data_it = table_expression_node_to_data.find(table_expression_node);
100
    if (table_expression_data_it == table_expression_node_to_data.end())
101
        return nullptr;
102

103
    return &table_expression_data_it->second;
104
}
105

106
const ColumnIdentifier & PlannerContext::getColumnNodeIdentifierOrThrow(const QueryTreeNodePtr & column_node) const
107
{
108
    auto & column_node_typed = column_node->as<ColumnNode &>();
109
    const auto & column_name = column_node_typed.getColumnName();
110
    auto column_source = column_node_typed.getColumnSource();
111
    const auto & table_expression_data = getTableExpressionDataOrThrow(column_source);
112
    return table_expression_data.getColumnIdentifierOrThrow(column_name);
113
}
114

115
const ColumnIdentifier * PlannerContext::getColumnNodeIdentifierOrNull(const QueryTreeNodePtr & column_node) const
116
{
117
    auto & column_node_typed = column_node->as<ColumnNode &>();
118
    const auto & column_name = column_node_typed.getColumnName();
119
    auto column_source = column_node_typed.getColumnSourceOrNull();
120
    if (!column_source)
121
        return nullptr;
122

123
    const auto * table_expression_data = getTableExpressionDataOrNull(column_source);
124
    if (!table_expression_data)
125
        return nullptr;
126

127
    return table_expression_data->getColumnIdentifierOrNull(column_name);
128
}
129

130
PlannerContext::SetKey PlannerContext::createSetKey(const DataTypePtr & left_operand_type, const QueryTreeNodePtr & set_source_node)
131
{
132
    const auto set_source_hash = set_source_node->getTreeHash();
133
    if (set_source_node->as<ConstantNode>())
134
    {
135
        /* We need to hash the type of the left operand because we can build different sets for different types.
136
         * (It's done for performance reasons. It's cheaper to convert a small set of values from literal to the type of the left operand.)
137
         *
138
         * For example in expression `(a :: Decimal(9, 1) IN (1.0, 2.5)) AND (b :: Decimal(9, 0) IN (1, 2.5))`
139
         * we need to build two different sets:
140
         *   - `{1, 2.5} :: Set(Decimal(9, 1))` for a
141
         *   - `{1} :: Set(Decimal(9, 0))` for b (2.5 omitted because bercause it's not representable as Decimal(9, 0)).
142
         */
143
        return "__set_" + left_operand_type->getName() + '_' + toString(set_source_hash);
144
    }
145

146
    /// For other cases we will cast left operand to the type of the set source, so no difference in types.
147
    return "__set_" + toString(set_source_hash);
148
}
149

150
}
151

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

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

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

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