1#include "evaluateMissingDefaults.h"
2
3#include <Core/Block.h>
4#include <Storages/ColumnDefault.h>
5#include <Interpreters/SyntaxAnalyzer.h>
6#include <Interpreters/ExpressionAnalyzer.h>
7#include <Interpreters/ExpressionActions.h>
8#include <Parsers/ASTExpressionList.h>
9#include <Parsers/ASTWithAlias.h>
10#include <utility>
11#include <DataTypes/DataTypesNumber.h>
12
13
14namespace DB
15{
16
17static ASTPtr requiredExpressions(Block & block, const NamesAndTypesList & required_columns, const ColumnDefaults & column_defaults)
18{
19 ASTPtr default_expr_list = std::make_shared<ASTExpressionList>();
20
21 for (const auto & column : required_columns)
22 {
23 if (block.has(column.name))
24 continue;
25
26 const auto it = column_defaults.find(column.name);
27
28 /// expressions must be cloned to prevent modification by the ExpressionAnalyzer
29 if (it != column_defaults.end())
30 default_expr_list->children.emplace_back(
31 setAlias(it->second.expression->clone(), it->first));
32 }
33
34 if (default_expr_list->children.empty())
35 return nullptr;
36 return default_expr_list;
37}
38
39void evaluateMissingDefaults(Block & block,
40 const NamesAndTypesList & required_columns,
41 const ColumnDefaults & column_defaults,
42 const Context & context, bool save_unneeded_columns)
43{
44 if (column_defaults.empty())
45 return;
46
47 ASTPtr default_expr_list = requiredExpressions(block, required_columns, column_defaults);
48 if (!default_expr_list)
49 return;
50
51 if (!save_unneeded_columns)
52 {
53 auto syntax_result = SyntaxAnalyzer(context).analyze(default_expr_list, block.getNamesAndTypesList());
54 ExpressionAnalyzer{default_expr_list, syntax_result, context}.getActions(true)->execute(block);
55 return;
56 }
57
58 /** ExpressionAnalyzer eliminates "unused" columns, in order to ensure their safety
59 * we are going to operate on a copy instead of the original block */
60 Block copy_block{block};
61
62 auto syntax_result = SyntaxAnalyzer(context).analyze(default_expr_list, block.getNamesAndTypesList());
63 auto expression_analyzer = ExpressionAnalyzer{default_expr_list, syntax_result, context};
64 auto required_source_columns = syntax_result->requiredSourceColumns();
65 auto rows_was = copy_block.rows();
66
67 // Delete all not needed columns in DEFAULT expression.
68 // They can intersect with columns added in PREWHERE
69 // test 00950_default_prewhere
70 // CLICKHOUSE-4523
71 for (const auto & delete_column : copy_block.getNamesAndTypesList())
72 {
73 if (std::find(required_source_columns.begin(), required_source_columns.end(), delete_column.name) == required_source_columns.end())
74 {
75 copy_block.erase(delete_column.name);
76 }
77 }
78
79 if (copy_block.columns() == 0)
80 {
81 // Add column to indicate block size in execute()
82 copy_block.insert({DataTypeUInt8().createColumnConst(rows_was, 0u), std::make_shared<DataTypeUInt8>(), "__dummy"});
83 }
84
85 expression_analyzer.getActions(true)->execute(copy_block);
86
87 /// move evaluated columns to the original block, materializing them at the same time
88 size_t pos = 0;
89 for (auto col = required_columns.begin(); col != required_columns.end(); ++col, ++pos)
90 {
91 if (copy_block.has(col->name))
92 {
93 auto evaluated_col = copy_block.getByName(col->name);
94 evaluated_col.column = evaluated_col.column->convertToFullColumnIfConst();
95
96 block.insert(pos, std::move(evaluated_col));
97 }
98 }
99}
100
101}
102