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 8fb35130046 [fix](Nereids): don't pushdown project when project
contains both side of join (#32214)
8fb35130046 is described below
commit 8fb351300460accc775d6770d6d7f970259a7370
Author: 谢健 <[email protected]>
AuthorDate: Fri Mar 15 19:21:26 2024 +0800
[fix](Nereids): don't pushdown project when project contains both side of
join (#32214)
---
.../join/PushDownProjectThroughSemiJoin.java | 19 +++++++++++++
.../join/PushDownProjectThroughSemiJoinTest.java | 32 ++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoin.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoin.java
index 0629092f451..66735d39b98 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoin.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoin.java
@@ -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);
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoinTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoinTest.java
index 8c5a29f0d55..bccd3056d35 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoinTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushDownProjectThroughSemiJoinTest.java
@@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Add;
import org.apache.doris.nereids.trees.expressions.Alias;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
+import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.plans.JoinType;
import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
@@ -133,4 +134,35 @@ class PushDownProjectThroughSemiJoinTest implements
MemoPatternMatchSupported {
)
);
}
+
+ @Test
+ void testProjectLiteral() {
+ List<NamedExpression> projectExprs = ImmutableList.of(
+ new Alias(new Add(scan1.getOutput().get(0), Literal.of(1)),
"alias"),
+ new Alias(scan2.getOutput().get(0).getExprId(), new
NullLiteral(), scan2.getOutput().get(0).getName())
+ );
+ // complex projection contain ti.id, which isn't in Join Condition
+ LogicalPlan plan = new LogicalPlanBuilder(scan1)
+ .join(scan2, JoinType.LEFT_SEMI_JOIN, Pair.of(1, 1))
+ .projectExprs(projectExprs)
+ .join(scan3, JoinType.INNER_JOIN, Pair.of(1, 1))
+ .build();
+ PlanChecker.from(MemoTestUtils.createConnectContext(), plan)
+
.applyExploration(PushDownProjectThroughSemiJoin.INSTANCE.buildRules())
+ .nonMatch(logicalJoin(logicalJoin(logicalProject(), group()),
group()));
+
+ projectExprs = ImmutableList.of(
+ new Alias(new Add(scan2.getOutput().get(0), Literal.of(1)),
"alias"),
+ new Alias(scan1.getOutput().get(0).getExprId(), new
NullLiteral(), scan2.getOutput().get(0).getName())
+ );
+ // complex projection contain ti.id, which isn't in Join Condition
+ plan = new LogicalPlanBuilder(scan1)
+ .join(scan2, JoinType.RIGHT_SEMI_JOIN, Pair.of(1, 1))
+ .projectExprs(projectExprs)
+ .join(scan3, JoinType.INNER_JOIN, Pair.of(1, 1))
+ .build();
+ PlanChecker.from(MemoTestUtils.createConnectContext(), plan)
+
.applyExploration(PushDownProjectThroughSemiJoin.INSTANCE.buildRules())
+ .nonMatch(logicalJoin(logicalJoin(logicalProject(), group()),
group()));
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]