Substitute aliases for required columns in ExpressionAnalyzer. [#CLICKHOUSE-3761]

This commit is contained in:
Nikolai Kochetov 2018-07-26 15:58:23 +03:00
parent 11d66d8733
commit 65dcca22a2
3 changed files with 48 additions and 8 deletions

View File

@ -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>;
}

View File

@ -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());
}

View File

@ -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();