This is an automated email from the ASF dual-hosted git repository.

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e4130d17892 [fix](merge into) result wrong when on clause contains 
null safe equal (#58091)
e4130d17892 is described below

commit e4130d178929844a25eda69e2ea63c0abca7d385
Author: morrySnow <[email protected]>
AuthorDate: Thu Nov 20 22:53:58 2025 +0800

    [fix](merge into) result wrong when on clause contains null safe equal 
(#58091)
    
    ### What problem does this PR solve?
    
    Related PR: #57044
    
    Problem Summary:
    
    meet error like:
    first_error_msg: column_name[__DORIS_DELETE_SIGN__], null value for not 
null column, type=TINYINT
---
 .../nereids/trees/plans/commands/merge/MergeIntoCommand.java  |  7 ++++---
 .../trees/plans/commands/merge/MergeIntoCommandTest.java      | 11 +++++++----
 regression-test/data/load_p0/merge_into/test_merge_into.out   |  4 ++++
 .../suites/load_p0/merge_into/test_merge_into.groovy          |  6 +++---
 4 files changed, 18 insertions(+), 10 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommand.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommand.java
index f1056666b53..b9bcbbc390c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommand.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommand.java
@@ -170,7 +170,7 @@ public class MergeIntoCommand extends Command implements 
ForwardWithSync, Explai
     /**
      * generate a branch number column to indicate this row matched witch 
branch
      */
-    private NamedExpression generateBranchLabel() {
+    private NamedExpression generateBranchLabel(NamedExpression deleteSign) {
         Expression matchedLabel = new NullLiteral(IntegerType.INSTANCE);
         for (int i = matchedClauses.size() - 1; i >= 0; i--) {
             MergeMatchedClause clause = matchedClauses.get(i);
@@ -197,7 +197,8 @@ public class MergeIntoCommand extends Command implements 
ForwardWithSync, Explai
                 notMatchedLabel = currentResult;
             }
         }
-        return new UnboundAlias(new If(onClause, matchedLabel, 
notMatchedLabel), BRANCH_LABEL);
+        return new UnboundAlias(new If(new Not(new IsNull(deleteSign)),
+                matchedLabel, notMatchedLabel), BRANCH_LABEL);
     }
 
     private List<Expression> generateDeleteProjection(List<Column> columns) {
@@ -462,11 +463,11 @@ public class MergeIntoCommand extends Command implements 
ForwardWithSync, Explai
         // generate a project to add delete sign, seq column, label and mark
         ImmutableList.Builder<NamedExpression> outputProjections = 
ImmutableList.builder();
         outputProjections.add(new UnboundStar(ImmutableList.of()));
-        outputProjections.add(generateBranchLabel());
         List<String> targetDeleteSignNameParts = 
Lists.newArrayList(targetNameInPlan);
         targetDeleteSignNameParts.add(Column.DELETE_SIGN);
         NamedExpression deleteSign = new 
UnboundSlot(targetDeleteSignNameParts);
         outputProjections.add(deleteSign);
+        outputProjections.add(generateBranchLabel(deleteSign));
         if (hasSequenceCol) {
             List<String> targetSeqColNameParts = 
Lists.newArrayList(targetNameInPlan);
             targetSeqColNameParts.add(Column.SEQUENCE_COL);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommandTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommandTest.java
index e1c3eb009f9..cc385d3912a 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommandTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/merge/MergeIntoCommandTest.java
@@ -34,7 +34,9 @@ import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.DefaultValueSlot;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
 import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.IsNull;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.expressions.Not;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.If;
 import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
@@ -134,17 +136,18 @@ public class MergeIntoCommandTest {
         MergeIntoCommand command = new MergeIntoCommand(
                 ImmutableList.of("ctl", "db", "tbl"), Optional.of("alias"), 
Optional.empty(),
                 source, onClause, matchedClauses, notMatchedClauses);
+        UnboundSlot unboundSlot = new UnboundSlot("alias", 
"__DORIS_DELETE_SIGN__");
 
         Class<?> clazz = 
Class.forName("org.apache.doris.nereids.trees.plans.commands.merge.MergeIntoCommand");
-        Method generateBranchLabel = 
clazz.getDeclaredMethod("generateBranchLabel");
+        Method generateBranchLabel = 
clazz.getDeclaredMethod("generateBranchLabel", NamedExpression.class);
         generateBranchLabel.setAccessible(true);
-        NamedExpression result = (NamedExpression) 
generateBranchLabel.invoke(command);
+        NamedExpression result = (NamedExpression) 
generateBranchLabel.invoke(command, unboundSlot);
         Expression matchedLabel = new If(new IntegerLiteral(1), new 
IntegerLiteral(0),
                 new If(new IntegerLiteral(2), new IntegerLiteral(1), new 
IntegerLiteral(2)));
         Expression notMatchedLabel = new If(new IntegerLiteral(3), new 
IntegerLiteral(3),
                 new If(new IntegerLiteral(4), new IntegerLiteral(4), new 
IntegerLiteral(5)));
-        NamedExpression expected = new UnboundAlias(new If(onClause, 
matchedLabel, notMatchedLabel),
-                "__DORIS_MERGE_INTO_BRANCH_LABEL__");
+        NamedExpression expected = new UnboundAlias(new If(new Not(new 
IsNull(unboundSlot)),
+                matchedLabel, notMatchedLabel), 
"__DORIS_MERGE_INTO_BRANCH_LABEL__");
         Assertions.assertEquals(expected, result);
     }
 
diff --git a/regression-test/data/load_p0/merge_into/test_merge_into.out 
b/regression-test/data/load_p0/merge_into/test_merge_into.out
index 04493ed5520..fac504ffd17 100644
--- a/regression-test/data/load_p0/merge_into/test_merge_into.out
+++ b/regression-test/data/load_p0/merge_into/test_merge_into.out
@@ -1,17 +1,21 @@
 -- This file is automatically generated. You should know what you did if you 
want to edit this
 -- !base_1 --
+\N     \N
 1      10
 3      33
 
 -- !seq_col_1 --
+\N     \N
 1      10
 3      33
 
 -- !seq_map_1 --
+\N     \N      2025-02-02
 1      10      2020-02-02
 3      33      2025-02-02
 
 -- !gen_col_1 --
+\N     \N      \N
 1      10      11
 3      33      36
 
diff --git a/regression-test/suites/load_p0/merge_into/test_merge_into.groovy 
b/regression-test/suites/load_p0/merge_into/test_merge_into.groovy
index 85c6ecfff52..0422be5954d 100644
--- a/regression-test/suites/load_p0/merge_into/test_merge_into.groovy
+++ b/regression-test/suites/load_p0/merge_into/test_merge_into.groovy
@@ -75,7 +75,7 @@ suite("test_merge_into") {
       "replication_allocation" = "tag.location.default: 1"
     );
     
-    INSERT INTO merge_into_source_table VALUES (1, 12), (2, 22), (3, 33);
+    INSERT INTO merge_into_source_table VALUES (1, 12), (2, 22), (3, 33), 
(null, null);
     INSERT INTO merge_into_target_base_table VALUES (1, 1), (2, 10);
     INSERT INTO merge_into_target_seq_col_table (c1, c2, 
__DORIS_SEQUENCE_COL__) VALUES (1, 1, '2020-02-02'), (2, 10, '2020-02-02');
     INSERT INTO merge_into_target_seq_map_table VALUES (1, 1, '2020-02-02'), 
(2, 10, '2020-02-02');
@@ -84,12 +84,12 @@ suite("test_merge_into") {
     SYNC;
     """
 
-    // base merge
+    // base merge, test null safe equals here
     sql """
         WITH tmp AS (SELECT * FROM merge_into_source_table)
         MERGE INTO merge_into_target_base_table t1
         USING tmp t2
-        ON t1.c1 = t2.c1
+        ON t1.c1 <=> t2.c1
         WHEN MATCHED AND t1.c2 = 10 THEN DELETE
         WHEN MATCHED THEN UPDATE SET c2 = 10
         WHEN NOT MATCHED THEN INSERT VALUES(t2.c1, t2.c2)


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

Reply via email to