mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-22 17:50:47 +00:00
Merge
This commit is contained in:
parent
c5a92790db
commit
e8d77fe8ec
@ -223,7 +223,7 @@ private:
|
||||
* Для агрегатных функций - если нужно, сделать sign rewrite.
|
||||
*/
|
||||
void normalizeTree();
|
||||
void normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, bool in_sign_rewritten);
|
||||
void normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias, bool in_sign_rewritten);
|
||||
|
||||
/// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn.
|
||||
void makeSet(ASTFunction * node, const Block & sample_block);
|
||||
|
@ -439,22 +439,67 @@ void ExpressionActions::finalize(const Names & output_columns)
|
||||
if (final_columns.empty())
|
||||
final_columns.insert(getAnyColumn(input_columns));
|
||||
|
||||
NameSet used_columns = final_columns;
|
||||
/// Какие столбцы нужны, чтобы выполнить действия от текущего до последнего.
|
||||
NameSet needed_columns = final_columns;
|
||||
/// Какие столбцы никто не будет трогать от текущего действия до последнего.
|
||||
NameSet unmodified_columns;
|
||||
|
||||
for (size_t i = 0; i < actions.size(); ++i)
|
||||
{
|
||||
NamesAndTypesList sample_columns = sample_block.getColumnsList();
|
||||
for (NamesAndTypesList::iterator it = sample_columns.begin(); it != sample_columns.end(); ++it)
|
||||
unmodified_columns.insert(it->first);
|
||||
}
|
||||
|
||||
/// Будем идти с конца и поодерживать множество нужных на данном этапе столбцов.
|
||||
/// Будем выбрасывать ненужные действия, хотя обычно их нет по построению.
|
||||
for (int i = static_cast<int>(actions.size()) - 1; i >= 0; --i)
|
||||
{
|
||||
Action & action = actions[i];
|
||||
Names in = action.getNeededColumns();
|
||||
std::string out = action.result_name;
|
||||
|
||||
Names needed = action.getNeededColumns();
|
||||
used_columns.insert(needed.begin(), needed.end());
|
||||
if (action.type == Action::PROJECT)
|
||||
{
|
||||
needed_columns = NameSet(in.begin(), in.end());
|
||||
unmodified_columns.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!out.empty())
|
||||
{
|
||||
/// Если результат не используется и нет побочных эффектов, выбросим действие.
|
||||
if (!needed_columns.count(out) &&
|
||||
(action.type == Action::APPLY_FUNCTION
|
||||
|| action.type == Action::ADD_COLUMN
|
||||
|| action.type == Action::COPY_COLUMN))
|
||||
{
|
||||
actions.erase(actions.begin() + i);
|
||||
|
||||
if (unmodified_columns.count(out))
|
||||
{
|
||||
sample_block.erase(out);
|
||||
unmodified_columns.erase(out);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
unmodified_columns.erase(out);
|
||||
|
||||
needed_columns.erase(out);
|
||||
}
|
||||
|
||||
needed_columns.insert(in.begin(), in.end());
|
||||
}
|
||||
}
|
||||
|
||||
for (NamesAndTypesList::iterator it = input_columns.begin(); it != input_columns.end();)
|
||||
{
|
||||
NamesAndTypesList::iterator it0 = it;
|
||||
++it;
|
||||
if (!used_columns.count(it0->first))
|
||||
if (!needed_columns.count(it0->first))
|
||||
{
|
||||
if (sample_block.has(it0->first))
|
||||
if (unmodified_columns.count(it0->first))
|
||||
sample_block.erase(it0->first);
|
||||
input_columns.erase(it0);
|
||||
}
|
||||
|
@ -286,14 +286,15 @@ void ExpressionAnalyzer::normalizeTree()
|
||||
MapOfASTs tmp_map;
|
||||
if (needSignRewrite())
|
||||
sign_column_name = getSignColumnName();
|
||||
normalizeTreeImpl(ast, tmp_map, tmp_set, false);
|
||||
normalizeTreeImpl(ast, tmp_map, tmp_set, "", false);
|
||||
}
|
||||
|
||||
|
||||
/// finished_asts - уже обработанные вершины (и на что они заменены)
|
||||
/// current_asts - вершины в текущем стеке вызовов этого метода
|
||||
/// current_alias - алиас, повешенный на предка ast (самого глебокого из предков с алиасами)
|
||||
/// in_sign_rewritten - находимся ли мы в поддереве, полученном в результате sign rewrite
|
||||
void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, bool in_sign_rewritten)
|
||||
void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias, bool in_sign_rewritten)
|
||||
{
|
||||
if (finished_asts.count(ast))
|
||||
{
|
||||
@ -304,6 +305,11 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
||||
ASTPtr initial_ast = ast;
|
||||
current_asts.insert(initial_ast);
|
||||
|
||||
std::string * my_alias = getAlias(ast);
|
||||
std::string new_current_alias = current_alias;
|
||||
if (my_alias && !my_alias->empty())
|
||||
new_current_alias = *my_alias;
|
||||
|
||||
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
||||
|
||||
if (!in_sign_rewritten && !sign_column_name.empty())
|
||||
@ -327,9 +333,9 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
||||
{
|
||||
if (node->kind == ASTIdentifier::Column)
|
||||
{
|
||||
/// Если это алиас
|
||||
/// Если это алиас, но не родительский алиас (чтобы работали конструкции вроде "SELECT column+1 AS column").
|
||||
Aliases::const_iterator jt = aliases.find(node->name);
|
||||
if (jt != aliases.end())
|
||||
if (jt != aliases.end() && current_alias != node->name)
|
||||
{
|
||||
/// Заменим его на соответствующий узел дерева
|
||||
if (current_asts.count(jt->second))
|
||||
@ -365,19 +371,19 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
|
||||
|
||||
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
||||
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
||||
normalizeTreeImpl(*it, finished_asts, current_asts, in_sign_rewritten);
|
||||
normalizeTreeImpl(*it, finished_asts, current_asts, new_current_alias, in_sign_rewritten);
|
||||
|
||||
/// Действия, выполняемые снизу вверх.
|
||||
|
||||
/// Если секция WHERE или HAVING состоит из одного алиаса, ссылку нужно заменить не только в children, но и в where_expression и having_expression.
|
||||
if (ASTSelectQuery * select = dynamic_cast<ASTSelectQuery *>(&*ast))
|
||||
{
|
||||
if (select->where_expression)
|
||||
normalizeTreeImpl(select->where_expression, finished_asts, current_asts, in_sign_rewritten);
|
||||
normalizeTreeImpl(select->where_expression, finished_asts, current_asts, new_current_alias, in_sign_rewritten);
|
||||
if (select->having_expression)
|
||||
normalizeTreeImpl(select->having_expression, finished_asts, current_asts, in_sign_rewritten);
|
||||
normalizeTreeImpl(select->having_expression, finished_asts, current_asts, new_current_alias, in_sign_rewritten);
|
||||
}
|
||||
|
||||
/// Действия, выполняемые снизу вверх.
|
||||
|
||||
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
||||
{
|
||||
if (node->name == "lambda")
|
||||
@ -974,6 +980,12 @@ ExpressionActionsPtr ExpressionAnalyzer::getActions(bool project_result)
|
||||
{
|
||||
actions->add(ExpressionActions::Action::project(result_columns));
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Не будем удалять исходные столбцы.
|
||||
for (NamesAndTypesList::const_iterator it = columns.begin(); it != columns.end(); ++it)
|
||||
result_names.push_back(it->first);
|
||||
}
|
||||
|
||||
actions->finalize(result_names);
|
||||
|
||||
|
@ -845,7 +845,7 @@ void StorageMergeTree::mergeParts(std::vector<DataPartPtr> parts)
|
||||
full_path + parts[i]->name + '/', DEFAULT_BLOCK_SIZE, all_column_names, *this, parts[i], ranges, StoragePtr()), primary_expr));
|
||||
}
|
||||
|
||||
/// Порядок потоков важен: при совпадении ключа элементы идет в порядке номера потока-источника.
|
||||
/// Порядок потоков важен: при совпадении ключа элементы идут в порядке номера потока-источника.
|
||||
/// В слитом куске строки с одинаковым ключом должны идти в порядке возрастания идентификатора исходного куска, то есть (примерного) возрастания времени вставки.
|
||||
BlockInputStreamPtr merged_stream = sign_column.empty()
|
||||
? new MergingSortedBlockInputStream(src_streams, sort_descr, DEFAULT_BLOCK_SIZE)
|
||||
|
Loading…
Reference in New Issue
Block a user