morrySnow commented on code in PR #64718:
URL: https://github.com/apache/doris/pull/64718#discussion_r3465495683


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java:
##########
@@ -978,15 +980,61 @@ private LogicalPlan 
bindUsingJoin(MatchingContext<LogicalUsingJoin<Plan, Plan>>
             ExpressionAnalyzer rightExprAnalyzer = new ExpressionAnalyzer(
                     using, rightScope, cascadesContext, true, false);
             Expression usingRightSlot = rightExprAnalyzer.analyze(usingColumn, 
rewriteContext);
+            leftConjunctsSlots.add((Slot) usingLeftSlot);
             rightConjunctsSlots.add((Slot) usingRightSlot);
             hashEqExprs.add(new EqualTo(usingLeftSlot, usingRightSlot));
         }
 
-        return new LogicalJoin<>(
-                    using.getJoinType() == JoinType.CROSS_JOIN ? 
JoinType.INNER_JOIN : using.getJoinType(),
-                    hashEqExprs.build(), 
using.getMatchCondition().map(ImmutableList::of).orElse(ImmutableList.of()),
-                    using.getDistributeHint(), Optional.empty(), 
rightConjunctsSlots,
-                    using.children(), null);
+        JoinType joinType = using.getJoinType() == JoinType.CROSS_JOIN
+                ? JoinType.INNER_JOIN : using.getJoinType();
+        LogicalJoin<Plan, Plan> join = new LogicalJoin<>(joinType,
+                hashEqExprs.build(), 
using.getMatchCondition().map(ImmutableList::of).orElse(ImmutableList.of()),
+                using.getDistributeHint(), Optional.empty(),
+                using.children(), null);
+
+        // Build Project on top of join with correct merge key semantics
+        List<Slot> joinOutput = join.getOutput();
+        Set<Slot> leftUsingSlotSet = ImmutableSet.copyOf(leftConjunctsSlots);
+        Set<Slot> rightUsingSlotSet = ImmutableSet.copyOf(rightConjunctsSlots);
+
+        // Build project expressions: merged key(s) + all join output columns
+        ImmutableList.Builder<NamedExpression> projectExprs = 
ImmutableList.builder();
+
+        // 1. Add merged key columns (without qualifier)
+        for (int i = 0; i < leftConjunctsSlots.size(); i++) {
+            Slot leftSlot = leftConjunctsSlots.get(i);
+            Slot rightSlot = rightConjunctsSlots.get(i);
+            String colName = leftSlot.getName();
+            NamedExpression mergeExpr;
+            if (joinType.isFullOuterJoin()) {
+                // FULL OUTER JOIN: COALESCE(left, right)
+                mergeExpr = new Alias(new Coalesce(leftSlot, rightSlot), 
colName);
+            } else if (joinType.isRightJoin() || 
joinType.isRightSemiOrAntiJoin()) {
+                // RIGHT OUTER / RIGHT SEMI / RIGHT ANTI: use right side 
(preserved side)
+                mergeExpr = new Alias(rightSlot, colName);
+            } else {
+                // LEFT OUTER / INNER / LEFT SEMI / LEFT ANTI / CROSS: use 
left side
+                mergeExpr = new Alias(leftSlot, colName);
+            }
+            projectExprs.add(mergeExpr);
+        }
+
+        // 2. Pass through all join output columns (with original qualifiers)
+        for (Slot slot : joinOutput) {
+            projectExprs.add(slot);
+        }
+
+        // 3. Build exceptAsteriskOutputs: qualified USING columns from both 
sides
+        //    that are present in the join output (exclude them from SELECT *)

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to