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

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

commit f64a9a33f8e28d8f13af476cb8b508fd35067203
Author: 谢健 <jianx...@gmail.com>
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: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to