MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / resolveExpressionNode

Method resolveExpressionNode

src/Analyzer/Resolve/QueryAnalyzer.cpp:3049–3522  ·  view source on GitHub ↗

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

Source from the content-addressed store, hash-verified

3047 * 4. If node has alias, update its value in scope alias map. Deregister alias from expression_aliases_in_resolve_process.
3048 */
3049ProjectionNames 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();

Callers

nothing calls this directly

Calls 15

checkStackSizeFunction · 0.85
backQuoteFunction · 0.85
toStringLowercaseFunction · 0.85
validateTreeSizeFunction · 0.85
pushExpressionNodeMethod · 0.80
hasOriginalASTMethod · 0.80
isMaterializedCTEMethod · 0.80

Tested by

no test coverage detected