| 1290 | } |
| 1291 | |
| 1292 | ScopePtr QueryAnalyzerVisitor::analyzeArrayJoin(ASTArrayJoin & array_join, ASTSelectQuery & select_query, ScopePtr source_scope) |
| 1293 | { |
| 1294 | ASTPtr array_join_expression_list = array_join.expression_list; |
| 1295 | if (array_join_expression_list->children.empty()) |
| 1296 | throw DB::Exception("ARRAY JOIN requires an argument", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); |
| 1297 | |
| 1298 | ExprAnalyzerOptions expr_options{"Array Join expression"}; |
| 1299 | expr_options.selectQuery(select_query) |
| 1300 | .subquerySupport(ExprAnalyzerOptions::SubquerySupport::DISALLOWED) |
| 1301 | .aggregateSupport(ExprAnalyzerOptions::AggregateSupport::DISALLOWED) |
| 1302 | .windowSupport(ExprAnalyzerOptions::WindowSupport::DISALLOWED); |
| 1303 | |
| 1304 | ArrayJoinDescriptions array_join_descs; |
| 1305 | FieldDescriptions output_fields = source_scope->getFields(); |
| 1306 | NameSet name_set; |
| 1307 | for (auto & array_join_expr : array_join_expression_list->children) |
| 1308 | { |
| 1309 | if (array_join_expr->tryGetAlias() == array_join_expr->getColumnName() && !array_join_expr->as<ASTIdentifier>()) |
| 1310 | throw Exception("No alias for non-trivial value in ARRAY JOIN: " + array_join_expr->tryGetAlias(), ErrorCodes::ALIAS_REQUIRED); |
| 1311 | |
| 1312 | String output_name = array_join_expr->getAliasOrColumnName(); |
| 1313 | if (name_set.count(output_name)) |
| 1314 | throw Exception("Duplicate alias in ARRAY JOIN: " + output_name, ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS); |
| 1315 | |
| 1316 | auto array_join_expr_type = ExprAnalyzer::analyze(array_join_expr, source_scope, context, analysis, expr_options); |
| 1317 | const auto array_type = getArrayJoinDataType(array_join_expr_type); |
| 1318 | if (!array_type) |
| 1319 | throw Exception("ARRAY JOIN requires array argument", ErrorCodes::TYPE_MISMATCH); |
| 1320 | |
| 1321 | auto col_ref = analysis.tryGetColumnReference(array_join_expr); |
| 1322 | // To determine if a scope is from outer query, we should use Scope::isLocalScope. |
| 1323 | // Practically, scopes belonging to FROM clause don't have parent scopes, so we can use operator== for convenience. |
| 1324 | if (col_ref && source_scope != col_ref->scope) |
| 1325 | throw Exception( |
| 1326 | "Outer query columns cannot be used in ARRAY JOIN: " + array_join_expr->getColumnName(), ErrorCodes::BAD_ARGUMENTS); |
| 1327 | |
| 1328 | ArrayJoinDescription array_join_desc; |
| 1329 | array_join_desc.expr = array_join_expr; |
| 1330 | |
| 1331 | if (col_ref && array_join_expr->tryGetAlias().empty()) // ARRAY JOIN `arr` |
| 1332 | { |
| 1333 | output_fields[col_ref->local_index] = FieldDescription{output_fields[col_ref->local_index].name, array_type->getNestedType()}; |
| 1334 | } |
| 1335 | else if (col_ref && !array_join_expr->tryGetAlias().empty() && array_join_expr->tryGetAlias() == output_fields[col_ref->local_index].name) // ARRAY JOIN `arr` as `arr` |
| 1336 | { |
| 1337 | output_fields[col_ref->local_index] = FieldDescription{output_fields[col_ref->local_index].name, array_type->getNestedType()}; |
| 1338 | } |
| 1339 | else // ARRAY JOIN `arr` as `arr2` |
| 1340 | { |
| 1341 | array_join_desc.create_new_field = true; |
| 1342 | output_fields.emplace_back(output_name, array_type->getNestedType()); |
| 1343 | } |
| 1344 | |
| 1345 | array_join_descs.emplace_back(std::move(array_join_desc)); |
| 1346 | } |
| 1347 | |
| 1348 | analysis.array_join_analysis[&select_query] = ArrayJoinAnalysis{(array_join.kind == ASTArrayJoin::Kind::Left), array_join_descs}; |
| 1349 | ScopePtr output_scope = createScope(output_fields); |
nothing calls this directly
no test coverage detected