提交 f504fd21 编写于 作者: V Vyacheslav Alipov

reorganized adding of MULTIPLE_ARRAY_JOIN action [#CONV-7967]

上级 0e96233d
...@@ -48,7 +48,9 @@ public: ...@@ -48,7 +48,9 @@ public:
DataTypePtr result_type; DataTypePtr result_type;
/// Для MULTIPLE_ARRAY_JOIN /// Для MULTIPLE_ARRAY_JOIN
NameToNameMap array_joined_columns; /// Имена исходных столбцов -> имена столбцов результатов ARRAY JOIN std::string nested_table_name;
std::string nested_table_alias;
NameSet array_joined_columns; /// Имена столбцов без префикса 'NestedTableName.'
/// Для ADD_COLUMN. /// Для ADD_COLUMN.
ColumnPtr added_column; ColumnPtr added_column;
...@@ -118,11 +120,15 @@ public: ...@@ -118,11 +120,15 @@ public:
return a; return a;
} }
static Action multipleArrayJoin(const NameToNameMap & array_joined_columns_) static Action multipleArrayJoin(const std::string & nested_table_name,
const std::string & nested_table_alias,
const NameSet & array_joined_columns)
{ {
Action a; Action a;
a.type = MULTIPLE_ARRAY_JOIN; a.type = MULTIPLE_ARRAY_JOIN;
a.array_joined_columns = array_joined_columns_; a.nested_table_name = nested_table_name;
a.nested_table_alias = nested_table_alias;
a.array_joined_columns = array_joined_columns;
return a; return a;
} }
...@@ -135,6 +141,11 @@ public: ...@@ -135,6 +141,11 @@ public:
private: private:
friend class ExpressionActions; friend class ExpressionActions;
/// Проверяет является ли данный столбец результатом ARRAY JOIN
bool isArrayJoinedColumnName(const String & name) const;
/// Возвращает исходное имя столбца до применения к нему ARRAY JOIN
String getOriginalNestedName(const String & name) const;
std::vector<Action> getPrerequisites(Block & sample_block); std::vector<Action> getPrerequisites(Block & sample_block);
void prepare(Block & sample_block); void prepare(Block & sample_block);
void execute(Block & block) const; void execute(Block & block) const;
......
...@@ -112,6 +112,9 @@ private: ...@@ -112,6 +112,9 @@ private:
typedef std::set<const IAST *> SetOfASTs; typedef std::set<const IAST *> SetOfASTs;
typedef std::map<ASTPtr, ASTPtr> MapOfASTs; typedef std::map<ASTPtr, ASTPtr> MapOfASTs;
/// Столбцы, которые должны быть преобразованы из-за секции ARRAY JOIN
NameSet array_joined_columns;
/** Для getActionsImpl. /** Для getActionsImpl.
* Стек из ExpressionActions, соответствующих вложенным лямбда-выражениям. * Стек из ExpressionActions, соответствующих вложенным лямбда-выражениям.
* Новое действие нужно добавлять на самый высокий возможный уровень. * Новое действие нужно добавлять на самый высокий возможный уровень.
...@@ -239,7 +242,9 @@ private: ...@@ -239,7 +242,9 @@ private:
/// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn. /// Превратить перечисление значений или подзапрос в ASTSet. node - функция in или notIn.
void makeSet(ASTFunction * node, const Block & sample_block); void makeSet(ASTFunction * node, const Block & sample_block);
void getArrayJoinedColumnsImpl(ASTPtr ast, NameToNameMap & array_joined_columns); void getArrayJoinedColumns();
void getArrayJoinedColumnsImpl(ASTPtr ast);
void addMultipleArrayJoinAction(ExpressionActions & actions);
void getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack); void getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack);
......
...@@ -12,8 +12,8 @@ Names ExpressionActions::Action::getNeededColumns() const ...@@ -12,8 +12,8 @@ Names ExpressionActions::Action::getNeededColumns() const
Names res = argument_names; Names res = argument_names;
res.insert(res.end(), prerequisite_names.begin(), prerequisite_names.end()); res.insert(res.end(), prerequisite_names.begin(), prerequisite_names.end());
for (NameToNameMap::const_iterator it = array_joined_columns.begin(); it != array_joined_columns.end(); ++it) for (NameSet::const_iterator it = array_joined_columns.begin(); it != array_joined_columns.end(); ++it)
res.push_back(it->first); res.push_back(DataTypeNested::concatenateNestedName(nested_table_alias, *it));
for (size_t i = 0; i < projection.size(); ++i) for (size_t i = 0; i < projection.size(); ++i)
{ {
...@@ -25,7 +25,28 @@ Names ExpressionActions::Action::getNeededColumns() const ...@@ -25,7 +25,28 @@ Names ExpressionActions::Action::getNeededColumns() const
return res; return res;
} }
bool ExpressionActions::Action::isArrayJoinedColumnName(const String & name) const
{
std::string nested_table = DataTypeNested::extractNestedTableName(name);
std::string nested_column = DataTypeNested::extractNestedColumnName(name);
return nested_column == nested_table_alias || (nested_table == nested_table_alias && array_joined_columns.count(nested_column));
}
String ExpressionActions::Action::getOriginalNestedName(const String & name) const
{
std::string nested_table = DataTypeNested::extractNestedTableName(name);
std::string nested_column = DataTypeNested::extractNestedColumnName(name);
if (nested_column == nested_table_alias)
return nested_table_name;
if (nested_table == nested_table_alias && array_joined_columns.count(nested_column))
return DataTypeNested::concatenateNestedName(nested_table_name, nested_column);
throw Exception("Can't produce original nested name for column: " + name, ErrorCodes::LOGICAL_ERROR);
}
ExpressionActions::Action ExpressionActions::Action::applyFunction(FunctionPtr function_, ExpressionActions::Action ExpressionActions::Action::applyFunction(FunctionPtr function_,
const std::vector<std::string> & argument_names_, const std::vector<std::string> & argument_names_,
std::string result_name_) std::string result_name_)
...@@ -156,8 +177,7 @@ void ExpressionActions::Action::prepare(Block & sample_block) ...@@ -156,8 +177,7 @@ void ExpressionActions::Action::prepare(Block & sample_block)
const ColumnWithNameAndType & current = sample_block.getByPosition(i); const ColumnWithNameAndType & current = sample_block.getByPosition(i);
const DataTypeArray * array_type = dynamic_cast<const DataTypeArray *>(&*current.type); const DataTypeArray * array_type = dynamic_cast<const DataTypeArray *>(&*current.type);
NameToNameMap::const_iterator array_joined_names = array_joined_columns.find(current.name); if (isArrayJoinedColumnName(current.name))
if (array_joined_columns.end() != array_joined_names)
{ {
if (!array_type) if (!array_type)
throw Exception("ARRAY JOIN requires array argument", ErrorCodes::TYPE_MISMATCH); throw Exception("ARRAY JOIN requires array argument", ErrorCodes::TYPE_MISMATCH);
...@@ -167,17 +187,10 @@ void ExpressionActions::Action::prepare(Block & sample_block) ...@@ -167,17 +187,10 @@ void ExpressionActions::Action::prepare(Block & sample_block)
ColumnWithNameAndType result; ColumnWithNameAndType result;
result.column = NULL; result.column = NULL;
result.type = array_type->getNestedType(); result.type = array_type->getNestedType();
result.name = array_joined_names->second; result.name = current.name;
/// Если для столбцов из секции ARRAY JOIN указали алиас, то не будем удалять исходные sample_block.erase(i);
/// столбцы из блока. Они могут быть использованы функциями, работающими с массивом целиком. sample_block.insert(i, result);
if (array_joined_names->first != array_joined_names->second)
sample_block.insert(result);
else
{
sample_block.erase(i);
sample_block.insert(i, result);
}
} }
} }
...@@ -250,7 +263,7 @@ void ExpressionActions::Action::execute(Block & block) const ...@@ -250,7 +263,7 @@ void ExpressionActions::Action::execute(Block & block) const
{ {
const ColumnWithNameAndType & current = block.getByPosition(i); const ColumnWithNameAndType & current = block.getByPosition(i);
if (current.name == source_name || array_joined_columns.count(current.name)) if (isArrayJoinedColumnName(current.name))
{ {
if (!dynamic_cast<const DataTypeArray *>(&*current.type)) if (!dynamic_cast<const DataTypeArray *>(&*current.type))
throw Exception("arrayJoin of not array: " + current.name, ErrorCodes::TYPE_MISMATCH); throw Exception("arrayJoin of not array: " + current.name, ErrorCodes::TYPE_MISMATCH);
...@@ -279,8 +292,7 @@ void ExpressionActions::Action::execute(Block & block) const ...@@ -279,8 +292,7 @@ void ExpressionActions::Action::execute(Block & block) const
{ {
ColumnWithNameAndType & current = block.getByPosition(i); ColumnWithNameAndType & current = block.getByPosition(i);
NameToNameMap::const_iterator array_joined_names = array_joined_columns.find(current.name); if (isArrayJoinedColumnName(current.name))
if (current.name == source_name || array_joined_columns.end() != array_joined_names)
{ {
ColumnPtr array_ptr = current.column; ColumnPtr array_ptr = current.column;
if (array_ptr->isConst()) if (array_ptr->isConst())
...@@ -289,17 +301,10 @@ void ExpressionActions::Action::execute(Block & block) const ...@@ -289,17 +301,10 @@ void ExpressionActions::Action::execute(Block & block) const
ColumnWithNameAndType result; ColumnWithNameAndType result;
result.column = dynamic_cast<const ColumnArray &>(*array_ptr).getDataPtr(); result.column = dynamic_cast<const ColumnArray &>(*array_ptr).getDataPtr();
result.type = dynamic_cast<const DataTypeArray &>(*current.type).getNestedType(); result.type = dynamic_cast<const DataTypeArray &>(*current.type).getNestedType();
result.name = type == MULTIPLE_ARRAY_JOIN ? array_joined_names->second : result_name; result.name = type == MULTIPLE_ARRAY_JOIN ? current.name : result_name;
/// Если для столбцов из секции ARRAY JOIN указали алиас, то не будем удалять исходные block.erase(i);
/// столбцы из блока. Они могут быть использованы функциями, работающими с массивом целиком. block.insert(i, result);
if (type == MULTIPLE_ARRAY_JOIN && array_joined_names->first != array_joined_names->second)
block.insert(result);
else
{
block.erase(i);
block.insert(i, result);
}
} }
else else
current.column = current.column->replicate(any_array->getOffsets()); current.column = current.column->replicate(any_array->getOffsets());
...@@ -372,12 +377,13 @@ std::string ExpressionActions::Action::toString() const ...@@ -372,12 +377,13 @@ std::string ExpressionActions::Action::toString() const
ss << result_name << "(" << result_type->getName() << ")" << "= " << "arrayJoin" << " ( " << source_name << " )"; ss << result_name << "(" << result_type->getName() << ")" << "= " << "arrayJoin" << " ( " << source_name << " )";
break; break;
case MULTIPLE_ARRAY_JOIN: case MULTIPLE_ARRAY_JOIN:
ss << "ARRAY JOIN {"; ss << "ARRAY JOIN " << nested_table_name << (nested_table_name != nested_table_alias ? " AS " + nested_table_alias : "");
for (NameToNameMap::const_iterator it = array_joined_columns.begin(); it != array_joined_columns.end(); ++it) ss << "{";
for (NameSet::const_iterator it = array_joined_columns.begin(); it != array_joined_columns.end(); ++it)
{ {
if (it != array_joined_columns.begin()) if (it != array_joined_columns.begin())
ss << ", "; ss << ", ";
ss << it->first << " = " << it->second; ss << *it;
} }
ss << "}"; ss << "}";
break; break;
...@@ -462,8 +468,8 @@ void ExpressionActions::addImpl(Action action, NameSet & current_names, Names & ...@@ -462,8 +468,8 @@ void ExpressionActions::addImpl(Action action, NameSet & current_names, Names &
if (action.result_name != "") if (action.result_name != "")
new_names.push_back(action.result_name); new_names.push_back(action.result_name);
for (NameToNameMap::const_iterator it = action.array_joined_columns.begin(); it != action.array_joined_columns.end(); ++it) for (NameSet::const_iterator it = action.array_joined_columns.begin(); it != action.array_joined_columns.end(); ++it)
new_names.push_back(it->second); new_names.push_back(DataTypeNested::concatenateNestedName(action.nested_table_alias, *it));
Actions prerequisites = action.getPrerequisites(sample_block); Actions prerequisites = action.getPrerequisites(sample_block);
...@@ -620,13 +626,15 @@ std::string ExpressionActions::getID() const ...@@ -620,13 +626,15 @@ std::string ExpressionActions::getID() const
ss << actions[i].result_name; ss << actions[i].result_name;
if (actions[i].type == Action::MULTIPLE_ARRAY_JOIN) if (actions[i].type == Action::MULTIPLE_ARRAY_JOIN)
{ {
for (NameToNameMap::const_iterator it = actions[i].array_joined_columns.begin(); ss << actions[i].nested_table_alias << ".{";
for (NameSet::const_iterator it = actions[i].array_joined_columns.begin();
it != actions[i].array_joined_columns.end(); ++it) it != actions[i].array_joined_columns.end(); ++it)
{ {
if (it != actions[i].array_joined_columns.begin()) if (it != actions[i].array_joined_columns.begin())
ss << ", "; ss << ", ";
ss << it->second; ss << *it;
} }
ss << "}";
} }
} }
...@@ -720,10 +728,10 @@ void ExpressionActions::optimizeArrayJoin() ...@@ -720,10 +728,10 @@ void ExpressionActions::optimizeArrayJoin()
if (actions[i].result_name != "") if (actions[i].result_name != "")
array_joined_columns.insert(actions[i].result_name); array_joined_columns.insert(actions[i].result_name);
for (NameToNameMap::const_iterator it = actions[i].array_joined_columns.begin(); for (NameSet::const_iterator it = actions[i].array_joined_columns.begin();
it != actions[i].array_joined_columns.end(); ++it) it != actions[i].array_joined_columns.end(); ++it)
{ {
array_joined_columns.insert(it->second); array_joined_columns.insert(DataTypeNested::concatenateNestedName(actions[i].nested_table_alias, *it));
} }
array_join_dependencies.insert(needed.begin(), needed.end()); array_join_dependencies.insert(needed.begin(), needed.end());
......
...@@ -60,11 +60,14 @@ void ExpressionAnalyzer::init() ...@@ -60,11 +60,14 @@ void ExpressionAnalyzer::init()
removeUnusedColumns(); removeUnusedColumns();
getArrayJoinedColumns();
/// Найдем агрегатные функции. /// Найдем агрегатные функции.
if (select_query && (select_query->group_expression_list || select_query->having_expression)) if (select_query && (select_query->group_expression_list || select_query->having_expression))
has_aggregation = true; has_aggregation = true;
ExpressionActions temp_actions(columns, settings); ExpressionActions temp_actions(columns, settings);
addMultipleArrayJoinAction(temp_actions);
getAggregatesImpl(ast, temp_actions); getAggregatesImpl(ast, temp_actions);
if (has_aggregation) if (has_aggregation)
...@@ -389,16 +392,6 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as ...@@ -389,16 +392,6 @@ void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_as
throw Exception("Requested Sign column while sign-rewrite is on.", ErrorCodes::QUERY_SECTION_DOESNT_MAKE_SENSE); throw Exception("Requested Sign column while sign-rewrite is on.", ErrorCodes::QUERY_SECTION_DOESNT_MAKE_SENSE);
} }
} }
/// на случай если подставили алиас
node = dynamic_cast<ASTIdentifier *>(&*ast);
if (node && node->kind == ASTIdentifier::Column && isArrayJoinedColumnName(node->name))
{
String original_name = getOriginalNestedName(node->name);
node->alias = node->name;
node->name = original_name;
}
} }
else if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast)) else if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
{ {
...@@ -568,22 +561,59 @@ void ExpressionAnalyzer::getRootActionsImpl(ASTPtr ast, bool no_subqueries, bool ...@@ -568,22 +561,59 @@ void ExpressionAnalyzer::getRootActionsImpl(ASTPtr ast, bool no_subqueries, bool
} }
void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast, NameToNameMap & array_joined_columns) void ExpressionAnalyzer::getArrayJoinedColumns()
{
assertSelect();
if (!select_query->array_join_identifier)
return;
getArrayJoinedColumnsImpl(ast);
}
void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast)
{ {
if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast)) if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
{ {
if (node->kind == ASTIdentifier::Column && isArrayJoinedColumnName(node->name)) if (node->kind == ASTIdentifier::Column && isArrayJoinedColumnName(node->name))
array_joined_columns[node->name] = node->alias; array_joined_columns.insert(DataTypeNested::extractNestedColumnName(node->name));
} }
else else
{ {
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
if (!dynamic_cast<ASTSelectQuery *>(&**it)) if (!dynamic_cast<ASTSelectQuery *>(&**it))
getArrayJoinedColumnsImpl(*it, array_joined_columns); getArrayJoinedColumnsImpl(*it);
} }
} }
void ExpressionAnalyzer::addMultipleArrayJoinAction(ExpressionActions & actions)
{
String nested_table_name = select_query->array_join_identifier->getColumnName();
String nested_table_alias = select_query->array_join_identifier->getAlias();
bool added_columns = false;
const NamesAndTypesList & input_columns = actions.getRequiredColumnsWithTypes();
for (NamesAndTypesList::const_iterator it = input_columns.begin(); it != input_columns.end(); ++it)
{
String nested_table = DataTypeNested::extractNestedTableName(it->first);
String nested_column = DataTypeNested::extractNestedColumnName(it->first);
if (nested_column == nested_table_name || (nested_table == nested_table_name && array_joined_columns.count(nested_column)))
{
added_columns = true;
String array_joined_name = DataTypeNested::concatenateNestedName(nested_table_alias, nested_column);
actions.add(ExpressionActions::Action::copyColumn(it->first, array_joined_name));
}
}
if (added_columns)
actions.add(ExpressionActions::Action::multipleArrayJoin(nested_table_name, nested_table_alias, array_joined_columns));
}
void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack) void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack)
{ {
/// Если результат вычисления уже есть в блоке. /// Если результат вычисления уже есть в блоке.
...@@ -890,14 +920,15 @@ bool ExpressionAnalyzer::appendArrayJoin(ExpressionActionsChain & chain) ...@@ -890,14 +920,15 @@ bool ExpressionAnalyzer::appendArrayJoin(ExpressionActionsChain & chain)
initChain(chain, columns); initChain(chain, columns);
ExpressionActionsChain::Step & step = chain.steps.back(); ExpressionActionsChain::Step & step = chain.steps.back();
NameToNameMap array_joined_columns; getArrayJoinedColumnsImpl(ast);
getArrayJoinedColumnsImpl(ast, array_joined_columns);
if (!array_joined_columns.empty()) if (!array_joined_columns.empty())
{ {
step.actions->add(ExpressionActions::Action::multipleArrayJoin(array_joined_columns)); addMultipleArrayJoinAction(*step.actions);
for (NameToNameMap::const_iterator it = array_joined_columns.begin(); it != array_joined_columns.end(); ++it)
step.required_output.push_back(it->second); String nested_table_alias = select_query->array_join_identifier->getAlias();
for (NameSet::const_iterator it = array_joined_columns.begin(); it != array_joined_columns.end(); ++it)
step.required_output.push_back(DataTypeNested::concatenateNestedName(nested_table_alias, *it));
} }
return true; return true;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册