Merge pull request #59774 from ClickHouse/analyzer-merge-follow-up

Followup #50894
This commit is contained in:
Dmitry Novik 2024-02-09 15:05:19 +01:00 committed by GitHub
commit 2e6ca6200e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -756,16 +756,23 @@ QueryTreeNodePtr replaceTableExpressionAndRemoveJoin(
auto join_tree_type = query_node->getJoinTree()->getNodeType(); auto join_tree_type = query_node->getJoinTree()->getNodeType();
auto modified_query = query_node->cloneAndReplace(original_table_expression, replacement_table_expression); auto modified_query = query_node->cloneAndReplace(original_table_expression, replacement_table_expression);
// For the case when join tree is just a table or a table function we don't need to do anything more.
if (join_tree_type == QueryTreeNodeType::TABLE || join_tree_type == QueryTreeNodeType::TABLE_FUNCTION) if (join_tree_type == QueryTreeNodeType::TABLE || join_tree_type == QueryTreeNodeType::TABLE_FUNCTION)
return modified_query; return modified_query;
// JOIN needs to be removed because StorageMerge should produce not joined data.
// GROUP BY should be removed as well.
auto * modified_query_node = modified_query->as<QueryNode>(); auto * modified_query_node = modified_query->as<QueryNode>();
// Remove the JOIN statement. As a result query will have a form like: SELECT * FROM <table> ...
modified_query = modified_query->cloneAndReplace(modified_query_node->getJoinTree(), replacement_table_expression); modified_query = modified_query->cloneAndReplace(modified_query_node->getJoinTree(), replacement_table_expression);
modified_query_node = modified_query->as<QueryNode>(); modified_query_node = modified_query->as<QueryNode>();
query_node = modified_query->as<QueryNode>(); query_node = modified_query->as<QueryNode>();
// For backward compatibility we need to leave all filters related to this table.
// It may lead to some incorrect result.
if (query_node->hasPrewhere()) if (query_node->hasPrewhere())
replaceFilterExpression(query_node->getPrewhere(), replacement_table_expression, context); replaceFilterExpression(query_node->getPrewhere(), replacement_table_expression, context);
if (query_node->hasWhere()) if (query_node->hasWhere())
@ -779,6 +786,9 @@ QueryTreeNodePtr replaceTableExpressionAndRemoveJoin(
projection.clear(); projection.clear();
NamesAndTypes projection_columns; NamesAndTypes projection_columns;
// Select only required columns from the table, because projection list may contain:
// 1. aggregate functions
// 2. expressions referencing other tables of JOIN
for (auto const & column_name : required_column_names) for (auto const & column_name : required_column_names)
{ {
QueryTreeNodePtr fake_node = std::make_shared<IdentifierNode>(Identifier{column_name}); QueryTreeNodePtr fake_node = std::make_shared<IdentifierNode>(Identifier{column_name});
@ -791,6 +801,8 @@ QueryTreeNodePtr replaceTableExpressionAndRemoveJoin(
throw Exception(ErrorCodes::LOGICAL_ERROR, "Required column '{}' is not resolved", column_name); throw Exception(ErrorCodes::LOGICAL_ERROR, "Required column '{}' is not resolved", column_name);
auto fake_column = resolved_column->getColumn(); auto fake_column = resolved_column->getColumn();
// Identifier is resolved to ColumnNode, but we need to get rid of ALIAS columns
// and also fix references to source expression (now column is referencing original table expression).
ApplyAliasColumnExpressionsVisitor visitor(replacement_table_expression); ApplyAliasColumnExpressionsVisitor visitor(replacement_table_expression);
visitor.visit(fake_node); visitor.visit(fake_node);
@ -860,7 +872,7 @@ SelectQueryInfo ReadFromMerge::getModifiedQueryInfo(const ContextPtr & modified_
QueryTreeNodePtr column_node; QueryTreeNodePtr column_node;
// Replace all references to ALIAS columns in the query by expressions.
if (is_alias) if (is_alias)
{ {
QueryTreeNodePtr fake_node = std::make_shared<IdentifierNode>(Identifier{column}); QueryTreeNodePtr fake_node = std::make_shared<IdentifierNode>(Identifier{column});