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 50742d6e19d [fix](nereids) AdjustNullable rule should handle union node with no children (#35074) 50742d6e19d is described below commit 50742d6e19dd76b0e288b0c8152bce49cebe13a2 Author: starocean999 <40539150+starocean...@users.noreply.github.com> AuthorDate: Fri May 24 14:33:12 2024 +0800 [fix](nereids) AdjustNullable rule should handle union node with no children (#35074) The output slot's nullable info is not correctly calculated in union node. Because old code only get correct result if union node has children. But the union node may have no children but only have constantExprList. So in that case, we should calculate output's nullable info byboth children and constantExprList. --- .../nereids/rules/rewrite/AdjustNullable.java | 54 +++++++++++++--------- .../rules/rewrite/PushProjectIntoUnion.java | 5 +- .../nereids/trees/plans/logical/LogicalUnion.java | 7 +++ .../nereids_syntax_p0/adjust_nullable.groovy | 18 ++++++++ 4 files changed, 59 insertions(+), 25 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 a608448e023..0404e7b71c9 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 @@ -165,45 +165,55 @@ public class AdjustNullable extends DefaultPlanRewriter<Map<ExprId, Slot>> imple @Override public Plan visitLogicalSetOperation(LogicalSetOperation setOperation, Map<ExprId, Slot> replaceMap) { setOperation = (LogicalSetOperation) super.visit(setOperation, replaceMap); - if (setOperation.children().isEmpty()) { - return setOperation; - } - List<Boolean> inputNullable = setOperation.child(0).getOutput().stream() - .map(ExpressionTrait::nullable).collect(Collectors.toList()); ImmutableList.Builder<List<SlotReference>> newChildrenOutputs = ImmutableList.builder(); - for (int i = 0; i < setOperation.arity(); i++) { - List<Slot> childOutput = setOperation.child(i).getOutput(); - List<SlotReference> setChildOutput = setOperation.getRegularChildOutput(i); - ImmutableList.Builder<SlotReference> newChildOutputs = ImmutableList.builder(); - for (int j = 0; j < setChildOutput.size(); j++) { - for (Slot slot : childOutput) { - if (slot.getExprId().equals(setChildOutput.get(j).getExprId())) { - inputNullable.set(j, slot.nullable() || inputNullable.get(j)); - newChildOutputs.add((SlotReference) slot); - break; + List<Boolean> inputNullable = null; + if (!setOperation.children().isEmpty()) { + inputNullable = setOperation.child(0).getOutput().stream() + .map(ExpressionTrait::nullable).collect(Collectors.toList()); + for (int i = 0; i < setOperation.arity(); i++) { + List<Slot> childOutput = setOperation.child(i).getOutput(); + List<SlotReference> setChildOutput = setOperation.getRegularChildOutput(i); + ImmutableList.Builder<SlotReference> newChildOutputs = ImmutableList.builder(); + for (int j = 0; j < setChildOutput.size(); j++) { + for (Slot slot : childOutput) { + if (slot.getExprId().equals(setChildOutput.get(j).getExprId())) { + inputNullable.set(j, slot.nullable() || inputNullable.get(j)); + newChildOutputs.add((SlotReference) slot); + break; + } } } + newChildrenOutputs.add(newChildOutputs.build()); } - newChildrenOutputs.add(newChildOutputs.build()); } if (setOperation instanceof LogicalUnion) { LogicalUnion logicalUnion = (LogicalUnion) setOperation; + if (!logicalUnion.getConstantExprsList().isEmpty() && setOperation.children().isEmpty()) { + int outputSize = logicalUnion.getConstantExprsList().get(0).size(); + // create the inputNullable list and fill it with all FALSE values + inputNullable = Lists.newArrayListWithCapacity(outputSize); + for (int i = 0; i < outputSize; i++) { + inputNullable.add(false); + } + } for (List<NamedExpression> constantExprs : logicalUnion.getConstantExprsList()) { for (int j = 0; j < constantExprs.size(); j++) { - if (constantExprs.get(j).nullable()) { - inputNullable.set(j, true); - } + inputNullable.set(j, inputNullable.get(j) || constantExprs.get(j).nullable()); } } } + if (inputNullable == null) { + // this is a fail-safe + // means there is no children and having no getConstantExprsList + // no way to update the nullable flag, so just do nothing + return setOperation; + } List<NamedExpression> outputs = setOperation.getOutputs(); List<NamedExpression> newOutputs = Lists.newArrayListWithCapacity(outputs.size()); for (int i = 0; i < inputNullable.size(); i++) { NamedExpression ne = outputs.get(i); Slot slot = ne instanceof Alias ? (Slot) ((Alias) ne).child() : (Slot) ne; - if (inputNullable.get(i)) { - slot = slot.withNullable(true); - } + slot = slot.withNullable(inputNullable.get(i)); newOutputs.add(ne instanceof Alias ? (NamedExpression) ne.withChildren(slot) : slot); } newOutputs.forEach(o -> replaceMap.put(o.getExprId(), o.toSlot())); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushProjectIntoUnion.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushProjectIntoUnion.java index 971071d1a63..130d4b04d3f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushProjectIntoUnion.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushProjectIntoUnion.java @@ -67,9 +67,8 @@ public class PushProjectIntoUnion extends OneRewriteRuleFactory { } newConstExprs.add(newProjections.build()); } - return p.child() - .withChildrenAndConstExprsList(ImmutableList.of(), ImmutableList.of(), newConstExprs.build()) - .withNewOutputs(p.getOutputs()); + return p.child().withNewOutputsChildrenAndConstExprsList(ImmutableList.copyOf(p.getOutput()), + ImmutableList.of(), ImmutableList.of(), newConstExprs.build()); }).toRule(RuleType.PUSH_PROJECT_INTO_UNION); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java index 2061071ba49..4a4daf6d471 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java @@ -179,6 +179,13 @@ public class LogicalUnion extends LogicalSetOperation implements Union, OutputPr return new LogicalUnion(qualifier, outputs, childrenOutputs, constantExprsList, hasPushedFilter, children); } + public LogicalUnion withNewOutputsChildrenAndConstExprsList(List<NamedExpression> newOutputs, List<Plan> children, + List<List<SlotReference>> childrenOutputs, + List<List<NamedExpression>> constantExprsList) { + return new LogicalUnion(qualifier, newOutputs, childrenOutputs, constantExprsList, + hasPushedFilter, Optional.empty(), Optional.empty(), children); + } + public LogicalUnion withAllQualifier() { return new LogicalUnion(Qualifier.ALL, outputs, regularChildrenOutputs, constantExprsList, hasPushedFilter, Optional.empty(), Optional.empty(), children); diff --git a/regression-test/suites/nereids_syntax_p0/adjust_nullable.groovy b/regression-test/suites/nereids_syntax_p0/adjust_nullable.groovy index 24fb20d9aa2..c9f99299220 100644 --- a/regression-test/suites/nereids_syntax_p0/adjust_nullable.groovy +++ b/regression-test/suites/nereids_syntax_p0/adjust_nullable.groovy @@ -95,5 +95,23 @@ suite("adjust_nullable") { sql """ drop table if exists table_8_undef_undef; """ + + sql """ + drop table if exists orders_2_x; + """ + + sql """CREATE TABLE `orders_2_x` ( + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderdate`) + DISTRIBUTED BY HASH(`o_orderdate`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + explain { + sql("verbose insert into orders_2_x values ( '2023-10-17'),( '2023-10-17');") + notContains("nullable=true") + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org