[fix](Nereids): don't pushdown project when project contains both side of join (#32214)

This commit is contained in:
谢健
2024-03-15 19:21:26 +08:00
committed by yiguolei
parent a90a1a76f1
commit f64a9a33f8
2 changed files with 51 additions and 0 deletions

View File

@ -38,6 +38,7 @@ import java.util.stream.Collectors;
/**
* Rule for pushdown project through left-semi/anti join
* Just push down project inside join to avoid to push the top of Join-Cluster.
* Note this rule is only used to push down project between join for join ordering.
* <pre>
* Join Join
* | |
@ -61,6 +62,9 @@ public class PushDownProjectThroughSemiJoin implements ExplorationRuleFactory {
.whenNot(j -> j.left().child().hasDistributeHint())
.then(topJoin -> {
LogicalProject<LogicalJoin<GroupPlan, GroupPlan>> project = topJoin.left();
if (projectBothJoinSide(project)) {
return null;
}
Plan newLeft = pushdownProject(project);
return topJoin.withChildren(newLeft, topJoin.right());
}).toRule(RuleType.PUSH_DOWN_PROJECT_THROUGH_SEMI_JOIN_LEFT),
@ -72,12 +76,27 @@ public class PushDownProjectThroughSemiJoin implements ExplorationRuleFactory {
.whenNot(j -> j.right().child().hasDistributeHint())
.then(topJoin -> {
LogicalProject<LogicalJoin<GroupPlan, GroupPlan>> project = topJoin.right();
if (projectBothJoinSide(project)) {
return null;
}
Plan newRight = pushdownProject(project);
return topJoin.withChildren(topJoin.left(), newRight);
}).toRule(RuleType.PUSH_DOWN_PROJECT_THROUGH_SEMI_JOIN_RIGHT)
);
}
private boolean projectBothJoinSide(LogicalProject<LogicalJoin<GroupPlan, GroupPlan>> project) {
// if project contains both side of join, it can't be pushed.
// such as:
// Project(l, null as r)
// ------ L(l) left anti join R(r)
LogicalJoin<?, ?> join = project.child();
Set<Slot> projectOutput = project.getOutputSet();
boolean containLeft = join.left().getOutput().stream().anyMatch(projectOutput::contains);
boolean containRight = join.right().getOutput().stream().anyMatch(projectOutput::contains);
return containRight && containLeft;
}
private Plan pushdownProject(LogicalProject<LogicalJoin<GroupPlan, GroupPlan>> project) {
LogicalJoin<GroupPlan, GroupPlan> join = project.child();
Set<Slot> conditionLeftSlots = CBOUtils.joinChildConditionSlots(join, true);