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

jakevin 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 1027dd52ba [feature](Nereids): Pushdown SemiJoin in RBO. (#18099)
1027dd52ba is described below

commit 1027dd52ba95f1fef9a1dd73eb1e4c65037425e5
Author: jakevin <[email protected]>
AuthorDate: Sun Mar 26 20:58:43 2023 +0800

    [feature](Nereids): Pushdown SemiJoin in RBO. (#18099)
---
 .../doris/nereids/jobs/batch/NereidsRewriter.java  |  17 ++-
 .../org/apache/doris/nereids/rules/RuleSet.java    |   4 -
 .../org/apache/doris/nereids/rules/RuleType.java   |   7 +-
 .../rules/rewrite/logical/SemiJoinCommute.java     |  38 +++++++
 .../logical}/SemiJoinLogicalJoinTranspose.java     |  33 ++----
 .../SemiJoinLogicalJoinTransposeProject.java       |  35 ++----
 .../join/SemiJoinLogicalJoinTransposeTest.java     | 126 ---------------------
 .../SemiJoinLogicalJoinTransposeProjectTest.java   |  32 ++----
 .../logical/SemiJoinLogicalJoinTransposeTest.java  |  96 ++++++++++++++++
 .../apache/doris/nereids/sqltest/InferTest.java    |   6 +-
 10 files changed, 181 insertions(+), 213 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
index d5939e61f3..26bfd2b5bb 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java
@@ -63,6 +63,8 @@ import 
org.apache.doris.nereids.rules.rewrite.logical.PruneOlapScanTablet;
 import org.apache.doris.nereids.rules.rewrite.logical.PushFilterInsideJoin;
 import org.apache.doris.nereids.rules.rewrite.logical.PushdownLimit;
 import org.apache.doris.nereids.rules.rewrite.logical.ReorderJoin;
+import 
org.apache.doris.nereids.rules.rewrite.logical.SemiJoinLogicalJoinTranspose;
+import 
org.apache.doris.nereids.rules.rewrite.logical.SemiJoinLogicalJoinTransposeProject;
 import org.apache.doris.nereids.rules.rewrite.logical.SplitLimit;
 
 import com.google.common.collect.ImmutableList;
@@ -155,6 +157,13 @@ public class NereidsRewriter extends BatchRewriteJob {
                 // efficient because it can find the new plans and apply 
transform wherever it is
                 bottomUp(RuleSet.PUSH_DOWN_FILTERS),
 
+                // pushdown SEMI Join
+                topDown(
+                    // new SemiJoinCommute(),
+                    new SemiJoinLogicalJoinTranspose(),
+                    new SemiJoinLogicalJoinTransposeProject()
+                ),
+
                 topDown(
                     new MergeFilters(),
                     new ReorderJoin(),
@@ -169,16 +178,16 @@ public class NereidsRewriter extends BatchRewriteJob {
             ),
 
             topic("Column pruning and infer predicate",
-                custom(RuleType.COLUMN_PRUNING, () -> new ColumnPruning()),
+                custom(RuleType.COLUMN_PRUNING, ColumnPruning::new),
 
-                custom(RuleType.INFER_PREDICATES, () -> new InferPredicates()),
+                custom(RuleType.INFER_PREDICATES, InferPredicates::new),
 
                 // column pruning create new project, so we should use 
PUSH_DOWN_FILTERS
                 // to change filter-project to project-filter
                 bottomUp(RuleSet.PUSH_DOWN_FILTERS),
 
                 // after eliminate outer join in the PUSH_DOWN_FILTERS, we can 
infer more predicate and push down
-                custom(RuleType.INFER_PREDICATES, () -> new InferPredicates()),
+                custom(RuleType.INFER_PREDICATES, InferPredicates::new),
 
                 bottomUp(RuleSet.PUSH_DOWN_FILTERS),
 
@@ -190,7 +199,7 @@ public class NereidsRewriter extends BatchRewriteJob {
             ),
 
             // this rule should invoke after ColumnPruning
-            custom(RuleType.ELIMINATE_UNNECESSARY_PROJECT, () -> new 
EliminateUnnecessaryProject()),
+            custom(RuleType.ELIMINATE_UNNECESSARY_PROJECT, 
EliminateUnnecessaryProject::new),
 
             // we need to execute this rule at the end of rewrite
             // to avoid two consecutive same project appear when we do 
optimization.
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
index ada9c98ad3..b5aca02751 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
@@ -26,8 +26,6 @@ import 
org.apache.doris.nereids.rules.exploration.join.OuterJoinLAsscom;
 import org.apache.doris.nereids.rules.exploration.join.OuterJoinLAsscomProject;
 import 
org.apache.doris.nereids.rules.exploration.join.PushdownProjectThroughInnerJoin;
 import 
org.apache.doris.nereids.rules.exploration.join.PushdownProjectThroughSemiJoin;
-import 
org.apache.doris.nereids.rules.exploration.join.SemiJoinLogicalJoinTranspose;
-import 
org.apache.doris.nereids.rules.exploration.join.SemiJoinLogicalJoinTransposeProject;
 import 
org.apache.doris.nereids.rules.exploration.join.SemiJoinSemiJoinTranspose;
 import 
org.apache.doris.nereids.rules.exploration.join.SemiJoinSemiJoinTransposeProject;
 import org.apache.doris.nereids.rules.implementation.AggregateStrategies;
@@ -86,8 +84,6 @@ public class RuleSet {
     public static final List<Rule> OTHER_REORDER_RULES = planRuleFactories()
             .add(OuterJoinLAsscom.INSTANCE)
             .add(OuterJoinLAsscomProject.INSTANCE)
-            .add(SemiJoinLogicalJoinTranspose.LEFT_DEEP)
-            .add(SemiJoinLogicalJoinTransposeProject.LEFT_DEEP)
             .add(SemiJoinSemiJoinTranspose.INSTANCE)
             .add(SemiJoinSemiJoinTransposeProject.INSTANCE)
             .add(LogicalJoinSemiJoinTranspose.INSTANCE)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
index cf04bc3024..d08eb03aa4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
@@ -130,6 +130,11 @@ public enum RuleType {
     PUSHDOWN_ALIAS_THROUGH_JOIN(RuleTypeClass.REWRITE),
     PUSHDOWN_FILTER_THROUGH_SET_OPERATION(RuleTypeClass.REWRITE),
     COLUMN_PRUNING(RuleTypeClass.REWRITE),
+
+    LOGICAL_SEMI_JOIN_LOGICAL_JOIN_TRANSPOSE(RuleTypeClass.REWRITE),
+    LOGICAL_SEMI_JOIN_LOGICAL_JOIN_TRANSPOSE_PROJECT(RuleTypeClass.REWRITE),
+    LOGICAL_SEMI_JOIN_COMMUTE(RuleTypeClass.REWRITE),
+
     // expression of plan rewrite
     REWRITE_ONE_ROW_RELATION_EXPRESSION(RuleTypeClass.REWRITE),
     REWRITE_PROJECT_EXPRESSION(RuleTypeClass.REWRITE),
@@ -218,8 +223,6 @@ public enum RuleType {
     LOGICAL_OUTER_JOIN_LASSCOM_PROJECT(RuleTypeClass.EXPLORATION),
     LOGICAL_OUTER_JOIN_ASSOC(RuleTypeClass.EXPLORATION),
     LOGICAL_OUTER_JOIN_ASSOC_PROJECT(RuleTypeClass.EXPLORATION),
-    LOGICAL_SEMI_JOIN_LOGICAL_JOIN_TRANSPOSE(RuleTypeClass.EXPLORATION),
-    
LOGICAL_SEMI_JOIN_LOGICAL_JOIN_TRANSPOSE_PROJECT(RuleTypeClass.EXPLORATION),
     LOGICAL_JOIN_LOGICAL_SEMI_JOIN_TRANSPOSE(RuleTypeClass.EXPLORATION),
     
LOGICAL_JOIN_LOGICAL_SEMI_JOIN_TRANSPOSE_PROJECT(RuleTypeClass.EXPLORATION),
     LOGICAL_SEMI_JOIN_SEMI_JOIN_TRANSPOSE(RuleTypeClass.EXPLORATION),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinCommute.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinCommute.java
new file mode 100644
index 0000000000..176fe7190d
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinCommute.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.rules.rewrite.logical;
+
+import org.apache.doris.nereids.rules.Rule;
+import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
+import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
+
+/**
+ * RightSemiJoin -> LeftSemiJoin
+ */
+public class SemiJoinCommute extends OneRewriteRuleFactory {
+    @Override
+    public Rule build() {
+        return logicalJoin()
+                .when(join -> join.getJoinType().isRightSemiOrAntiJoin())
+                .whenNot(LogicalJoin::hasJoinHint)
+                .whenNot(LogicalJoin::isMarkJoin)
+                .then(join -> join.withTypeChildren(join.getJoinType().swap(), 
join.right(), join.left()))
+                .toRule(RuleType.LOGICAL_SEMI_JOIN_COMMUTE);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTranspose.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTranspose.java
similarity index 77%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTranspose.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTranspose.java
index 158ff03abc..f795b5632f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTranspose.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTranspose.java
@@ -15,14 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.exploration.join;
+package org.apache.doris.nereids.rules.rewrite.logical;
 
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.rules.exploration.OneExplorationRuleFactory;
-import 
org.apache.doris.nereids.rules.exploration.join.SemiJoinLogicalJoinTransposeProject.ContainsType;
+import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
+import 
org.apache.doris.nereids.rules.rewrite.logical.SemiJoinLogicalJoinTransposeProject.ContainsType;
 import org.apache.doris.nereids.trees.expressions.ExprId;
-import org.apache.doris.nereids.trees.plans.GroupPlan;
 import org.apache.doris.nereids.trees.plans.JoinType;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
@@ -37,21 +36,10 @@ import java.util.Set;
  * <li>SemiJoin(LogicalJoin(X, Y), Z) -> LogicalJoin(X, SemiJoin(Y, Z))
  * </ul>
  */
-public class SemiJoinLogicalJoinTranspose extends OneExplorationRuleFactory {
-
-    public static final SemiJoinLogicalJoinTranspose LEFT_DEEP = new 
SemiJoinLogicalJoinTranspose(true);
-
-    public static final SemiJoinLogicalJoinTranspose ALL = new 
SemiJoinLogicalJoinTranspose(false);
-
-    private final boolean leftDeep;
-
-    public SemiJoinLogicalJoinTranspose(boolean leftDeep) {
-        this.leftDeep = leftDeep;
-    }
-
+public class SemiJoinLogicalJoinTranspose extends OneRewriteRuleFactory {
     @Override
     public Rule build() {
-        return logicalJoin(logicalJoin(), group())
+        return logicalJoin(logicalJoin(), any())
                 .when(topJoin -> (topJoin.getJoinType().isLeftSemiOrAntiJoin()
                         && (topJoin.left().getJoinType().isInnerJoin()
                         || topJoin.left().getJoinType().isLeftOuterJoin()
@@ -59,10 +47,10 @@ public class SemiJoinLogicalJoinTranspose extends 
OneExplorationRuleFactory {
                 .whenNot(topJoin -> topJoin.hasJoinHint() || 
topJoin.left().hasJoinHint())
                 .whenNot(LogicalJoin::isMarkJoin)
                 .then(topSemiJoin -> {
-                    LogicalJoin<GroupPlan, GroupPlan> bottomJoin = 
topSemiJoin.left();
-                    GroupPlan a = bottomJoin.left();
-                    GroupPlan b = bottomJoin.right();
-                    GroupPlan c = topSemiJoin.right();
+                    LogicalJoin<Plan, Plan> bottomJoin = topSemiJoin.left();
+                    Plan a = bottomJoin.left();
+                    Plan b = bottomJoin.right();
+                    Plan c = topSemiJoin.right();
 
                     Set<ExprId> conjunctsIds = 
topSemiJoin.getConditionExprId();
                     ContainsType containsType = 
SemiJoinLogicalJoinTransposeProject.containsChildren(conjunctsIds,
@@ -84,9 +72,6 @@ public class SemiJoinLogicalJoinTranspose extends 
OneExplorationRuleFactory {
                         Plan newBottomSemiJoin = topSemiJoin.withChildren(a, 
c);
                         return bottomJoin.withChildren(newBottomSemiJoin, b);
                     } else {
-                        if (leftDeep) {
-                            return null;
-                        }
                         /*
                          *    topSemiJoin            newTopJoin
                          *      /     \             /         \
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeProject.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeProject.java
similarity index 80%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeProject.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeProject.java
index 46aca17216..aeabe44000 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeProject.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeProject.java
@@ -15,13 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.exploration.join;
+package org.apache.doris.nereids.rules.rewrite.logical;
 
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.rules.exploration.OneExplorationRuleFactory;
+import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
 import org.apache.doris.nereids.trees.expressions.ExprId;
-import org.apache.doris.nereids.trees.plans.GroupPlan;
+import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.plans.JoinType;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
@@ -38,33 +38,23 @@ import java.util.Set;
  * <li>SemiJoin(LogicalJoin(X, Y), Z) -> LogicalJoin(X, SemiJoin(Y, Z))
  * </ul>
  */
-public class SemiJoinLogicalJoinTransposeProject extends 
OneExplorationRuleFactory {
-    public static final SemiJoinLogicalJoinTransposeProject LEFT_DEEP = new 
SemiJoinLogicalJoinTransposeProject(true);
-
-    public static final SemiJoinLogicalJoinTransposeProject ALL = new 
SemiJoinLogicalJoinTransposeProject(false);
-
-    private final boolean leftDeep;
-
-    public SemiJoinLogicalJoinTransposeProject(boolean leftDeep) {
-        this.leftDeep = leftDeep;
-    }
-
+public class SemiJoinLogicalJoinTransposeProject extends OneRewriteRuleFactory 
{
     @Override
     public Rule build() {
-        return logicalJoin(logicalProject(logicalJoin()), group())
+        return logicalJoin(logicalProject(logicalJoin()), any())
                 .when(topJoin -> (topJoin.getJoinType().isLeftSemiOrAntiJoin()
                         && (topJoin.left().child().getJoinType().isInnerJoin()
                         || 
topJoin.left().child().getJoinType().isLeftOuterJoin()
                         || 
topJoin.left().child().getJoinType().isRightOuterJoin())))
                 .whenNot(join -> join.hasJoinHint() || 
join.left().child().hasJoinHint())
                 .whenNot(join -> join.isMarkJoin() || 
join.left().child().isMarkJoin())
-                .when(join -> JoinReorderUtils.isAllSlotProject(join.left()))
+                .when(join -> join.left().getProjects().stream().allMatch(expr 
-> expr instanceof Slot))
                 .then(topSemiJoin -> {
-                    LogicalProject<LogicalJoin<GroupPlan, GroupPlan>> project 
= topSemiJoin.left();
-                    LogicalJoin<GroupPlan, GroupPlan> bottomJoin = 
project.child();
-                    GroupPlan a = bottomJoin.left();
-                    GroupPlan b = bottomJoin.right();
-                    GroupPlan c = topSemiJoin.right();
+                    LogicalProject<LogicalJoin<Plan, Plan>> project = 
topSemiJoin.left();
+                    LogicalJoin<Plan, Plan> bottomJoin = project.child();
+                    Plan a = bottomJoin.left();
+                    Plan b = bottomJoin.right();
+                    Plan c = topSemiJoin.right();
 
                     Set<ExprId> conjunctsIds = 
topSemiJoin.getConditionExprId();
                     ContainsType containsType = containsChildren(conjunctsIds, 
a.getOutputExprIdSet(),
@@ -90,9 +80,6 @@ public class SemiJoinLogicalJoinTransposeProject extends 
OneExplorationRuleFacto
                         Plan newTopJoin = 
bottomJoin.withChildren(newBottomSemiJoin, b);
                         return project.withChildren(newTopJoin);
                     } else {
-                        if (leftDeep) {
-                            return null;
-                        }
                         /*-
                          *     topSemiJoin                  project
                          *       /     \                       |
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeTest.java
deleted file mode 100644
index beb2dcbb23..0000000000
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.nereids.rules.exploration.join;
-
-import org.apache.doris.common.Pair;
-import org.apache.doris.nereids.memo.Group;
-import org.apache.doris.nereids.trees.plans.JoinType;
-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.LogicalOlapScan;
-import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
-import org.apache.doris.nereids.util.LogicalPlanBuilder;
-import org.apache.doris.nereids.util.MemoTestUtils;
-import org.apache.doris.nereids.util.PlanChecker;
-import org.apache.doris.nereids.util.PlanConstructor;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class SemiJoinLogicalJoinTransposeTest {
-    private static final LogicalOlapScan scan1 = 
PlanConstructor.newLogicalOlapScan(0, "t1", 0);
-    private static final LogicalOlapScan scan2 = 
PlanConstructor.newLogicalOlapScan(1, "t2", 0);
-    private static final LogicalOlapScan scan3 = 
PlanConstructor.newLogicalOlapScan(2, "t3", 0);
-
-    @Test
-    public void testSemiJoinLogicalTransposeLAsscom() {
-        /*
-         *    topSemiJoin                newTopJoin
-         *      /     \                 /         \
-         * bottomJoin  C   -->  newBottomSemiJoin  B
-         *  /    \                  /    \
-         * A      B                A      C
-         */
-        LogicalPlan topJoin = new LogicalPlanBuilder(scan1)
-                .join(scan2, JoinType.INNER_JOIN, Pair.of(0, 0)) // t1.id = 
t2.id
-                .join(scan3, JoinType.LEFT_SEMI_JOIN, Pair.of(0, 0)) // t1.id 
= t3.id
-                .build();
-
-        PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
-                
.applyExploration(SemiJoinLogicalJoinTranspose.LEFT_DEEP.build())
-                .checkMemo(memo -> {
-                    Group root = memo.getRoot();
-                    Assertions.assertEquals(2, 
root.getLogicalExpressions().size());
-                    Plan plan = 
memo.copyOut(root.getLogicalExpressions().get(1), false);
-
-                    LogicalJoin<?, ?> newTopJoin = (LogicalJoin<?, ?>) plan;
-                    LogicalJoin<?, ?> newBottomJoin = (LogicalJoin<?, ?>) 
newTopJoin.left();
-                    Assertions.assertEquals(JoinType.INNER_JOIN, 
newTopJoin.getJoinType());
-                    Assertions.assertEquals(JoinType.LEFT_SEMI_JOIN, 
newBottomJoin.getJoinType());
-
-                    LogicalOlapScan newBottomJoinLeft = (LogicalOlapScan) 
newBottomJoin.left();
-                    LogicalOlapScan newBottomJoinRight = (LogicalOlapScan) 
newBottomJoin.right();
-                    LogicalOlapScan newTopJoinRight = (LogicalOlapScan) 
newTopJoin.right();
-
-                    Assertions.assertEquals("t1", 
newBottomJoinLeft.getTable().getName());
-                    Assertions.assertEquals("t3", 
newBottomJoinRight.getTable().getName());
-                    Assertions.assertEquals("t2", 
newTopJoinRight.getTable().getName());
-                });
-    }
-
-    @Test
-    public void testSemiJoinLogicalTransposeLAsscomFail() {
-        LogicalPlan topJoin = new LogicalPlanBuilder(scan1)
-                .join(scan2, JoinType.INNER_JOIN, Pair.of(0, 0)) // t1.id = 
t2.id
-                .join(scan3, JoinType.LEFT_SEMI_JOIN, Pair.of(2, 0)) // t2.id 
= t3.id
-                .build();
-
-        PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
-                
.applyExploration(SemiJoinLogicalJoinTranspose.LEFT_DEEP.build())
-                .checkMemo(memo -> {
-                    Group root = memo.getRoot();
-                    Assertions.assertEquals(1, 
root.getLogicalExpressions().size());
-                });
-    }
-
-    @Test
-    public void testSemiJoinLogicalTransposeAll() {
-        /*
-         *    topSemiJoin            newTopJoin
-         *      /     \             /         \
-         * bottomJoin  C   -->     A   newBottomSemiJoin
-         *  /    \                         /      \
-         * A      B                       B        C
-         */
-        LogicalPlan topJoin = new LogicalPlanBuilder(scan1)
-                .join(scan2, JoinType.INNER_JOIN, Pair.of(0, 0)) // t1.id = 
t2.id
-                .join(scan3, JoinType.LEFT_SEMI_JOIN, Pair.of(2, 0)) // t2.id 
= t3.id
-                .build();
-
-        PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
-                .applyExploration(SemiJoinLogicalJoinTranspose.ALL.build())
-                .checkMemo(memo -> {
-                    Group root = memo.getRoot();
-                    Assertions.assertEquals(2, 
root.getLogicalExpressions().size());
-                    Plan plan = 
memo.copyOut(root.getLogicalExpressions().get(1), false);
-
-                    LogicalJoin<?, ?> newTopJoin = (LogicalJoin<?, ?>) plan;
-                    LogicalJoin<?, ?> newBottomJoin = (LogicalJoin<?, ?>) 
newTopJoin.right();
-                    Assertions.assertEquals(JoinType.INNER_JOIN, 
newTopJoin.getJoinType());
-                    Assertions.assertEquals(JoinType.LEFT_SEMI_JOIN, 
newBottomJoin.getJoinType());
-
-                    LogicalOlapScan newTopJoinLeft = (LogicalOlapScan) 
newTopJoin.left();
-                    LogicalOlapScan newBottomJoinLeft = (LogicalOlapScan) 
newBottomJoin.left();
-                    LogicalOlapScan newBottomJoinRight = (LogicalOlapScan) 
newBottomJoin.right();
-
-                    Assertions.assertEquals("t1", 
newTopJoinLeft.getTable().getName());
-                    Assertions.assertEquals("t2", 
newBottomJoinLeft.getTable().getName());
-                    Assertions.assertEquals("t3", 
newBottomJoinRight.getTable().getName());
-                });
-    }
-}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeProjectTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeProjectTest.java
similarity index 78%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeProjectTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeProjectTest.java
index 7b42fe4e5d..88ba0417f0 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinLogicalJoinTransposeProjectTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeProjectTest.java
@@ -15,10 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.exploration.join;
+package org.apache.doris.nereids.rules.rewrite.logical;
 
 import org.apache.doris.common.Pair;
-import org.apache.doris.nereids.memo.Group;
 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;
@@ -29,7 +28,6 @@ import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.nereids.util.PlanConstructor;
 
 import com.google.common.collect.ImmutableList;
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 class SemiJoinLogicalJoinTransposeProjectTest implements 
MemoPatternMatchSupported {
@@ -38,7 +36,7 @@ class SemiJoinLogicalJoinTransposeProjectTest implements 
MemoPatternMatchSupport
     private static final LogicalOlapScan scan3 = 
PlanConstructor.newLogicalOlapScan(2, "t3", 0);
 
     @Test
-    void testSemiJoinLogicalTransposeProjectLAsscom() {
+    void pushLeft() {
         /*-
          *     topSemiJoin                    project
          *      /     \                         |
@@ -55,8 +53,8 @@ class SemiJoinLogicalJoinTransposeProjectTest implements 
MemoPatternMatchSupport
                 .build();
 
         PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
-                
.applyExploration(SemiJoinLogicalJoinTransposeProject.LEFT_DEEP.build())
-                .matchesExploration(
+                .applyTopDown(new SemiJoinLogicalJoinTransposeProject())
+                .matchesFromRoot(
                         logicalProject(
                                 innerLogicalJoin(
                                         leftSemiLogicalJoin(
@@ -70,23 +68,7 @@ class SemiJoinLogicalJoinTransposeProjectTest implements 
MemoPatternMatchSupport
     }
 
     @Test
-    void testSemiJoinLogicalTransposeProjectLAsscomFail() {
-        LogicalPlan topJoin = new LogicalPlanBuilder(scan1)
-                .join(scan2, JoinType.INNER_JOIN, Pair.of(0, 0)) // t1.id = 
t2.id
-                .project(ImmutableList.of(0, 2)) // t1.id, t2.id
-                .join(scan3, JoinType.LEFT_SEMI_JOIN, Pair.of(1, 0)) // t2.id 
= t3.id
-                .build();
-
-        PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
-                
.applyExploration(SemiJoinLogicalJoinTransposeProject.LEFT_DEEP.build())
-                .checkMemo(memo -> {
-                    Group root = memo.getRoot();
-                    Assertions.assertEquals(1, 
root.getLogicalExpressions().size());
-                });
-    }
-
-    @Test
-    void testSemiJoinLogicalTransposeProjectAll() {
+    void pushRight() {
         /*-
          *     topSemiJoin                  project
          *       /     \                       |
@@ -103,8 +85,8 @@ class SemiJoinLogicalJoinTransposeProjectTest implements 
MemoPatternMatchSupport
                 .build();
 
         PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
-                
.applyExploration(SemiJoinLogicalJoinTransposeProject.ALL.build())
-                .matchesExploration(
+                .applyTopDown(new SemiJoinLogicalJoinTransposeProject())
+                .matchesFromRoot(
                         logicalProject(
                                 logicalJoin(
                                         logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t1")),
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeTest.java
new file mode 100644
index 0000000000..cccb8890b7
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/SemiJoinLogicalJoinTransposeTest.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.rules.rewrite.logical;
+
+import org.apache.doris.common.Pair;
+import org.apache.doris.nereids.memo.Group;
+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;
+import org.apache.doris.nereids.util.LogicalPlanBuilder;
+import org.apache.doris.nereids.util.MemoPatternMatchSupported;
+import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.nereids.util.PlanChecker;
+import org.apache.doris.nereids.util.PlanConstructor;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class SemiJoinLogicalJoinTransposeTest implements 
MemoPatternMatchSupported {
+    private static final LogicalOlapScan scan1 = 
PlanConstructor.newLogicalOlapScan(0, "t1", 0);
+    private static final LogicalOlapScan scan2 = 
PlanConstructor.newLogicalOlapScan(1, "t2", 0);
+    private static final LogicalOlapScan scan3 = 
PlanConstructor.newLogicalOlapScan(2, "t3", 0);
+
+    @Test
+    public void pushLeft() {
+        /*
+         *    topSemiJoin                newTopJoin
+         *      /     \                 /         \
+         * bottomJoin  C   -->  newBottomSemiJoin  B
+         *  /    \                  /    \
+         * A      B                A      C
+         */
+        LogicalPlan topJoin = new LogicalPlanBuilder(scan1)
+                .join(scan2, JoinType.INNER_JOIN, Pair.of(0, 0)) // t1.id = 
t2.id
+                .join(scan3, JoinType.LEFT_SEMI_JOIN, Pair.of(0, 0)) // t1.id 
= t3.id
+                .build();
+
+        PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
+                .applyTopDown(new SemiJoinLogicalJoinTranspose())
+                .matchesFromRoot(
+                        innerLogicalJoin(
+                                leftSemiLogicalJoin(
+                                        logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t1")),
+                                        logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t3"))
+                                ),
+                                logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t2"))
+                        )
+                );
+    }
+
+    @Test
+    public void pushRight() {
+        /*
+         *    topSemiJoin            newTopJoin
+         *      /     \             /         \
+         * bottomJoin  C   -->     A   newBottomSemiJoin
+         *  /    \                         /      \
+         * A      B                       B        C
+         */
+        LogicalPlan topJoin = new LogicalPlanBuilder(scan1)
+                .join(scan2, JoinType.INNER_JOIN, Pair.of(0, 0)) // t1.id = 
t2.id
+                .join(scan3, JoinType.LEFT_SEMI_JOIN, Pair.of(2, 0)) // t2.id 
= t3.id
+                .build();
+
+        PlanChecker.from(MemoTestUtils.createConnectContext(), topJoin)
+                .applyTopDown(new SemiJoinLogicalJoinTranspose())
+                .checkMemo(memo -> {
+                    Group root = memo.getRoot();
+                    Assertions.assertEquals(1, 
root.getLogicalExpressions().size());
+                })
+                .matchesFromRoot(
+                        innerLogicalJoin(
+                                logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t1")),
+                                leftSemiLogicalJoin(
+                                        logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t2")),
+                                        logicalOlapScan().when(scan -> 
scan.getTable().getName().equals("t3"))
+                                )
+                        )
+                );
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/sqltest/InferTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/sqltest/InferTest.java
index 48b5026d1e..010a920023 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/sqltest/InferTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/sqltest/InferTest.java
@@ -82,10 +82,8 @@ public class InferTest extends SqlTestBase {
                 .analyze(sql)
                 .rewrite()
                 .matches(
-                        leftSemiLogicalJoin(
-                                logicalProject(
-                                        innerLogicalJoin()
-                                ),
+                        innerLogicalJoin(
+                                leftSemiLogicalJoin(),
                                 logicalProject()
                         )
                 );


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to