mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 17:20:50 +00:00
Substitute aliases for required columns in ExpressionAnalyzer. [#CLICKHOUSE-3761]
This commit is contained in:
parent
11d66d8733
commit
65dcca22a2
@ -12,5 +12,6 @@ namespace DB
|
||||
using Names = std::vector<std::string>;
|
||||
using NameSet = std::unordered_set<std::string>;
|
||||
using NameToNameMap = std::unordered_map<std::string, std::string>;
|
||||
using NameToNameSetMap = std::unordered_map<std::string, NameSet>;
|
||||
|
||||
}
|
||||
|
@ -62,6 +62,8 @@
|
||||
#include <Functions/FunctionsMiscellaneous.h>
|
||||
#include <DataTypes/DataTypeTuple.h>
|
||||
#include <Parsers/queryToString.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -172,7 +174,7 @@ ExpressionAnalyzer::ExpressionAnalyzer(
|
||||
const SubqueriesForSets & subqueries_for_set_)
|
||||
: ast(ast_), context(context_), settings(context.getSettings()),
|
||||
subquery_depth(subquery_depth_),
|
||||
source_columns(source_columns_), required_result_columns(required_result_columns_.begin(), required_result_columns_.end()),
|
||||
source_columns(source_columns_),
|
||||
storage(storage_),
|
||||
do_global(do_global_), subqueries_for_sets(subqueries_for_set_)
|
||||
{
|
||||
@ -217,6 +219,9 @@ ExpressionAnalyzer::ExpressionAnalyzer(
|
||||
/// Common subexpression elimination. Rewrite rules.
|
||||
normalizeTree();
|
||||
|
||||
/// Substitute aliases for required_result_columns and create set with their names.
|
||||
required_result_columns = createRequiredResultColumnsMap(required_result_columns_);
|
||||
|
||||
/// Remove unneeded columns according to 'required_result_columns'.
|
||||
/// Leave all selected columns in case of DISTINCT; columns that contain arrayJoin function inside.
|
||||
/// Must be after 'normalizeTree' (after expanding aliases, for aliases not get lost)
|
||||
@ -971,6 +976,25 @@ void ExpressionAnalyzer::addASTAliases(ASTPtr & ast, int ignore_levels)
|
||||
}
|
||||
|
||||
|
||||
NameToNameSetMap ExpressionAnalyzer::createRequiredResultColumnsMap(const Names & required_result_columns)
|
||||
{
|
||||
NameToNameSetMap map;
|
||||
ParserExpression parser;
|
||||
|
||||
for (const auto & column : required_result_columns)
|
||||
{
|
||||
/// TODO: it's better to change type of required_result_columns to ASTs
|
||||
auto expr = parseQuery(parser, column, 0);
|
||||
SetOfASTs tmp_set;
|
||||
MapOfASTs tmp_map;
|
||||
normalizeTreeImpl(expr, tmp_map, tmp_set, "", 0);
|
||||
map[expr->getColumnName()].insert(column);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
void ExpressionAnalyzer::normalizeTree()
|
||||
{
|
||||
SetOfASTs tmp_set;
|
||||
@ -2754,12 +2778,24 @@ void ExpressionAnalyzer::appendProjectResult(ExpressionActionsChain & chain) con
|
||||
ASTs asts = select_query->select_expression_list->children;
|
||||
for (size_t i = 0; i < asts.size(); ++i)
|
||||
{
|
||||
String result_name = asts[i]->getAliasOrColumnName();
|
||||
if (required_result_columns.empty() || required_result_columns.count(result_name))
|
||||
String result_name = asts[i]->getColumnName();
|
||||
if (required_result_columns.empty())
|
||||
{
|
||||
result_columns.emplace_back(asts[i]->getColumnName(), result_name);
|
||||
result_columns.emplace_back(result_name, asts[i]->getAliasOrColumnName());
|
||||
step.required_output.push_back(result_columns.back().second);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto iter = required_result_columns.find(result_name);
|
||||
if (iter != required_result_columns.end())
|
||||
{
|
||||
for (const auto & original_name : iter->second)
|
||||
{
|
||||
result_columns.emplace_back(result_name, original_name);
|
||||
step.required_output.push_back(result_columns.back().second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
step.actions->add(ExpressionAction::project(result_columns));
|
||||
@ -3280,7 +3316,7 @@ void ExpressionAnalyzer::removeUnneededColumnsFromSelectClause()
|
||||
|
||||
elements.erase(std::remove_if(elements.begin(), elements.end(), [this](const auto & node)
|
||||
{
|
||||
return !required_result_columns.count(node->getAliasOrColumnName()) && !hasArrayJoin(node);
|
||||
return !required_result_columns.count(node->getColumnName()) && !hasArrayJoin(node);
|
||||
}), elements.end());
|
||||
}
|
||||
|
||||
|
@ -192,9 +192,9 @@ private:
|
||||
*/
|
||||
NamesAndTypesList source_columns;
|
||||
|
||||
/** If non-empty, ignore all expressions in not from this list.
|
||||
*/
|
||||
NameSet required_result_columns;
|
||||
/// If non-empty, ignore all expressions in not from this list.
|
||||
/// Map columns with substituted aliases to original names.
|
||||
NameToNameSetMap required_result_columns;
|
||||
|
||||
/// Columns after ARRAY JOIN, JOIN, and/or aggregation.
|
||||
NamesAndTypesList aggregated_columns;
|
||||
@ -275,6 +275,9 @@ private:
|
||||
void normalizeTree();
|
||||
void normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias, size_t level);
|
||||
|
||||
/// Substitute aliases for required_result_columns and create map with their new to original names.
|
||||
NameToNameSetMap createRequiredResultColumnsMap(const Names & required_result_columns);
|
||||
|
||||
/// Eliminates injective function calls and constant expressions from group by statement
|
||||
void optimizeGroupBy();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user