|
1 | 1 | #include <Analyzer/ValidationUtils.h> |
2 | 2 |
|
3 | 3 | #include <Analyzer/AggregationUtils.h> |
| 4 | +#include <Analyzer/ArrayJoinNode.h> |
4 | 5 | #include <Analyzer/ColumnNode.h> |
5 | 6 | #include <Analyzer/ConstantNode.h> |
6 | 7 | #include <Analyzer/FunctionNode.h> |
7 | 8 | #include <Analyzer/InDepthQueryTreeVisitor.h> |
| 9 | +#include <Analyzer/JoinNode.h> |
8 | 10 | #include <Analyzer/QueryNode.h> |
9 | 11 | #include <Analyzer/TableNode.h> |
10 | 12 | #include <Analyzer/WindowFunctionsUtils.h> |
11 | 13 | #include <Storages/IStorage.h> |
12 | 14 |
|
| 15 | +#include <memory> |
| 16 | + |
13 | 17 | namespace DB |
14 | 18 | { |
15 | 19 |
|
16 | 20 | namespace ErrorCodes |
17 | 21 | { |
18 | | - extern const int NOT_AN_AGGREGATE; |
19 | | - extern const int NOT_IMPLEMENTED; |
20 | 22 | extern const int BAD_ARGUMENTS; |
21 | | - extern const int ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER; |
22 | 23 | extern const int ILLEGAL_PREWHERE; |
23 | | - extern const int UNSUPPORTED_METHOD; |
| 24 | + extern const int ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER; |
| 25 | + extern const int LOGICAL_ERROR; |
| 26 | + extern const int NOT_AN_AGGREGATE; |
| 27 | + extern const int NOT_IMPLEMENTED; |
24 | 28 | extern const int UNEXPECTED_EXPRESSION; |
| 29 | + extern const int UNSUPPORTED_METHOD; |
25 | 30 | } |
26 | 31 |
|
27 | 32 | namespace |
@@ -541,4 +546,76 @@ void validateCorrelatedSubqueries(const QueryTreeNodePtr & node) |
541 | 546 | } |
542 | 547 | } |
543 | 548 |
|
| 549 | +void validateFromClause(const QueryTreeNodePtr & node) |
| 550 | +{ |
| 551 | + const auto & root_query_node = node->as<QueryNode &>(); |
| 552 | + auto correlated_columns_set = root_query_node.getCorrelatedColumnsSet(); |
| 553 | + |
| 554 | + std::vector<QueryTreeNodePtr> nodes_to_process = { root_query_node.getJoinTree() }; |
| 555 | + |
| 556 | + while (!nodes_to_process.empty()) |
| 557 | + { |
| 558 | + auto node_to_process = std::move(nodes_to_process.back()); |
| 559 | + nodes_to_process.pop_back(); |
| 560 | + |
| 561 | + auto node_type = node_to_process->getNodeType(); |
| 562 | + |
| 563 | + switch (node_type) |
| 564 | + { |
| 565 | + case QueryTreeNodeType::TABLE: |
| 566 | + [[fallthrough]]; |
| 567 | + case QueryTreeNodeType::TABLE_FUNCTION: |
| 568 | + break; |
| 569 | + case QueryTreeNodeType::QUERY: |
| 570 | + { |
| 571 | + auto & query_node = node_to_process->as<QueryNode &>(); |
| 572 | + const auto & correlated_columns = query_node.getCorrelatedColumns(); |
| 573 | + for (const auto & column : correlated_columns) |
| 574 | + { |
| 575 | + if (!correlated_columns_set.contains(std::static_pointer_cast<ColumnNode>(column))) |
| 576 | + throw Exception(ErrorCodes::NOT_IMPLEMENTED, |
| 577 | + "Lateral joins are not supported. Correlated column '{}' is found in the FROM clause. In query {}", |
| 578 | + column->formatASTForErrorMessage(), |
| 579 | + node->formatASTForErrorMessage()); |
| 580 | + } |
| 581 | + break; |
| 582 | + } |
| 583 | + case QueryTreeNodeType::UNION: |
| 584 | + { |
| 585 | + for (const auto & union_node : node_to_process->as<UnionNode>()->getQueries().getNodes()) |
| 586 | + nodes_to_process.push_back(union_node); |
| 587 | + break; |
| 588 | + } |
| 589 | + case QueryTreeNodeType::ARRAY_JOIN: |
| 590 | + { |
| 591 | + auto & array_join_node = node_to_process->as<ArrayJoinNode &>(); |
| 592 | + nodes_to_process.push_back(array_join_node.getTableExpression()); |
| 593 | + break; |
| 594 | + } |
| 595 | + case QueryTreeNodeType::CROSS_JOIN: |
| 596 | + { |
| 597 | + auto & join_node = node_to_process->as<CrossJoinNode &>(); |
| 598 | + for (const auto & expr : std::ranges::reverse_view(join_node.getTableExpressions())) |
| 599 | + nodes_to_process.push_back(expr); |
| 600 | + break; |
| 601 | + } |
| 602 | + case QueryTreeNodeType::JOIN: |
| 603 | + { |
| 604 | + auto & join_node = node_to_process->as<JoinNode &>(); |
| 605 | + nodes_to_process.push_back(join_node.getRightTableExpression()); |
| 606 | + nodes_to_process.push_back(join_node.getLeftTableExpression()); |
| 607 | + break; |
| 608 | + } |
| 609 | + default: |
| 610 | + { |
| 611 | + throw Exception(ErrorCodes::LOGICAL_ERROR, |
| 612 | + "Unexpected node type for table expression. " |
| 613 | + "Expected table, table function, query, union, join or array join. Actual {}", |
| 614 | + node_to_process->getNodeTypeName()); |
| 615 | + } |
| 616 | + } |
| 617 | + } |
| 618 | + |
| 619 | +} |
| 620 | + |
544 | 621 | } |
0 commit comments