|
1 | | -#include <Interpreters/ProcessorsProfileLog.h> |
2 | 1 | #include <Common/FieldVisitorToString.h> |
3 | 2 |
|
4 | 3 | #include <Columns/ColumnNullable.h> |
|
21 | 20 | #include <Functions/exists.h> |
22 | 21 | #include <Functions/grouping.h> |
23 | 22 |
|
24 | | -#include <TableFunctions/TableFunctionFactory.h> |
25 | 23 | #include <Formats/FormatFactory.h> |
26 | 24 |
|
| 25 | +#include <TableFunctions/TableFunctionFactory.h> |
| 26 | + |
27 | 27 | #include <Storages/IStorage.h> |
28 | 28 | #include <Storages/StorageJoin.h> |
29 | 29 |
|
30 | | -#include <Interpreters/misc.h> |
31 | 30 | #include <Interpreters/convertFieldToType.h> |
| 31 | +#include <Interpreters/misc.h> |
32 | 32 | #include <Interpreters/ExternalDictionariesLoader.h> |
33 | 33 | #include <Interpreters/InterpreterSelectQueryAnalyzer.h> |
| 34 | +#include <Interpreters/ProcessorsProfileLog.h> |
34 | 35 |
|
35 | 36 | #include <Processors/Executors/PullingAsyncPipelineExecutor.h> |
36 | 37 |
|
|
62 | 63 | #include <Analyzer/FunctionSecretArgumentsFinderTreeNode.h> |
63 | 64 | #include <Analyzer/RecursiveCTE.h> |
64 | 65 |
|
| 66 | +#include <Analyzer/Resolve/CorrelatedColumnsCollector.h> |
65 | 67 | #include <Analyzer/Resolve/IdentifierResolveScope.h> |
66 | 68 | #include <Analyzer/Resolve/QueryAnalyzer.h> |
67 | 69 | #include <Analyzer/Resolve/QueryExpressionsAliasVisitor.h> |
|
70 | 72 | #include <Analyzer/Resolve/TableFunctionsWithClusterAlternativesVisitor.h> |
71 | 73 | #include <Analyzer/Resolve/TypoCorrection.h> |
72 | 74 |
|
73 | | -#include <Planner/PlannerActionsVisitor.h> |
74 | | - |
75 | 75 | #include <Core/Settings.h> |
76 | 76 |
|
| 77 | +#include <ranges> |
| 78 | + |
77 | 79 | namespace ProfileEvents |
78 | 80 | { |
79 | 81 | extern const Event ScalarSubqueriesGlobalCacheHit; |
@@ -162,7 +164,7 @@ QueryAnalyzer::~QueryAnalyzer() = default; |
162 | 164 |
|
163 | 165 | void QueryAnalyzer::resolve(QueryTreeNodePtr & node, const QueryTreeNodePtr & table_expression, ContextPtr context) |
164 | 166 | { |
165 | | - IdentifierResolveScope scope(node, nullptr /*parent_scope*/); |
| 167 | + IdentifierResolveScope & scope = createIdentifierResolveScope(node, /*parent_scope=*/ nullptr); |
166 | 168 |
|
167 | 169 | if (!scope.context) |
168 | 170 | scope.context = context; |
@@ -232,7 +234,7 @@ void QueryAnalyzer::resolve(QueryTreeNodePtr & node, const QueryTreeNodePtr & ta |
232 | 234 |
|
233 | 235 | void QueryAnalyzer::resolveConstantExpression(QueryTreeNodePtr & node, const QueryTreeNodePtr & table_expression, ContextPtr context) |
234 | 236 | { |
235 | | - IdentifierResolveScope scope(node, nullptr /*parent_scope*/); |
| 237 | + IdentifierResolveScope & scope = createIdentifierResolveScope(node, /*parent_scope=*/ nullptr); |
236 | 238 |
|
237 | 239 | if (!scope.context) |
238 | 240 | scope.context = context; |
@@ -293,6 +295,12 @@ std::optional<JoinTableSide> QueryAnalyzer::getColumnSideFromJoinTree(const Quer |
293 | 295 | return {}; |
294 | 296 | } |
295 | 297 |
|
| 298 | +IdentifierResolveScope & QueryAnalyzer::createIdentifierResolveScope(const QueryTreeNodePtr & scope_node, IdentifierResolveScope * parent_scope) |
| 299 | +{ |
| 300 | + auto [it, _] = node_to_scope_map.emplace(scope_node, IdentifierResolveScope{scope_node, parent_scope}); |
| 301 | + return it->second; |
| 302 | +} |
| 303 | + |
296 | 304 | ProjectionName QueryAnalyzer::calculateFunctionProjectionName(const QueryTreeNodePtr & function_node, const ProjectionNames & parameters_projection_names, |
297 | 305 | const ProjectionNames & arguments_projection_names) |
298 | 306 | { |
@@ -1382,31 +1390,16 @@ IdentifierResolveResult QueryAnalyzer::tryResolveIdentifierInParentScopes(const |
1382 | 1390 | if (identifier_lookup.isFunctionLookup()) |
1383 | 1391 | return resolve_result; |
1384 | 1392 |
|
1385 | | - QueryTreeNodes nodes_to_process = { resolved_identifier }; |
1386 | | - while (!nodes_to_process.empty()) |
| 1393 | + CorrelatedColumnsCollector correlated_columns_collector{resolved_identifier, identifier_resolve_context.scope_to_resolve_alias_expression, node_to_scope_map}; |
| 1394 | + if (correlated_columns_collector.has() && !scope.context->getSettingsRef()[Setting::allow_experimental_correlated_subqueries]) |
1387 | 1395 | { |
1388 | | - auto current = nodes_to_process.back(); |
1389 | | - nodes_to_process.pop_back(); |
1390 | | - if (current->getNodeType() == QueryTreeNodeType::COLUMN) |
1391 | | - { |
1392 | | - auto is_correlated_column = checkCorrelatedColumn(&scope, current); |
1393 | | - if (is_correlated_column && !scope.context->getSettingsRef()[Setting::allow_experimental_correlated_subqueries]) |
1394 | | - { |
1395 | | - throw Exception(ErrorCodes::UNSUPPORTED_METHOD, |
1396 | | - "Resolved identifier '{}' in parent scope to expression '{}' with correlated column '{}'" |
1397 | | - " (Enable 'allow_experimental_correlated_subqueries' setting to allow correlated subqueries execution). In scope {}", |
1398 | | - identifier_lookup.identifier.getFullName(), |
1399 | | - resolved_identifier->formatASTForErrorMessage(), |
1400 | | - current->as<ColumnNode>()->getColumnName(), |
1401 | | - scope.scope_node->formatASTForErrorMessage()); |
1402 | | - } |
1403 | | - } |
1404 | | - |
1405 | | - for (const auto & child : current->getChildren()) |
1406 | | - { |
1407 | | - if (child) |
1408 | | - nodes_to_process.push_back(child); |
1409 | | - } |
| 1396 | + throw Exception(ErrorCodes::UNSUPPORTED_METHOD, |
| 1397 | + "Resolved identifier '{}' in parent scope to expression '{}' with correlated columns '{}'" |
| 1398 | + " (Enable 'allow_experimental_correlated_subqueries' setting to allow correlated subqueries execution). In scope {}", |
| 1399 | + identifier_lookup.identifier.getFullName(), |
| 1400 | + resolved_identifier->formatASTForErrorMessage(), |
| 1401 | + fmt::join(correlated_columns_collector.get() | std::views::transform([](const auto & e) { return e->template as<ColumnNode>()->getColumnName(); }), "', '"), |
| 1402 | + scope.scope_node->formatASTForErrorMessage()); |
1410 | 1403 | } |
1411 | 1404 |
|
1412 | 1405 | return resolve_result; |
@@ -2317,7 +2310,7 @@ ProjectionNames QueryAnalyzer::resolveMatcher(QueryTreeNodePtr & matcher_node, I |
2317 | 2310 | if (apply_transformer->getApplyTransformerType() == ApplyColumnTransformerType::LAMBDA) |
2318 | 2311 | { |
2319 | 2312 | auto lambda_expression_to_resolve = expression_node->clone(); |
2320 | | - IdentifierResolveScope lambda_scope(expression_node, &scope /*parent_scope*/); |
| 2313 | + auto & lambda_scope = createIdentifierResolveScope(lambda_expression_to_resolve, /*parent_scope=*/&scope); |
2321 | 2314 | node_projection_names = resolveLambda(expression_node, lambda_expression_to_resolve, {node}, lambda_scope); |
2322 | 2315 | auto & lambda_expression_to_resolve_typed = lambda_expression_to_resolve->as<LambdaNode &>(); |
2323 | 2316 | node = lambda_expression_to_resolve_typed.getExpression(); |
@@ -3111,7 +3104,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi |
3111 | 3104 | auto first_argument_type = in_first_argument->getNodeType(); |
3112 | 3105 | if (first_argument_type == QueryTreeNodeType::QUERY || first_argument_type == QueryTreeNodeType::UNION) |
3113 | 3106 | { |
3114 | | - IdentifierResolveScope subquery_scope(in_first_argument, &scope /*parent_scope*/); |
| 3107 | + IdentifierResolveScope & subquery_scope = createIdentifierResolveScope(in_first_argument, &scope /*parent_scope*/); |
3115 | 3108 | subquery_scope.subquery_depth = scope.subquery_depth + 1; |
3116 | 3109 |
|
3117 | 3110 | evaluateScalarSubqueryIfNeeded(in_first_argument, subquery_scope); |
@@ -3240,7 +3233,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi |
3240 | 3233 |
|
3241 | 3234 | auto lambda_expression_clone = lambda_expression_untyped->clone(); |
3242 | 3235 |
|
3243 | | - IdentifierResolveScope lambda_scope(lambda_expression_clone, &scope /*parent_scope*/); |
| 3236 | + IdentifierResolveScope & lambda_scope = createIdentifierResolveScope(lambda_expression_clone, &scope /*parent_scope*/); |
3244 | 3237 | ProjectionNames lambda_projection_names = resolveLambda(lambda_expression_untyped, lambda_expression_clone, function_arguments, lambda_scope); |
3245 | 3238 |
|
3246 | 3239 | auto & resolved_lambda = lambda_expression_clone->as<LambdaNode &>(); |
@@ -3488,7 +3481,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi |
3488 | 3481 | QueryTreeNodes lambda_arguments; |
3489 | 3482 | lambda_arguments.reserve(lambda_arguments_size); |
3490 | 3483 |
|
3491 | | - IdentifierResolveScope lambda_scope(lambda_to_resolve, &scope /*parent_scope*/); |
| 3484 | + IdentifierResolveScope & lambda_scope = createIdentifierResolveScope(lambda_to_resolve, &scope /*parent_scope*/); |
3492 | 3485 | for (size_t i = 0; i < lambda_arguments_size; ++i) |
3493 | 3486 | { |
3494 | 3487 | const auto & argument_type = function_data_type_argument_types[i]; |
@@ -3715,7 +3708,7 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode( |
3715 | 3708 | auto node_type = node->getNodeType(); |
3716 | 3709 | if (!allow_table_expression && (node_type == QueryTreeNodeType::QUERY || node_type == QueryTreeNodeType::UNION)) |
3717 | 3710 | { |
3718 | | - IdentifierResolveScope subquery_scope(node, &scope /*parent_scope*/); |
| 3711 | + IdentifierResolveScope & subquery_scope = createIdentifierResolveScope(node, &scope /*parent_scope*/); |
3719 | 3712 | subquery_scope.subquery_depth = scope.subquery_depth + 1; |
3720 | 3713 |
|
3721 | 3714 | evaluateScalarSubqueryIfNeeded(node, subquery_scope); |
@@ -3790,7 +3783,7 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode( |
3790 | 3783 | else |
3791 | 3784 | union_node->setIsCTE(false); |
3792 | 3785 |
|
3793 | | - IdentifierResolveScope subquery_scope(resolved_identifier_node, &scope /*parent_scope*/); |
| 3786 | + IdentifierResolveScope & subquery_scope = createIdentifierResolveScope(resolved_identifier_node, &scope /*parent_scope*/); |
3794 | 3787 | subquery_scope.subquery_depth = scope.subquery_depth + 1; |
3795 | 3788 |
|
3796 | 3789 | /// CTE is being resolved, it's required to forbid to resolve to it again |
@@ -3927,7 +3920,7 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode( |
3927 | 3920 | [[fallthrough]]; |
3928 | 3921 | case QueryTreeNodeType::UNION: |
3929 | 3922 | { |
3930 | | - IdentifierResolveScope subquery_scope(node, &scope /*parent_scope*/); |
| 3923 | + IdentifierResolveScope & subquery_scope = createIdentifierResolveScope(node, &scope /*parent_scope*/); |
3931 | 3924 | subquery_scope.subquery_depth = scope.subquery_depth + 1; |
3932 | 3925 |
|
3933 | 3926 | std::string projection_name = "_subquery_" + std::to_string(subquery_counter); |
@@ -4356,7 +4349,7 @@ void QueryAnalyzer::resolveInterpolateColumnsNodeList(QueryTreeNodePtr & interpo |
4356 | 4349 | bool is_column_constant = interpolate_node_typed.getExpression()->getNodeType() == QueryTreeNodeType::CONSTANT; |
4357 | 4350 |
|
4358 | 4351 | auto & interpolation_to_resolve = interpolate_node_typed.getInterpolateExpression(); |
4359 | | - IdentifierResolveScope interpolate_scope(interpolation_to_resolve, &scope /*parent_scope*/); |
| 4352 | + IdentifierResolveScope & interpolate_scope = createIdentifierResolveScope(interpolation_to_resolve, &scope /*parent_scope*/); |
4360 | 4353 |
|
4361 | 4354 | auto fake_column_node = std::make_shared<ColumnNode>(NameAndTypePair(column_to_interpolate_name, interpolate_node_typed.getExpression()->getResultType()), interpolate_node); |
4362 | 4355 | if (is_column_constant) |
@@ -4661,7 +4654,7 @@ void QueryAnalyzer::initializeTableExpressionData(const QueryTreeNodePtr & table |
4661 | 4654 | */ |
4662 | 4655 | alias_column_to_resolve = column_name_to_column_node[alias_column_to_resolve_name]; |
4663 | 4656 |
|
4664 | | - IdentifierResolveScope alias_column_resolve_scope(alias_column_to_resolve, nullptr /*parent_scope*/); |
| 4657 | + IdentifierResolveScope & alias_column_resolve_scope = createIdentifierResolveScope(alias_column_to_resolve, &scope /*parent_scope*/); |
4665 | 4658 | alias_column_resolve_scope.column_name_to_column_node = std::move(column_name_to_column_node); |
4666 | 4659 | alias_column_resolve_scope.context = scope.context; |
4667 | 4660 |
|
@@ -5282,7 +5275,7 @@ void QueryAnalyzer::resolveJoin(QueryTreeNodePtr & join_node, IdentifierResolveS |
5282 | 5275 | left_subquery->getProjection().getNodes().push_back(projection_node->clone()); |
5283 | 5276 | left_subquery->getJoinTree() = left_table_expression; |
5284 | 5277 |
|
5285 | | - IdentifierResolveScope left_subquery_scope(left_subquery, nullptr /*parent_scope*/); |
| 5278 | + IdentifierResolveScope & left_subquery_scope = createIdentifierResolveScope(left_subquery, nullptr /*parent_scope*/); |
5286 | 5279 | resolveQuery(left_subquery, left_subquery_scope); |
5287 | 5280 |
|
5288 | 5281 | const auto & resolved_nodes = left_subquery->getProjection().getNodes(); |
@@ -5905,7 +5898,7 @@ void QueryAnalyzer::resolveUnion(const QueryTreeNodePtr & union_node, Identifier |
5905 | 5898 | auto & non_recursive_query_mutable_context = non_recursive_query_is_query_node ? non_recursive_query->as<QueryNode &>().getMutableContext() |
5906 | 5899 | : non_recursive_query->as<UnionNode &>().getMutableContext(); |
5907 | 5900 |
|
5908 | | - IdentifierResolveScope non_recursive_subquery_scope(non_recursive_query, &scope /*parent_scope*/); |
| 5901 | + IdentifierResolveScope & non_recursive_subquery_scope = createIdentifierResolveScope(non_recursive_query, &scope /*parent_scope*/); |
5909 | 5902 | non_recursive_subquery_scope.subquery_depth = scope.subquery_depth + 1; |
5910 | 5903 |
|
5911 | 5904 | if (non_recursive_query_is_query_node) |
@@ -5936,7 +5929,7 @@ void QueryAnalyzer::resolveUnion(const QueryTreeNodePtr & union_node, Identifier |
5936 | 5929 | { |
5937 | 5930 | auto & query_node = queries_nodes[i]; |
5938 | 5931 |
|
5939 | | - IdentifierResolveScope subquery_scope(query_node, &scope /*parent_scope*/); |
| 5932 | + IdentifierResolveScope & subquery_scope = createIdentifierResolveScope(query_node, &scope /*parent_scope*/); |
5940 | 5933 |
|
5941 | 5934 | if (recursive_cte_table_node) |
5942 | 5935 | subquery_scope.expression_argument_name_to_node[union_node_typed.getCTEName()] = recursive_cte_table_node; |
|
0 commit comments