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

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


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new 7227338b506 branch-3.1: [fix](rbo) use wrong child's output of set 
operation #59105 (#59141)
7227338b506 is described below

commit 7227338b506c733ca079d2ac905d4d2c6b751dc4
Author: morrySnow <[email protected]>
AuthorDate: Fri Dec 19 10:32:31 2025 +0800

    branch-3.1: [fix](rbo) use wrong child's output of set operation #59105 
(#59141)
    
    picked from #59105
---
 .../rules/rewrite/EliminateEmptyRelation.java      | 76 ++++++++++++----------
 1 file changed, 41 insertions(+), 35 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java
index 44c042687a9..55e79e4742e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java
@@ -37,7 +37,6 @@ import 
org.apache.doris.nereids.trees.plans.logical.LogicalProject;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
 
 import java.util.List;
 import java.util.Optional;
@@ -83,13 +82,20 @@ public class EliminateEmptyRelation implements 
RewriteRuleFactory {
                     }).toRule(RuleType.ELIMINATE_AGG_ON_EMPTYRELATION),
             // after BuildAggForUnion rule, union may have more than 2 
children.
             logicalUnion(multi()).then(union -> {
-                if (union.children().isEmpty()) {
-                    // example: select * from (select 1,2 union select 3, 4) T;
-                    // the children size is 0. (1,2) and (3,4) are stored in 
union.constantExprsList
+                boolean needProcess = union.arity() == 1;
+                for (int i = 0; i < union.arity(); i++) {
+                    if (union.child(i) instanceof EmptyRelation) {
+                        needProcess = true;
+                        break;
+                    }
+                }
+                if (!needProcess) {
                     return null;
                 }
-                ImmutableList.Builder<Plan> nonEmptyChildrenBuilder = 
ImmutableList.builder();
-                ImmutableList.Builder<List<SlotReference>> 
nonEmptyOutputsBuilder = ImmutableList.builder();
+                ImmutableList.Builder<Plan> nonEmptyChildrenBuilder
+                        = ImmutableList.builderWithExpectedSize(union.arity());
+                ImmutableList.Builder<List<SlotReference>> 
nonEmptyOutputsBuilder
+                        = ImmutableList.builderWithExpectedSize(union.arity());
                 for (int i = 0; i < union.arity(); i++) {
                     if (!(union.child(i) instanceof EmptyRelation)) {
                         nonEmptyChildrenBuilder.add(union.child(i));
@@ -97,6 +103,7 @@ public class EliminateEmptyRelation implements 
RewriteRuleFactory {
                     }
                 }
                 List<Plan> nonEmptyChildren = nonEmptyChildrenBuilder.build();
+                List<List<SlotReference>> nonEmptyOutputs = 
nonEmptyOutputsBuilder.build();
                 if (nonEmptyChildren.isEmpty()) {
                     if (union.getConstantExprsList().isEmpty()) {
                         return new LogicalEmptyRelation(
@@ -107,28 +114,19 @@ public class EliminateEmptyRelation implements 
RewriteRuleFactory {
                     }
                 } else if (nonEmptyChildren.size() == 1) {
                     if (union.getConstantExprsList().isEmpty()) {
-                        Plan child = nonEmptyChildren.get(0);
+                        ImmutableList.Builder<NamedExpression> projectsBuilder 
= ImmutableList.builder();
                         List<Slot> unionOutput = union.getOutput();
-                        int childIdx = 
union.children().indexOf(nonEmptyChildren.get(0));
-                        if (childIdx >= 0) {
-                            List<SlotReference> childOutput = 
union.getRegularChildOutput(childIdx);
-                            List<NamedExpression> projects = 
Lists.newArrayList();
-                            for (int i = 0; i < unionOutput.size(); i++) {
-                                ExprId id = unionOutput.get(i).getExprId();
-                                Alias alias = new Alias(id, 
childOutput.get(i), unionOutput.get(i).getName());
-                                projects.add(alias);
-                            }
-
-                            return new LogicalProject<>(projects, child);
-                        } else {
-                            // should not hit here.
-                            return null;
+                        for (int i = 0; i < unionOutput.size(); i++) {
+                            ExprId id = unionOutput.get(i).getExprId();
+                            Alias alias = new Alias(id, 
nonEmptyOutputs.get(0).get(i), unionOutput.get(i).getName());
+                            projectsBuilder.add(alias);
                         }
+                        return new LogicalProject<>(projectsBuilder.build(), 
nonEmptyChildren.get(0));
                     }
                 }
 
                 if (union.children().size() != nonEmptyChildren.size()) {
-                    return union.withChildrenAndTheirOutputs(nonEmptyChildren, 
nonEmptyOutputsBuilder.build());
+                    return union.withChildrenAndTheirOutputs(nonEmptyChildren, 
nonEmptyOutputs);
                 } else {
                     // no empty relation child, do not change union
                     return null;
@@ -174,8 +172,20 @@ public class EliminateEmptyRelation implements 
RewriteRuleFactory {
                             
ConnectContext.get().getStatementContext().getNextRelationId(),
                             except.getOutput());
                 } else {
-                    ImmutableList.Builder<Plan> nonEmptyChildrenBuilder = 
ImmutableList.builder();
-                    ImmutableList.Builder<List<SlotReference>> 
nonEmptyOutputsBuilder = ImmutableList.builder();
+                    boolean needProcess = false;
+                    for (int i = 1; i < except.arity(); i++) {
+                        if (except.child(i) instanceof EmptyRelation) {
+                            needProcess = true;
+                            break;
+                        }
+                    }
+                    if (!needProcess) {
+                        return null;
+                    }
+                    ImmutableList.Builder<Plan> nonEmptyChildrenBuilder
+                            = 
ImmutableList.builderWithExpectedSize(except.arity());
+                    ImmutableList.Builder<List<SlotReference>> 
nonEmptyOutputsBuilder
+                            = 
ImmutableList.builderWithExpectedSize(except.arity());
                     for (int i = 0; i < except.arity(); i++) {
                         if (!(except.child(i) instanceof EmptyRelation)) {
                             nonEmptyChildrenBuilder.add(except.child(i));
@@ -183,31 +193,27 @@ public class EliminateEmptyRelation implements 
RewriteRuleFactory {
                         }
                     }
                     List<Plan> nonEmptyChildren = 
nonEmptyChildrenBuilder.build();
+                    List<List<SlotReference>> nonEmptyOutputs = 
nonEmptyOutputsBuilder.build();
                     if (nonEmptyChildren.size() == 1) {
                         // the first child is not empty, others are all empty
                         // case 1. FIRST except(distinct) empty = > 
project(AGG(FIRST))
                         // case 2. FIRST except(all) empty = > project(FIRST)
                         Plan projectChild;
                         if (except.getQualifier() == 
SetOperation.Qualifier.DISTINCT) {
-                            List<NamedExpression> firstOutputNamedExpressions 
= first.getOutput()
-                                    .stream().map(slot -> (NamedExpression) 
slot)
-                                    .collect(ImmutableList.toImmutableList());
-                            projectChild = new 
LogicalAggregate<>(ImmutableList.copyOf(firstOutputNamedExpressions),
-                                    firstOutputNamedExpressions, true, 
Optional.empty(), first);
+                            projectChild = new LogicalAggregate<>((List) 
nonEmptyOutputs.get(0),
+                                    (List) nonEmptyOutputs.get(0), true, 
Optional.empty(), first);
                         } else {
                             projectChild = first;
                         }
                         List<Slot> exceptOutput = except.getOutput();
-                        List<Slot> projectInputSlots = 
projectChild.getOutput();
-                        List<NamedExpression> projects = Lists.newArrayList();
+                        List<SlotReference> projectInputSlots = 
nonEmptyOutputs.get(0);
+                        ImmutableList.Builder<NamedExpression> projectsBuilder 
= ImmutableList.builder();
                         for (int i = 0; i < exceptOutput.size(); i++) {
                             ExprId id = exceptOutput.get(i).getExprId();
                             Alias alias = new Alias(id, 
projectInputSlots.get(i), exceptOutput.get(i).getName());
-                            projects.add(alias);
+                            projectsBuilder.add(alias);
                         }
-                        return new LogicalProject<>(projects, projectChild);
-                    } else if (nonEmptyChildren.size() == 
except.children().size()) {
-                        return null;
+                        return new LogicalProject<>(projectsBuilder.build(), 
projectChild);
                     } else {
                         return 
except.withChildrenAndTheirOutputs(nonEmptyChildren, 
nonEmptyOutputsBuilder.build());
                     }


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

Reply via email to