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

Reply via email to