From f2475136b4083cb9d1983e894280e636b76ab781 Mon Sep 17 00:00:00 2001 From: morrySnow <101034200+morrySnow@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:39:17 +0800 Subject: [PATCH] [fix](Nereids) set operation output nullable maybe wrong (#39109) (#39444) pick from master #39109 when first regulator child output nullable is not right, we may get wrong nullable output, and lead be crash --- .../nereids/rules/rewrite/AdjustNullable.java | 15 ++--- .../adjust_nullable/set_operation.groovy | 67 +++++++++++++++++-- 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AdjustNullable.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AdjustNullable.java index 03274defb751b1..b3c0d77b1e79be 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AdjustNullable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AdjustNullable.java @@ -26,7 +26,6 @@ import org.apache.doris.nereids.trees.expressions.OrderExpression; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.SlotReference; -import org.apache.doris.nereids.trees.expressions.functions.ExpressionTrait; import org.apache.doris.nereids.trees.expressions.functions.Function; import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; import org.apache.doris.nereids.trees.plans.Plan; @@ -57,7 +56,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; /** * because some rule could change output's nullable. @@ -145,8 +143,10 @@ public Plan visitLogicalSetOperation(LogicalSetOperation setOperation, Map> newChildrenOutputs = ImmutableList.builder(); List inputNullable = null; if (!setOperation.children().isEmpty()) { - inputNullable = setOperation.getRegularChildOutput(0).stream() - .map(ExpressionTrait::nullable).collect(Collectors.toList()); + inputNullable = Lists.newArrayListWithCapacity(setOperation.getOutputs().size()); + for (int i = 0; i < setOperation.getOutputs().size(); i++) { + inputNullable.add(false); + } for (int i = 0; i < setOperation.arity(); i++) { List childOutput = setOperation.child(i).getOutput(); List setChildOutput = setOperation.getRegularChildOutput(i); @@ -262,13 +262,6 @@ private Set updateExpressions(Set inputs, Map updateExpression(i, replaceMap)).collect(ImmutableSet.toImmutableSet()); } - private Map collectChildrenOutputMap(LogicalPlan plan) { - return plan.children().stream() - .map(Plan::getOutputSet) - .flatMap(Set::stream) - .collect(Collectors.toMap(NamedExpression::getExprId, s -> s)); - } - private static class SlotReferenceReplacer extends DefaultExpressionRewriter> { public static SlotReferenceReplacer INSTANCE = new SlotReferenceReplacer(); diff --git a/regression-test/suites/nereids_rules_p0/adjust_nullable/set_operation.groovy b/regression-test/suites/nereids_rules_p0/adjust_nullable/set_operation.groovy index 1eba278c6b4779..0d3017b939cb09 100644 --- a/regression-test/suites/nereids_rules_p0/adjust_nullable/set_operation.groovy +++ b/regression-test/suites/nereids_rules_p0/adjust_nullable/set_operation.groovy @@ -18,29 +18,84 @@ suite("test_set_operation_adjust_nullable") { sql """ - DROP TABLE IF EXISTS t1 + DROP TABLE IF EXISTS set_operation_t1 """ sql """ - DROP TABLE IF EXISTS t2 + DROP TABLE IF EXISTS set_operation_t2 """ sql """ - CREATE TABLE t1(c1 varchar) DISTRIBUTED BY hash(c1) PROPERTIES ("replication_num" = "1"); + CREATE TABLE set_operation_t1(c1 varchar) DISTRIBUTED BY hash(c1) PROPERTIES ("replication_num" = "1"); """ sql """ - CREATE TABLE t2(c2 date) DISTRIBUTED BY hash(c2) PROPERTIES ("replication_num" = "1"); + CREATE TABLE set_operation_t2(c2 date) DISTRIBUTED BY hash(c2) PROPERTIES ("replication_num" = "1"); """ sql """ - insert into t1 values('+06-00'); + insert into set_operation_t1 values('+06-00'); """ sql """ - insert into t2 values('1990-11-11'); + insert into set_operation_t2 values('1990-11-11'); """ sql """ SELECT c1, c1 FROM t1 EXCEPT SELECT c2, c2 FROM t2; """ + + // do not use regulator child output nullable as init nullable info + + sql """ + DROP TABLE IF EXISTS set_operation_t1 + """ + sql """ + DROP TABLE IF EXISTS set_operation_t2 + """ + + sql """ + create table set_operation_t1 ( + pk int, + c1 char(25) not null , + c2 varchar(100) null , + ) + distributed by hash(pk) buckets 10 + properties("replication_num" = "1"); + """ + + sql """insert into set_operation_t1 values (1, '1', '1');""" + + sql """ + create table set_operation_t2 ( + c3 varchar(100) not null , + pk int + ) + distributed by hash(pk) buckets 10 + properties("replication_num" = "1"); + """ + + sql """insert into set_operation_t2 values ('1', 1);""" + + sql """ + select + c2, + c1 + from + set_operation_t1 + order by + 1, + 2 asc + limit + 0 + union distinct + select + c3, + c3 + from + set_operation_t2 + except + select + 'LDvlqYTfrq', + 'rVdUjeSaJW'; + """ }