github-actions[bot] commented on code in PR #64718:
URL: https://github.com/apache/doris/pull/64718#discussion_r3459284858


##########
regression-test/suites/query_p0/join/test_using_join_merge_key.groovy:
##########
@@ -0,0 +1,130 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_using_join_merge_key", "query_p0") {
+    order_qt_left_outer """
+        SELECT l.k, r.k, k, l.*, r.*, *
+        FROM (
+            SELECT 1 AS k, 'l1' AS v1
+            UNION ALL SELECT 2, 'l2'
+            UNION ALL SELECT 4, 'l4'
+        ) l
+        LEFT OUTER JOIN (
+            SELECT 2 AS k, 'r2' AS v2
+            UNION ALL SELECT 3, 'r3'
+            UNION ALL SELECT 4, 'r4'
+        ) r USING(k)
+    """
+
+    order_qt_right_outer """
+        SELECT l.k, r.k, k, l.*, r.*, *
+        FROM (
+            SELECT 1 AS k, 'l1' AS v1
+            UNION ALL SELECT 2, 'l2'
+            UNION ALL SELECT 4, 'l4'
+        ) l
+        RIGHT OUTER JOIN (
+            SELECT 2 AS k, 'r2' AS v2
+            UNION ALL SELECT 3, 'r3'
+            UNION ALL SELECT 4, 'r4'
+        ) r USING(k)
+    """
+
+    order_qt_full_outer """
+        SELECT l.k, r.k, k, l.*, r.*, *
+        FROM (
+            SELECT 1 AS k, 'l1' AS v1
+            UNION ALL SELECT 2, 'l2'
+            UNION ALL SELECT 4, 'l4'
+        ) l
+        FULL OUTER JOIN (
+            SELECT 2 AS k, 'r2' AS v2
+            UNION ALL SELECT 3, 'r3'
+            UNION ALL SELECT 4, 'r4'
+        ) r USING(k)
+    """
+
+    order_qt_left_semi """
+        SELECT l.k, k, l.*, *
+        FROM (
+            SELECT 1 AS k, 'l1' AS v1
+            UNION ALL SELECT 2, 'l2'
+            UNION ALL SELECT 4, 'l4'
+        ) l
+        LEFT SEMI JOIN (
+            SELECT 2 AS k, 'r2' AS v2
+            UNION ALL SELECT 3, 'r3'
+            UNION ALL SELECT 4, 'r4'
+        ) r USING(k)
+    """
+
+    order_qt_right_semi """
+        SELECT r.k, k, r.*, * 

Review Comment:
   `git diff --check` fails on this new suite because this line, and the 
matching `right_anti` SELECT below, end with a trailing space after `*`. Please 
trim those trailing spaces so the patch passes whitespace checks.



##########
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:
   Because this only excludes the current join's USING slots, a chained USING 
join re-exposes qualified key columns hidden by the left child. In `t1 JOIN t2 
USING(a) JOIN t3 USING(a)`, the second join's left key is the first join's 
merged `a`, so `leftUsingSlotSet` does not include the hidden `t1.a`/`t2.a` 
slots that are still in `joinOutput`. They are passed through and not removed 
from this project's asterisk output, so `SELECT *` can return multiple `a` 
columns instead of the single merged key. Please carry forward child asterisk 
exclusions, for example by excluding `joinOutput - join.getAsteriskOutput()` or 
deriving pass-through star visibility from the child asterisk outputs, and add 
a result-shape regression for a chained USING join.



##########
regression-test/data/query_p0/join/test_using_join_merge_key.out:
##########
@@ -0,0 +1,35 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !left_outer --
+1      \N      1       1       l1      \N      \N      1       l1      \N
+2      2       2       2       l2      2       r2      2       l2      r2
+4      4       4       4       l4      4       r4      4       l4      r4
+
+-- !right_outer --
+\N     3       3       \N      \N      3       r3      3       \N      r3
+2      2       2       2       l2      2       r2      2       l2      r2
+4      4       4       4       l4      4       r4      4       l4      r4
+
+-- !full_outer --
+\N     3       3       \N      \N      3       r3      3       \N      r3
+1      \N      1       1       l1      \N      \N      1       l1      \N
+2      2       2       2       l2      2       r2      2       l2      r2
+4      4       4       4       l4      4       r4      4       l4      r4
+
+-- !left_semi --
+2      2       2       l2      2       l2
+4      4       4       l4      4       l4
+
+-- !right_semi --
+2      2       2       r2      2       r2
+4      4       4       r4      4       r4
+
+-- !left_anti --
+1      1       1       l1      1       l1
+
+-- !right_anti --
+3      3       3       r3      3       r3
+
+-- !inner --
+2      2       2       2       l2      2       r2      2       l2      r2
+4      4       4       4       l4      4       r4      4       l4      r4
+

Review Comment:
   `git diff --check` reports this extra blank line at EOF. Please 
regenerate/trim the expected output so the file ends after the last expected 
row with only the normal terminal newline.



-- 
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