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 7ac12ac7d72 [feature](Nereids): return edges that can be pulled up 
(#28280)
7ac12ac7d72 is described below

commit 7ac12ac7d7260f2cbb05093cc55a99914c1f8c43
Author: 谢健 <[email protected]>
AuthorDate: Tue Dec 12 17:55:59 2023 +0800

    [feature](Nereids): return edges that can be pulled up (#28280)
---
 .../jobs/joinorder/hypergraph/HyperGraph.java      |  39 +++++--
 .../jobs/joinorder/hypergraph/edge/FilterEdge.java |   4 +
 .../joinorder/hypergraph/CompareOuterJoinTest.java | 117 ++++++++++++++++++++-
 3 files changed, 152 insertions(+), 8 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
index 9f04ae38cbe..7b721a40993 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/HyperGraph.java
@@ -580,6 +580,10 @@ public class HyperGraph {
         LongBitmap.getIterator(addedNodes).forEach(index -> 
nodes.get(index).attachEdge(edge));
     }
 
+    public int edgeSize() {
+        return joinEdges.size() + filterEdges.size();
+    }
+
     /**
      * compare hypergraph
      *
@@ -588,20 +592,37 @@ public class HyperGraph {
      *          be pull up from this hyper graph
      */
     public @Nullable List<Expression> isLogicCompatible(HyperGraph viewHG, 
LogicalCompatibilityContext ctx) {
-        if (viewHG.filterEdges.size() != filterEdges.size() && 
viewHG.joinEdges.size() != joinEdges.size()) {
-            return null;
-        }
         Map<Edge, Edge> queryToView = constructEdgeMap(viewHG, 
ctx.getQueryToViewEdgeExpressionMapping());
-        if (queryToView.size() != filterEdges.size() + joinEdges.size()) {
+
+        // All edge in view must have a mapped edge in query
+        if (queryToView.size() != viewHG.edgeSize()) {
             return null;
         }
+
         boolean allMatch = queryToView.entrySet().stream()
                 .allMatch(entry ->
                         compareEdgeWithNode(entry.getKey(), entry.getValue(), 
ctx.getQueryToViewNodeIDMapping()));
         if (!allMatch) {
             return null;
         }
-        return ImmutableList.of();
+
+        // join edges must be identical
+        boolean isJoinIdentical = joinEdges.stream()
+                .allMatch(queryToView::containsKey);
+        if (!isJoinIdentical) {
+            return null;
+        }
+
+        // extract all top filters
+        List<FilterEdge> residualFilterEdges = filterEdges.stream()
+                .filter(e -> !queryToView.containsKey(e))
+                .collect(ImmutableList.toImmutableList());
+        if (residualFilterEdges.stream().anyMatch(e -> !e.isTopFilter())) {
+            return null;
+        }
+        return residualFilterEdges.stream()
+                .flatMap(e -> e.getExpressions().stream())
+                .collect(ImmutableList.toImmutableList());
     }
 
     private Map<Edge, Edge> constructEdgeMap(HyperGraph viewHG, 
Map<Expression, Expression> exprMap) {
@@ -622,13 +643,19 @@ public class HyperGraph {
 
     private boolean compareEdgeWithNode(Edge t, Edge o, Map<Integer, Integer> 
nodeMap) {
         if (t instanceof FilterEdge && o instanceof FilterEdge) {
-            return false;
+            return compareEdgeWithFilter((FilterEdge) t, (FilterEdge) o, 
nodeMap);
         } else if (t instanceof JoinEdge && o instanceof JoinEdge) {
             return compareJoinEdge((JoinEdge) t, (JoinEdge) o, nodeMap);
         }
         return false;
     }
 
+    private boolean compareEdgeWithFilter(FilterEdge t, FilterEdge o, 
Map<Integer, Integer> nodeMap) {
+        long tChild = t.getReferenceNodes();
+        long oChild = o.getReferenceNodes();
+        return compareNodeMap(tChild, oChild, nodeMap);
+    }
+
     private boolean compareJoinEdge(JoinEdge t, JoinEdge o, Map<Integer, 
Integer> nodeMap) {
         long tLeft = t.getLeftExtendedNodes();
         long tRight = t.getRightExtendedNodes();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/edge/FilterEdge.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/edge/FilterEdge.java
index d04031067d8..ec037871025 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/edge/FilterEdge.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/edge/FilterEdge.java
@@ -49,6 +49,10 @@ public class FilterEdge extends Edge {
         return rejectEdges;
     }
 
+    public boolean isTopFilter() {
+        return rejectEdges.isEmpty();
+    }
+
     @Override
     public Set<Slot> getInputSlots() {
         return filter.getInputSlots();
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
index f8ba3ead2ec..d0e5084a1c1 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/CompareOuterJoinTest.java
@@ -25,13 +25,17 @@ import 
org.apache.doris.nereids.rules.exploration.mv.StructInfo;
 import org.apache.doris.nereids.rules.exploration.mv.mapping.RelationMapping;
 import org.apache.doris.nereids.rules.exploration.mv.mapping.SlotMapping;
 import org.apache.doris.nereids.sqltest.SqlTestBase;
+import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.util.HyperGraphBuilder;
 import org.apache.doris.nereids.util.PlanChecker;
 
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
+import java.util.List;
+
 class CompareOuterJoinTest extends SqlTestBase {
     @Test
     void testStarGraphWithInnerJoin() {
@@ -50,12 +54,12 @@ class CompareOuterJoinTest extends SqlTestBase {
         Plan p1 = PlanChecker.from(c1)
                 .analyze()
                 .rewrite()
-                .getPlan();
+                .getPlan().child(0);
         Plan p2 = PlanChecker.from(c1)
                 .analyze()
                 .rewrite()
                 .applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
-                .getAllPlan().get(0);
+                .getAllPlan().get(0).child(0);
         HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
         HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
         Assertions.assertTrue(h1.isLogicCompatible(h2, constructContext(p1, 
p2)) != null);
@@ -78,6 +82,115 @@ class CompareOuterJoinTest extends SqlTestBase {
         Assertions.assertTrue(h1.isLogicCompatible(h2, constructContext(p1, 
p2)) != null);
     }
 
+    @Test
+    void testInnerJoinWithFilter() {
+        
connectContext.getSessionVariable().setDisableNereidsRules("INFER_PREDICATES");
+        CascadesContext c1 = createCascadesContext(
+                "select * from T1 inner join T2 on T1.id = T2.id where T1.id = 
0",
+                connectContext
+        );
+        Plan p1 = PlanChecker.from(c1)
+                .analyze()
+                .rewrite()
+                .getPlan().child(0);
+        CascadesContext c2 = createCascadesContext(
+                "select * from T1 inner join T2 on T1.id = T2.id",
+                connectContext
+        );
+        Plan p2 = PlanChecker.from(c2)
+                .analyze()
+                .rewrite()
+                .applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
+                .getAllPlan().get(0).child(0);
+        HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
+        HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+        List<Expression> exprList = h1.isLogicCompatible(h2, 
constructContext(p1, p2));
+        Assertions.assertEquals(1, exprList.size());
+        Assertions.assertEquals("(id = 0)", exprList.get(0).toSql());
+    }
+
+    @Disabled
+    @Test
+    void testInnerJoinWithFilter2() {
+        
connectContext.getSessionVariable().setDisableNereidsRules("INFER_PREDICATES");
+        CascadesContext c1 = createCascadesContext(
+                "select * from T1 inner join T2 on T1.id = T2.id where T1.id = 
0",
+                connectContext
+        );
+        Plan p1 = PlanChecker.from(c1)
+                .analyze()
+                .rewrite()
+                .getPlan().child(0);
+        CascadesContext c2 = createCascadesContext(
+                "select * from T1 inner join T2 on T1.id = T2.id where T1.id = 
0",
+                connectContext
+        );
+        Plan p2 = PlanChecker.from(c2)
+                .analyze()
+                .rewrite()
+                .applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
+                .getAllPlan().get(0).child(0);
+        HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
+        HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+        List<Expression> exprList = h1.isLogicCompatible(h2, 
constructContext(p1, p2));
+        Assertions.assertEquals(0, exprList.size());
+    }
+
+    @Test
+    void testLeftOuterJoinWithLeftFilter() {
+        
connectContext.getSessionVariable().setDisableNereidsRules("INFER_PREDICATES");
+        CascadesContext c1 = createCascadesContext(
+                "select * from ( select * from T1 where T1.id = 0) T1 left 
outer join T2 on T1.id = T2.id",
+                connectContext
+        );
+        
connectContext.getSessionVariable().setDisableNereidsRules("INFER_PREDICATES");
+        Plan p1 = PlanChecker.from(c1)
+                .analyze()
+                .rewrite()
+                .getPlan().child(0);
+        CascadesContext c2 = createCascadesContext(
+                "select * from T1 left outer join T2 on T1.id = T2.id",
+                connectContext
+        );
+        Plan p2 = PlanChecker.from(c2)
+                .analyze()
+                .rewrite()
+                .applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
+                .getAllPlan().get(0).child(0);
+        HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
+        HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+        List<Expression> exprList = h1.isLogicCompatible(h2, 
constructContext(p1, p2));
+        Assertions.assertEquals(1, exprList.size());
+        Assertions.assertEquals("(id = 0)", exprList.get(0).toSql());
+    }
+
+    @Test
+    void testLeftOuterJoinWithRightFilter() {
+        
connectContext.getSessionVariable().setDisableNereidsRules("INFER_PREDICATES");
+        CascadesContext c1 = createCascadesContext(
+                "select * from T1 left outer join ( select * from T2 where 
T2.id = 0) T2 on T1.id = T2.id",
+                connectContext
+        );
+        
connectContext.getSessionVariable().setDisableNereidsRules("INFER_PREDICATES");
+        Plan p1 = PlanChecker.from(c1)
+                .analyze()
+                .rewrite()
+                .getPlan().child(0);
+        CascadesContext c2 = createCascadesContext(
+                "select * from T1 left outer join T2 on T1.id = T2.id",
+                connectContext
+        );
+        Plan p2 = PlanChecker.from(c2)
+                .analyze()
+                .rewrite()
+                .applyExploration(RuleSet.BUSHY_TREE_JOIN_REORDER)
+                .getAllPlan().get(0).child(0);
+        HyperGraph h1 = HyperGraph.toStructInfo(p1).get(0);
+        HyperGraph h2 = HyperGraph.toStructInfo(p2).get(0);
+        List<Expression> exprList = h1.isLogicCompatible(h2, 
constructContext(p1, p2));
+        Assertions.assertEquals(null, exprList);
+    }
+
     LogicalCompatibilityContext constructContext(Plan p1, Plan p2) {
         StructInfo st1 = AbstractMaterializedViewRule.extractStructInfo(p1,
                 null).get(0);


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

Reply via email to