Resolve join node in scope
| 5141 | |
| 5142 | /// Resolve join node in scope |
| 5143 | void QueryAnalyzer::resolveJoin(QueryTreeNodePtr & join_node, IdentifierResolveScope & scope, QueryExpressionsAliasVisitor & expressions_visitor) |
| 5144 | { |
| 5145 | checkStackSize(); |
| 5146 | |
| 5147 | auto & join_node_typed = join_node->as<JoinNode &>(); |
| 5148 | |
| 5149 | resolveQueryJoinTreeNode(join_node_typed.getLeftTableExpression(), scope, expressions_visitor); |
| 5150 | validateJoinTableExpressionWithoutAlias(join_node, join_node_typed.getLeftTableExpression(), scope); |
| 5151 | |
| 5152 | resolveQueryJoinTreeNode(join_node_typed.getRightTableExpression(), scope, expressions_visitor); |
| 5153 | validateJoinTableExpressionWithoutAlias(join_node, join_node_typed.getRightTableExpression(), scope); |
| 5154 | |
| 5155 | if (isCorrelatedQueryOrUnionNode(join_node_typed.getLeftTableExpression())) |
| 5156 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, |
| 5157 | "Correlated subqueries are not supported in JOINs yet, but found in expression: {}", |
| 5158 | join_node_typed.getLeftTableExpression()->formatASTForErrorMessage()); |
| 5159 | |
| 5160 | if (isCorrelatedQueryOrUnionNode(join_node_typed.getRightTableExpression())) |
| 5161 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, |
| 5162 | "Correlated subqueries are not supported in JOINs yet, but found in expression: {}", |
| 5163 | join_node_typed.getRightTableExpression()->formatASTForErrorMessage()); |
| 5164 | |
| 5165 | if (!join_node_typed.getLeftTableExpression()->hasAlias() && !join_node_typed.getRightTableExpression()->hasAlias()) |
| 5166 | checkDuplicateTableNamesOrAliasForPasteJoin(join_node_typed, scope); |
| 5167 | |
| 5168 | if (join_node_typed.isNaturalJoin()) |
| 5169 | { |
| 5170 | /// Synthesize a USING expression from the intersection of left and right column names. |
| 5171 | Names left_cols; |
| 5172 | NameSet right_cols; |
| 5173 | |
| 5174 | if (!getOrderedColumnsFromTableExpression(join_node_typed.getLeftTableExpression(), left_cols)) |
| 5175 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, |
| 5176 | "NATURAL JOIN: cannot determine columns of left table expression in {}", |
| 5177 | join_node_typed.formatASTForErrorMessage()); |
| 5178 | |
| 5179 | if (!getColumnsFromTableExpression(join_node_typed.getRightTableExpression(), right_cols)) |
| 5180 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, |
| 5181 | "NATURAL JOIN: cannot determine columns of right table expression in {}", |
| 5182 | join_node_typed.formatASTForErrorMessage()); |
| 5183 | |
| 5184 | QueryTreeNodes using_nodes; |
| 5185 | NameSet seen; |
| 5186 | for (const auto & col_name : left_cols) |
| 5187 | { |
| 5188 | /// Skip sub-columns (e.g. name.size) — NATURAL JOIN only matches top-level columns. |
| 5189 | if (col_name.find('.') != std::string::npos) |
| 5190 | continue; |
| 5191 | |
| 5192 | if (right_cols.contains(col_name) && !seen.contains(col_name)) |
| 5193 | { |
| 5194 | seen.insert(col_name); |
| 5195 | using_nodes.push_back(std::make_shared<IdentifierNode>(Identifier(col_name))); |
| 5196 | } |
| 5197 | } |
| 5198 | |
| 5199 | if (using_nodes.empty()) |
| 5200 | { |
nothing calls this directly
no test coverage detected