3030#include < Analyzer/Resolve/TypoCorrection.h>
3131
3232#include < Core/Settings.h>
33+ #include < iostream>
3334
3435namespace DB
3536{
@@ -329,6 +330,21 @@ bool IdentifierResolver::tryBindIdentifierToAliases(const IdentifierLookup & ide
329330 return scope.aliases .find (identifier_lookup, ScopeAliases::FindOption::FIRST_NAME) != nullptr ;
330331}
331332
333+ bool IdentifierResolver::tryBindIdentifierToJoinUsingColumn (const IdentifierLookup & identifier_lookup, const IdentifierResolveScope & scope)
334+ {
335+ for (const auto * join_using : scope.join_using_columns )
336+ {
337+ for (const auto & [using_column_name, _] : *join_using)
338+ {
339+ // std::cerr << identifier_lookup.identifier.getFullName() << " <===========> " << using_column_name << std::endl;
340+ if (identifier_lookup.identifier .getFullName () == using_column_name)
341+ return true ;
342+ }
343+ }
344+
345+ return false ;
346+ }
347+
332348/* * Resolve identifier from table columns.
333349 *
334350 * 1. If table column nodes are empty or identifier is not expression lookup return nullptr.
@@ -634,11 +650,15 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromStorage(
634650 tryBindIdentifierToTableExpressions (column_identifier_lookup, table_expression_node, scope))
635651 break ;
636652
653+ if (tryBindIdentifierToJoinUsingColumn (column_identifier_lookup, scope))
654+ break ;
655+
637656 qualified_identifier = std::move (qualified_identifier_with_removed_part);
638657 }
639658
640659 auto qualified_identifier_full_name = qualified_identifier.getFullName ();
641660 node_to_projection_name.emplace (result_expression, std::move (qualified_identifier_full_name));
661+ // std::cerr << "resolved from storage : " << qualified_identifier.getFullName() << " as " << result_expression->dumpTree() << std::endl;
642662
643663 return { .resolved_identifier = result_expression, .resolve_place = IdentifierResolvePlace::JOIN_TREE };
644664}
@@ -857,8 +877,36 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromJoin(const I
857877 IdentifierResolveScope & scope)
858878{
859879 const auto & from_join_node = table_expression_node->as <const JoinNode &>();
860- auto left_resolved_identifier = tryResolveIdentifierFromJoinTreeNode (identifier_lookup, from_join_node.getLeftTableExpression (), scope).resolved_identifier ;
861- auto right_resolved_identifier = tryResolveIdentifierFromJoinTreeNode (identifier_lookup, from_join_node.getRightTableExpression (), scope).resolved_identifier ;
880+ JoinKind join_kind = from_join_node.getKind ();
881+
882+ bool join_node_in_resolve_process = scope.table_expressions_in_resolve_process .contains (table_expression_node.get ());
883+ std::unordered_map<std::string, ColumnNodePtr> join_using_column_name_to_column_node;
884+
885+ if (!join_node_in_resolve_process && from_join_node.isUsingJoinExpression ())
886+ {
887+ auto & join_using_list = from_join_node.getJoinExpression ()->as <ListNode &>();
888+ for (auto & join_using_node : join_using_list.getNodes ())
889+ {
890+ auto & column_node = join_using_node->as <ColumnNode &>();
891+ join_using_column_name_to_column_node.emplace (column_node.getColumnName (), std::static_pointer_cast<ColumnNode>(join_using_node));
892+ }
893+ }
894+
895+ auto try_resolve_identifier_from_join_tree_node = [&](const QueryTreeNodePtr & join_tree_node, bool may_be_override_by_using_column)
896+ {
897+ if (may_be_override_by_using_column && !join_using_column_name_to_column_node.empty ())
898+ scope.join_using_columns .push_back (&join_using_column_name_to_column_node);
899+
900+ auto res = tryResolveIdentifierFromJoinTreeNode (identifier_lookup, join_tree_node, scope);
901+
902+ if (may_be_override_by_using_column && !join_using_column_name_to_column_node.empty ())
903+ scope.join_using_columns .pop_back ();
904+
905+ return std::move (res.resolved_identifier );
906+ };
907+
908+ auto left_resolved_identifier = try_resolve_identifier_from_join_tree_node (from_join_node.getLeftTableExpression (), join_kind == JoinKind::Right);
909+ auto right_resolved_identifier = try_resolve_identifier_from_join_tree_node (from_join_node.getRightTableExpression (), join_kind != JoinKind::Right);
862910
863911 if (!identifier_lookup.isExpressionLookup ())
864912 {
@@ -875,20 +923,6 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromJoin(const I
875923 };
876924 }
877925
878- bool join_node_in_resolve_process = scope.table_expressions_in_resolve_process .contains (table_expression_node.get ());
879-
880- std::unordered_map<std::string, ColumnNodePtr> join_using_column_name_to_column_node;
881-
882- if (!join_node_in_resolve_process && from_join_node.isUsingJoinExpression ())
883- {
884- auto & join_using_list = from_join_node.getJoinExpression ()->as <ListNode &>();
885- for (auto & join_using_node : join_using_list.getNodes ())
886- {
887- auto & column_node = join_using_node->as <ColumnNode &>();
888- join_using_column_name_to_column_node.emplace (column_node.getColumnName (), std::static_pointer_cast<ColumnNode>(join_using_node));
889- }
890- }
891-
892926 auto check_nested_column_not_in_using = [&join_using_column_name_to_column_node, &identifier_lookup](const QueryTreeNodePtr & node)
893927 {
894928 /* * tldr: When an identifier is resolved into the function `nested` or `getSubcolumn`, and
@@ -950,8 +984,6 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromJoin(const I
950984 std::optional<JoinTableSide> resolved_side;
951985 QueryTreeNodePtr resolved_identifier;
952986
953- JoinKind join_kind = from_join_node.getKind ();
954-
955987 auto convert_resolved_result_type_if_needed = [](
956988 const QueryTreeNodePtr & resolved_identifier_candidate,
957989 const std::unordered_map<std::string, ColumnNodePtr> & using_column_name_to_column_node,
@@ -964,12 +996,16 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromJoin(const I
964996 if (using_column_node_it != using_column_name_to_column_node.end () &&
965997 !using_column_node_it->second ->getColumnType ()->equals (*resolved_column.getColumnType ()))
966998 {
999+ // std::cerr << "... fixing type for " << resolved_column.dumpTree() << std::endl;
9671000 auto resolved_column_clone = std::static_pointer_cast<ColumnNode>(resolved_column.clone ());
9681001 resolved_column_clone->setColumnType (using_column_node_it->second ->getColumnType ());
9691002
9701003 auto projection_name_it = projection_name_mapping.find (resolved_identifier_candidate);
9711004 if (projection_name_it != projection_name_mapping.end ())
1005+ {
9721006 projection_name_mapping[resolved_column_clone] = projection_name_it->second ;
1007+ // std::cerr << ".. upd name " << projection_name_it->second << " for col " << resolved_column_clone->dumpTree() << std::endl;
1008+ }
9731009
9741010 resolve_result = std::move (resolved_column_clone);
9751011
@@ -983,6 +1019,10 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromJoin(const I
9831019 if (auto missed_subcolumn_identifier = checkIsMissedObjectJSONSubcolumn (left_resolved_identifier, right_resolved_identifier))
9841020 return { .resolved_identifier = missed_subcolumn_identifier, .resolve_place = IdentifierResolvePlace::JOIN_TREE };
9851021
1022+
1023+ // for (const auto & [k, v] : join_using_column_name_to_column_node)
1024+ // std::cerr << k << " -> " << v->dumpTree() << std::endl;
1025+
9861026 if (left_resolved_identifier && right_resolved_identifier)
9871027 {
9881028 auto using_column_node_it = join_using_column_name_to_column_node.end ();
@@ -1092,10 +1132,12 @@ IdentifierResolveResult IdentifierResolver::tryResolveIdentifierFromJoin(const I
10921132 auto nullable_resolved_identifier = convertJoinedColumnTypeToNullIfNeeded (resolved_identifier, join_kind, resolved_side, scope);
10931133 if (nullable_resolved_identifier)
10941134 {
1135+ // std::cerr << ".. convert to null " << nullable_resolved_identifier->dumpTree() << std::endl;
10951136 resolved_identifier = nullable_resolved_identifier;
10961137 // / Set the same projection name for new nullable node
10971138 if (projection_name_it != node_to_projection_name.end ())
10981139 {
1140+ // std::cerr << "... upd name for null " << projection_name_it->second << " -> " << resolved_identifier->dumpTree() << std::endl;
10991141 node_to_projection_name.emplace (resolved_identifier, projection_name_it->second );
11001142 }
11011143 }
0 commit comments