Resolve expression node. * Argument node can be replaced with different node, or even with list node in case of matcher resolution. * Example: SELECT * FROM test_table; * * - is matcher node, and it can be resolved into ListNode. * * Steps: * 1. If node has alias, replace node with its value in scope alias map. Register alias in expression_aliases_in_resolve_process, to prevent resolvi
| 3047 | * 4. If node has alias, update its value in scope alias map. Deregister alias from expression_aliases_in_resolve_process. |
| 3048 | */ |
| 3049 | ProjectionNames QueryAnalyzer::resolveExpressionNode( |
| 3050 | QueryTreeNodePtr & node, |
| 3051 | IdentifierResolveScope & scope, |
| 3052 | bool allow_lambda_expression, |
| 3053 | bool allow_table_expression, |
| 3054 | bool ignore_alias, |
| 3055 | bool allow_niladic_functions) |
| 3056 | { |
| 3057 | checkStackSize(); |
| 3058 | |
| 3059 | auto resolved_expression_it = resolved_expressions.find(node); |
| 3060 | if (resolved_expression_it != resolved_expressions.end()) |
| 3061 | { |
| 3062 | /** There can be edge case, when subquery for IN function is resolved multiple times in different context. |
| 3063 | * SELECT id IN (subquery AS value), value FROM test_table; |
| 3064 | * When we start to resolve `value` identifier, subquery is already resolved but constant folding is not performed. |
| 3065 | */ |
| 3066 | auto node_type = node->getNodeType(); |
| 3067 | if (!allow_table_expression && (node_type == QueryTreeNodeType::QUERY || node_type == QueryTreeNodeType::UNION)) |
| 3068 | { |
| 3069 | IdentifierResolveScope & subquery_scope = createIdentifierResolveScope(node, &scope /*parent_scope*/); |
| 3070 | subquery_scope.subquery_depth = scope.subquery_depth + 1; |
| 3071 | |
| 3072 | evaluateScalarSubqueryIfNeeded(node, subquery_scope); |
| 3073 | } |
| 3074 | |
| 3075 | return resolved_expression_it->second; |
| 3076 | } |
| 3077 | |
| 3078 | String node_alias = node->getAlias(); |
| 3079 | ProjectionNames result_projection_names; |
| 3080 | |
| 3081 | if (node_alias.empty()) |
| 3082 | { |
| 3083 | auto projection_name_it = node_to_projection_name.find(node); |
| 3084 | if (projection_name_it != node_to_projection_name.end()) |
| 3085 | result_projection_names.push_back(projection_name_it->second); |
| 3086 | } |
| 3087 | else |
| 3088 | { |
| 3089 | result_projection_names.push_back(node_alias); |
| 3090 | /// Remove alias later. This needed to produce the same query tree subtree |
| 3091 | /// for expressions with aliaes to subexpression. Example: |
| 3092 | /// SELECT f(a as b) as c FROM t GROUP BY c |
| 3093 | if (!ignore_alias) |
| 3094 | scope.aliases.node_to_remove_aliases.push_back(node); |
| 3095 | } |
| 3096 | |
| 3097 | scope.pushExpressionNode(node); |
| 3098 | |
| 3099 | auto node_type = node->getNodeType(); |
| 3100 | |
| 3101 | switch (node_type) |
| 3102 | { |
| 3103 | case QueryTreeNodeType::IDENTIFIER: |
| 3104 | { |
| 3105 | auto & identifier_node = node->as<IdentifierNode &>(); |
| 3106 | auto unresolved_identifier = identifier_node.getIdentifier(); |
nothing calls this directly
no test coverage detected