You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2025/12/18 06:31:18 UTC
(doris) 01/01: branch-3.1: [fix](rbo) use wrong child's output of set operation #59105
This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch pick_3.1_59105
in repository https://gitbox.apache.org/repos/asf/doris.git
commit cc738779cdbd74d58efd0a1a8a560aad4dddc800
Author: morrySnow <zh...@selectdb.com>
AuthorDate: Thu Dec 18 10:30:20 2025 +0800
branch-3.1: [fix](rbo) use wrong child's output of set operation #59105
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: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org