Initialize query join tree node. * * 1. Resolve identifiers. * 2. Register table, table function, query, union, join, array join nodes in scope table expressions in resolve process. */
| 4005 | * 2. Register table, table function, query, union, join, array join nodes in scope table expressions in resolve process. |
| 4006 | */ |
| 4007 | void QueryAnalyzer::initializeQueryJoinTreeNode(QueryTreeNodePtr & join_tree_node, IdentifierResolveScope & scope) |
| 4008 | { |
| 4009 | std::deque<QueryTreeNodePtr *> join_tree_node_ptrs_to_process_queue; |
| 4010 | join_tree_node_ptrs_to_process_queue.push_back(&join_tree_node); |
| 4011 | |
| 4012 | while (!join_tree_node_ptrs_to_process_queue.empty()) |
| 4013 | { |
| 4014 | auto * current_join_tree_node_ptr = join_tree_node_ptrs_to_process_queue.front(); |
| 4015 | join_tree_node_ptrs_to_process_queue.pop_front(); |
| 4016 | |
| 4017 | auto & current_join_tree_node = *current_join_tree_node_ptr; |
| 4018 | auto current_join_tree_node_type = current_join_tree_node->getNodeType(); |
| 4019 | |
| 4020 | switch (current_join_tree_node_type) |
| 4021 | { |
| 4022 | case QueryTreeNodeType::IDENTIFIER: |
| 4023 | { |
| 4024 | auto & from_table_identifier = current_join_tree_node->as<IdentifierNode &>(); |
| 4025 | auto table_identifier_lookup = IdentifierLookup{from_table_identifier.getIdentifier(), IdentifierLookupContext::TABLE_EXPRESSION}; |
| 4026 | if (current_join_tree_node->hasOriginalAST()) |
| 4027 | table_identifier_lookup.original_ast_node = current_join_tree_node->getOriginalAST(); |
| 4028 | |
| 4029 | auto from_table_identifier_alias = from_table_identifier.getAlias(); |
| 4030 | |
| 4031 | IdentifierResolveContext resolve_settings; |
| 4032 | /// In join tree initialization ignore join tree as identifier lookup source |
| 4033 | resolve_settings.allow_to_check_join_tree = false; |
| 4034 | /** Disable resolve of subquery during identifier resolution. |
| 4035 | * Example: SELECT * FROM (SELECT 1) AS t1, t1; |
| 4036 | * During `t1` identifier resolution we resolve it into subquery SELECT 1, but we want to disable |
| 4037 | * subquery resolution at this stage, because JOIN TREE of parent query is not resolved. |
| 4038 | */ |
| 4039 | resolve_settings.allow_to_resolve_subquery_during_identifier_resolution = false; |
| 4040 | |
| 4041 | scope.pushExpressionNode(current_join_tree_node); |
| 4042 | |
| 4043 | auto table_identifier_resolve_result = tryResolveIdentifier(table_identifier_lookup, scope, resolve_settings); |
| 4044 | |
| 4045 | scope.popExpressionNode(); |
| 4046 | |
| 4047 | auto resolved_identifier = table_identifier_resolve_result.resolved_identifier; |
| 4048 | |
| 4049 | if (!resolved_identifier) |
| 4050 | { |
| 4051 | /// Suggest a similar table name, possibly from another database (e.g. |
| 4052 | /// `system.functions` for a bare `functions`), matching the old analyzer's hint. |
| 4053 | auto [hint_database_name, hint_table_name] |
| 4054 | = IdentifierResolver::tryGetTableNameHint(from_table_identifier.getIdentifier(), scope.context); |
| 4055 | if (!hint_database_name.empty()) |
| 4056 | throw Exception(ErrorCodes::UNKNOWN_TABLE, |
| 4057 | "Unknown table expression identifier '{}' in scope {}. Maybe you meant {}.{}?", |
| 4058 | from_table_identifier.getIdentifier().getFullName(), |
| 4059 | scope.scope_node->formatASTForErrorMessage(), |
| 4060 | backQuoteIfNeed(hint_database_name), |
| 4061 | backQuoteIfNeed(hint_table_name)); |
| 4062 | throw Exception(ErrorCodes::UNKNOWN_TABLE, |
| 4063 | "Unknown table expression identifier '{}' in scope {}", |
| 4064 | from_table_identifier.getIdentifier().getFullName(), |
nothing calls this directly
no test coverage detected