提交 e8d77fe8 编写于 作者: M Michael Kolupaev

Merge

上级 c5a92790
......@@ -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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册