You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by hu...@apache.org on 2022/12/06 04:28:49 UTC

[doris] branch master updated: [Enhancement](Nereids) Explain display extra information (#14802)

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

huajianlan 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 e578e2cd98 [Enhancement](Nereids) Explain display extra information (#14802)
e578e2cd98 is described below

commit e578e2cd98805b77b47a38ed109e8ea70e4d7b48
Author: xiaojunjie <97...@qq.com>
AuthorDate: Tue Dec 6 12:28:40 2022 +0800

    [Enhancement](Nereids) Explain display extra information (#14802)
    
    # Proposed changes
    
    Issue Number: close #14554
    
    ## Problem summary
    
    1. provide a function **Plan.extraPlans** that returns extra plans, eg: LogicalSubQueryAlias in LogicalCTE.
    2. combine the extra plans and the children in the AbstractPlan.treeString(), distinguished by the * at the beginning.
    ```
    ========== PARSED PLAN ==========
    LogicalCTE ( aliasQueries=[LogicalSubQueryAlias ( alias=s )] )
    |-*LogicalSubQueryAlias ( alias=s )
    |  +--LogicalProject ( projects=['s_suppkey] )
    |     +--LogicalFilter ( predicates=('s_suppkey = '') )
    |        +--LogicalCheckPolicy ( child=UnboundRelation ( nameParts=supplier ) )
    |           +--UnboundRelation ( nameParts=supplier )
    +--LogicalProject ( projects=[*] )
       +--LogicalJoin ( type=CROSS_JOIN, hashJoinConjuncts=[], otherJoinConjuncts=[] )
          |--LogicalSubQueryAlias ( alias=t1 )
          |  +--LogicalCheckPolicy ( child=UnboundRelation ( nameParts=s ) )
          |     +--UnboundRelation ( nameParts=s )
          +--LogicalSubQueryAlias ( alias=t2 )
             +--LogicalCheckPolicy ( child=UnboundRelation ( nameParts=s ) )
                +--UnboundRelation ( nameParts=s )
    ```
---
 .../java/org/apache/doris/nereids/memo/Group.java  | 20 ++++++++-
 .../doris/nereids/trees/plans/AbstractPlan.java    |  4 +-
 .../org/apache/doris/nereids/trees/plans/Plan.java | 12 +++++
 .../nereids/trees/plans/logical/LogicalCTE.java    | 10 +++++
 .../nereids/trees/plans/logical/LogicalFilter.java | 19 ++++++++
 .../apache/doris/nereids/util/TreeStringUtils.java | 52 +++++++++++++++-------
 .../suites/nereids_syntax_p0/explain.groovy        | 10 +++++
 7 files changed, 108 insertions(+), 19 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
index ca7e47a0f9..cfce2e6d28 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
@@ -20,6 +20,7 @@ package org.apache.doris.nereids.memo;
 import org.apache.doris.common.Pair;
 import org.apache.doris.nereids.properties.LogicalProperties;
 import org.apache.doris.nereids.properties.PhysicalProperties;
+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.LogicalPlan;
 import org.apache.doris.nereids.util.TreeStringUtils;
@@ -384,6 +385,23 @@ public class Group {
                 return ImmutableList.of();
             }
         };
-        return TreeStringUtils.treeString(this, toString, getChildren);
+
+        Function<Object, List<Object>> getExtraPlans = obj -> {
+            if (obj instanceof Plan) {
+                return (List) ((Plan) obj).extraPlans();
+            } else {
+                return ImmutableList.of();
+            }
+        };
+
+        Function<Object, Boolean> displayExtraPlan = obj -> {
+            if (obj instanceof Plan) {
+                return ((Plan) obj).displayExtraPlanFirst();
+            } else {
+                return false;
+            }
+        };
+
+        return TreeStringUtils.treeString(this, toString, getChildren, getExtraPlans, displayExtraPlan);
     }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
index 253678e48d..17b840dfb6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java
@@ -108,7 +108,9 @@ public abstract class AbstractPlan extends AbstractTreeNode<Plan> implements Pla
     public String treeString() {
         return TreeStringUtils.treeString(this,
                 plan -> plan.toString(),
-                plan -> (List) ((Plan) plan).children());
+                plan -> (List) ((Plan) plan).children(),
+                plan -> (List) ((Plan) plan).extraPlans(),
+                plan -> ((Plan) plan).displayExtraPlanFirst());
     }
 
     @Override
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
index db0b9bc65a..1db9446f57 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java
@@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.NamedExpression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
 import java.util.List;
@@ -70,6 +71,17 @@ public interface Plan extends TreeNode<Plan> {
         throw new IllegalStateException("Not support compute logical properties for " + getClass().getName());
     }
 
+    /**
+     * Get extra plans.
+     */
+    default List<Plan> extraPlans() {
+        return ImmutableList.of();
+    }
+
+    default boolean displayExtraPlanFirst() {
+        return false;
+    }
+
     /**
      * Get output slot list of the plan.
      */
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTE.java
index 0bdaa999f5..f5976c0091 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTE.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTE.java
@@ -54,6 +54,11 @@ public class LogicalCTE<CHILD_TYPE extends Plan> extends LogicalUnary<CHILD_TYPE
         return aliasQueries;
     }
 
