Fix identifier qualification in the presence of ARRAY JOIN

This commit is contained in:
Dmitry Novik 2024-11-29 17:00:14 +01:00
parent 7c15d83a21
commit a528b51a97
5 changed files with 29 additions and 9 deletions

View File

@ -165,6 +165,9 @@ struct IdentifierResolveScope
/// Table expression node to data
std::unordered_map<QueryTreeNodePtr, AnalysisTableExpressionData> table_expression_node_to_data;
/// Table expression nodes that appear in the join tree of the corresponding query
std::unordered_set<QueryTreeNodePtr> registered_table_expression_nodes;
QueryTreeNodePtrWithHashIgnoreTypesSet nullable_group_by_keys;
/// Here we count the number of nullable GROUP BY keys we met resolving expression.
/// E.g. for a query `SELECT tuple(tuple(number)) FROM numbers(10) GROUP BY (number, tuple(number)) with cube`

View File

@ -680,6 +680,27 @@ bool IdentifierResolver::tryBindIdentifierToTableExpressions(const IdentifierLoo
return can_bind_identifier_to_table_expression;
}
bool IdentifierResolver::tryBindIdentifierToArrayJoinExpressions(const IdentifierLookup & identifier_lookup, const IdentifierResolveScope & scope)
{
bool result = false;
for (const auto & table_expression : scope.registered_table_expression_nodes)
{
auto * array_join_node = table_expression->as<ArrayJoinNode>();
if (!array_join_node)
continue;
for (const auto & array_join_expression : array_join_node->getJoinExpressions())
{
auto array_join_expression_alias = array_join_expression->getAlias();
if (identifier_lookup.identifier.front() == array_join_expression_alias)
return true;
}
}
return result;
}
QueryTreeNodePtr IdentifierResolver::tryResolveIdentifierFromStorage(
const Identifier & identifier,
const QueryTreeNodePtr & table_expression_node,

View File

@ -109,6 +109,9 @@ public:
const QueryTreeNodePtr & table_expression_node,
const IdentifierResolveScope & scope);
static bool tryBindIdentifierToArrayJoinExpressions(const IdentifierLookup & identifier_lookup,
const IdentifierResolveScope & scope);
QueryTreeNodePtr tryResolveIdentifierFromTableExpression(const IdentifierLookup & identifier_lookup,
const QueryTreeNodePtr & table_expression_node,
IdentifierResolveScope & scope);

View File

@ -1593,7 +1593,7 @@ void QueryAnalyzer::qualifyColumnNodesWithProjectionNames(const QueryTreeNodes &
if (need_to_qualify)
need_to_qualify = IdentifierResolver::tryBindIdentifierToTableExpressions(identifier_lookup, table_expression_node, scope);
if (IdentifierResolver::tryBindIdentifierToAliases(identifier_lookup, scope))
if (IdentifierResolver::tryBindIdentifierToAliases(identifier_lookup, scope) || IdentifierResolver::tryBindIdentifierToArrayJoinExpressions(identifier_lookup, scope))
need_to_qualify = true;
if (need_to_qualify)
@ -5366,6 +5366,7 @@ void QueryAnalyzer::resolveQueryJoinTreeNode(QueryTreeNodePtr & join_tree_node,
};
add_table_expression_alias_into_scope(join_tree_node);
scope.registered_table_expression_nodes.insert(join_tree_node);
scope.table_expressions_in_resolve_process.erase(join_tree_node.get());
}

View File

@ -135,14 +135,6 @@ public:
using Base = InDepthQueryTreeVisitorWithContext<CreateUniqueArrayJoinAliasesVisitor>;
using Base::Base;
bool needChildVisit(VisitQueryTreeNodeType & parent [[maybe_unused]], VisitQueryTreeNodeType & child [[maybe_unused]])
{
auto * array_join = parent->as<ArrayJoinNode>();
if (!array_join)
return true;
return child != array_join->getJoinExpressionsNode();
}
void enterImpl(QueryTreeNodePtr & node)
{
if (auto * array_join_typed = node->as<ArrayJoinNode>())