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