+    @Override
+    public List<Plan> extraPlans() {
+        return (List) aliasQueries;
+    }
+
     /**
      * In fact, the action of LogicalCTE is to store and register with clauses, and this logical node will be
      * eliminated immediately after finishing the process of with-clause registry; This process is executed before
@@ -71,6 +76,11 @@ public class LogicalCTE<CHILD_TYPE extends Plan> extends LogicalUnary<CHILD_TYPE
         );
     }
 
+    @Override
+    public boolean displayExtraPlanFirst() {
+        return true;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
index 0029c205f7..ba82ab0491 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalFilter.java
@@ -21,6 +21,7 @@ import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.LogicalProperties;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.SubqueryExpr;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.PlanType;
 import org.apache.doris.nereids.trees.plans.algebra.Filter;
@@ -33,6 +34,8 @@ import com.google.common.collect.ImmutableList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Logical filter plan.
@@ -70,6 +73,22 @@ public class LogicalFilter<CHILD_TYPE extends Plan> extends LogicalUnary<CHILD_T
         return predicates;
     }
 
+    @Override
+    public List<Plan> extraPlans() {
+        if (predicates != null) {
+            return predicates.children().stream()
+                .flatMap(m -> {
+                    if (m instanceof SubqueryExpr) {
+                        return Stream.of(
+                                new LogicalSubQueryAlias<>(m.toSql(), ((SubqueryExpr) m).getQueryPlan()));
+                    } else {
+                        return new LogicalFilter<Plan>(m, child()).extraPlans().stream();
+                    }
+                }).collect(Collectors.toList());
+        }
+        return ImmutableList.of();
+    }
+
     @Override
     public List<Slot> computeOutput() {
         return child().getOutput();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TreeStringUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TreeStringUtils.java
index 6ff8ba88ce..0db4710464 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TreeStringUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TreeStringUtils.java
@@ -29,34 +29,52 @@ import java.util.function.Function;
 public class TreeStringUtils {
 
     public static String treeString(Object object, Function<Object, String> objectToString,
-            Function<Object, List<Object>> childSupplier) {
+            Function<Object, List<Object>> childSupplier,
+            Function<Object, List<Object>> extraPlansSupplier,
+            Function<Object, Boolean> displaySupplier) {
         List<String> lines = new ArrayList<>();
-        treeString(lines, 0, new ArrayList<>(), object, objectToString, childSupplier);
+        treeString(lines, new ArrayList<>(), object,
+                objectToString, childSupplier, extraPlansSupplier, displaySupplier, false);
         return StringUtils.join(lines, "\n");
     }
 
-    private static void treeString(List<String> lines, int depth, List<Boolean> lastChildren, Object object,
-            Function<Object, String> objectToString, Function<Object, List<Object>> childrenSupplier) {
+    private static void treeString(List<String> lines, List<Boolean> lastChildren, Object object,
+            Function<Object, String> objectToString, Function<Object, List<Object>> childrenSupplier,
+            Function<Object, List<Object>> extraPlansSupplier,
+            Function<Object, Boolean> displaySupplier,
+            boolean isExtraPlan) {
         StringBuilder sb = new StringBuilder();
-        if (depth > 0) {
-            if (lastChildren.size() > 1) {
-                for (int i = 0; i < lastChildren.size() - 1; i++) {
-                    sb.append(lastChildren.get(i) ? "   " : "|  ");
-                }
-            }
-            if (lastChildren.size() > 0) {
-                Boolean last = lastChildren.get(lastChildren.size() - 1);
-                sb.append(last ? "+--" : "|--");
-            }
+
+        for (int i = 0; i < lastChildren.size() - 1; i++) {
+            sb.append(lastChildren.get(i) ? "   " : "|  ");
+        }
+
+        if (lastChildren.size() > 0) {
+            Boolean last = lastChildren.get(lastChildren.size() - 1);
+            sb.append(last ? "+-" : "|-");
+            sb.append(isExtraPlan ? "*" : "-");
         }
+
         sb.append(objectToString.apply(object));
         lines.add(sb.toString());
 
+        List<Object> allObjects = new ArrayList<>();
         List<Object> children = childrenSupplier.apply(object);
-        for (int i = 0; i < children.size(); i++) {
+        List<Object> extraPlans = extraPlansSupplier.apply(object);
+        boolean displayExtraPlanFirst = displaySupplier.apply(object);
+        if (displayExtraPlanFirst) {
+            allObjects.addAll(extraPlans);
+            allObjects.addAll(children);
+        } else {
+            allObjects.addAll(children);
+            allObjects.addAll(extraPlans);
+        }
+        for (int i = 0; i < allObjects.size(); i++) {
             List<Boolean> newLasts = new ArrayList<>(lastChildren);
-            newLasts.add(i + 1 == children.size());
-            treeString(lines, depth + 1, newLasts, children.get(i), objectToString, childrenSupplier);
+            newLasts.add(i + 1 == allObjects.size());
+            boolean isSubExtraPlan = displayExtraPlanFirst ? i < extraPlans.size() : i >= children.size();
+            treeString(lines, newLasts, allObjects.get(i),
+                    objectToString, childrenSupplier, extraPlansSupplier, displaySupplier, isSubExtraPlan);
         }
     }
 }
diff --git a/regression-test/suites/nereids_syntax_p0/explain.groovy b/regression-test/suites/nereids_syntax_p0/explain.groovy
index f265bbebde..d6e1167ec9 100644
--- a/regression-test/suites/nereids_syntax_p0/explain.groovy
+++ b/regression-test/suites/nereids_syntax_p0/explain.groovy
@@ -47,4 +47,14 @@ suite("nereids_explain") {
         sql("parsed plan select 100")
         contains "UnboundOneRowRelation"
     }
+
+    explain {
+        sql("plan select * from lineorder where lo_orderkey > (select avg(lo_orderkey) from lineorder)")
+        contains "*LogicalSubQueryAlias"
+    }
+
+    explain {
+        sql("plan with s as (select * from supplier) select * from s as s1, s as s2")
+        contains "*LogicalSubQueryAlias"
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org