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 <971308...@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-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org