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]