This is an automated email from the ASF dual-hosted git repository. jakevin pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
commit 1e4fa20d55bb3c7b44df7231df78fe594b59f3b3 Author: jackwener <jakevin...@gmail.com> AuthorDate: Tue Mar 19 17:36:50 2024 +0800 [fix](Nereids): slot set in condition can be empty (#32169) (cherry picked from commit ca092139a007dca99006d8247d9926947b1490d3) --- .../rules/rewrite/PullUpProjectUnderLimit.java | 6 ++-- .../rules/rewrite/PullUpProjectUnderTopN.java | 38 +++++++++++++++++----- .../apache/doris/nereids/trees/plans/JoinType.java | 4 +++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderLimit.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderLimit.java index a1a4ac4d219..cc2e6388a60 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderLimit.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderLimit.java @@ -21,6 +21,7 @@ import org.apache.doris.nereids.rules.Rule; import org.apache.doris.nereids.rules.RuleType; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.util.PlanUtils; @@ -36,9 +37,10 @@ import java.util.stream.Collectors; public class PullUpProjectUnderLimit extends OneRewriteRuleFactory { @Override public Rule build() { - return logicalLimit(logicalProject().whenNot(p -> p.isAllSlots())) + return logicalLimit(logicalProject(logicalJoin().when(j -> j.getJoinType().isLeftRightOuterOrCrossJoin())) + .whenNot(p -> p.isAllSlots())) .then(limit -> { - LogicalProject<Plan> project = limit.child(); + LogicalProject<LogicalJoin<Plan, Plan>> project = limit.child(); Set<Slot> allUsedSlots = project.getProjects().stream().flatMap(ne -> ne.getInputSlots().stream()) .collect(Collectors.toSet()); Set<Slot> outputSet = project.child().getOutputSet(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderTopN.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderTopN.java index b02edd9033b..469444006d1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderTopN.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PullUpProjectUnderTopN.java @@ -20,41 +20,61 @@ package org.apache.doris.nereids.rules.rewrite; import org.apache.doris.nereids.properties.OrderKey; import org.apache.doris.nereids.rules.Rule; import org.apache.doris.nereids.rules.RuleType; +import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; +import org.apache.doris.nereids.trees.plans.logical.LogicalTopN; +import org.apache.doris.nereids.util.ExpressionUtils; import org.apache.doris.nereids.util.PlanUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** - * Pull up Project under TopN. + * Pull up Project under TopN for PushDownTopNThroughJoin */ public class PullUpProjectUnderTopN extends OneRewriteRuleFactory { @Override public Rule build() { - return logicalTopN(logicalProject().whenNot(p -> p.isAllSlots())) - .whenNot(topN -> topN.child().hasPushedDownToProjectionFunctions()) + return logicalTopN( + logicalProject(logicalJoin().when(j -> j.getJoinType().isLeftRightOuterOrCrossJoin())) + .whenNot(p -> p.isAllSlots())) .then(topN -> { - LogicalProject<Plan> project = topN.child(); + LogicalProject<LogicalJoin<Plan, Plan>> project = topN.child(); Set<Slot> outputSet = project.child().getOutputSet(); - if (!topN.getOrderKeys().stream().map(OrderKey::getExpr).flatMap(e -> e.getInputSlots().stream()) - .allMatch(outputSet::contains)) { - return null; + + Map<Slot, Expression> slotMap = ExpressionUtils.generateReplaceMap(project.getProjects()); + List<OrderKey> newOrderKeys = new ArrayList<>(); + for (OrderKey orderKey : topN.getOrderKeys()) { + if (!(orderKey.getExpr() instanceof Slot)) { + return null; + } + Expression expression = slotMap.get((Slot) orderKey.getExpr()); + if (expression instanceof Slot) { + newOrderKeys.add(orderKey.withExpression(expression)); + } else { + return null; + } } + Set<Slot> allUsedSlots = project.getProjects().stream().flatMap(ne -> ne.getInputSlots().stream()) .collect(Collectors.toSet()); + LogicalTopN<Plan> newTopN = topN.withOrderKeys(newOrderKeys); if (outputSet.size() == allUsedSlots.size()) { Preconditions.checkState(outputSet.equals(allUsedSlots)); - return project.withChildren(topN.withChildren(project.child())); + return project.withChildren(newTopN.withChildren(project.child())); } else { Plan columnProject = PlanUtils.projectOrSelf(ImmutableList.copyOf(allUsedSlots), project.child()); - return project.withChildren(topN.withChildren(columnProject)); + return project.withChildren(newTopN.withChildren(columnProject)); } }).toRule(RuleType.PULL_UP_PROJECT_UNDER_TOPN); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/JoinType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/JoinType.java index bb5e1aed245..3423b13168b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/JoinType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/JoinType.java @@ -152,6 +152,10 @@ public enum JoinType { return this == RIGHT_OUTER_JOIN; } + public final boolean isLeftRightOuterOrCrossJoin() { + return this == LEFT_OUTER_JOIN || this == RIGHT_OUTER_JOIN || this == CROSS_JOIN; + } + public final boolean isLeftSemiOrAntiJoin() { return this == LEFT_SEMI_JOIN || this == LEFT_ANTI_JOIN || this == NULL_AWARE_LEFT_ANTI_JOIN; } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org