You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by xi...@apache.org on 2022/03/29 11:07:33 UTC

[iotdb] branch yanshi updated: fix some issues

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

xingtanzjr pushed a commit to branch yanshi
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/yanshi by this push:
     new 478e207  fix some issues
478e207 is described below

commit 478e2073ed5d049ab96b449a2a71eb2916f7d000
Author: Jinrui.Zhang <xi...@gmail.com>
AuthorDate: Tue Mar 29 15:20:39 2022 +0800

    fix some issues
---
 .../db/mpp/sql/planner/DistributionPlanner.java    |   2 +
 .../db/mpp/sql/planner/plan/node/PlanNode.java     |   5 +
 .../sql/planner/plan/node/PlanNodeVisualizer.java  | 266 +++++++++++++++++++++
 .../planner/plan/node/process/ExchangeNode.java    |   7 +
 .../sql/planner/plan/node/process/LimitNode.java   |   7 +
 .../planner/plan/node/process/TimeJoinNode.java    |   6 +
 .../planner/plan/node/sink/FragmentSinkNode.java   |   7 +
 .../planner/plan/node/source/SeriesScanNode.java   |  12 +
 .../db/mpp/sql/plan/DistributionPlannerTest.java   |   2 +
 .../iotdb/db/mpp/sql/plan/QueryPlannerTest.java    |   2 +
 10 files changed, 316 insertions(+)

diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/DistributionPlanner.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/DistributionPlanner.java
index 881ea55..9991c8b 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/DistributionPlanner.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/DistributionPlanner.java
@@ -67,9 +67,11 @@ public class DistributionPlanner {
     PlanNode rootAfterRewrite = rewriteSource();
     System.out.println("===== Step 2: Partition SourceNode =====");
     System.out.println(PlanNodeUtil.nodeToString(rootAfterRewrite));
+    PlanNodeVisualizer.printAsBox(rootAfterRewrite);
     PlanNode rootWithExchange = addExchangeNode(rootAfterRewrite);
     System.out.println("===== Step 3: Add ExchangeNode =====");
     System.out.println(PlanNodeUtil.nodeToString(rootWithExchange));
+    PlanNodeVisualizer.printAsBox(rootWithExchange);
     SubPlan subPlan = splitFragment(rootWithExchange);
     List<FragmentInstance> fragmentInstances = planFragmentInstances(subPlan);
     return new DistributedQueryPlan(
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNode.java
index 91f95c0..a0d480a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNode.java
@@ -18,6 +18,7 @@
  */
 package org.apache.iotdb.db.mpp.sql.planner.plan.node;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.lang.Validate;
 
 import java.nio.ByteBuffer;
@@ -77,4 +78,8 @@ public abstract class PlanNode {
   }
 
   public abstract void serialize(ByteBuffer byteBuffer);
+
+  public List<String> getBoxString() {
+    return ImmutableList.of("PlanNode");
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNodeVisualizer.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNodeVisualizer.java
new file mode 100644
index 0000000..6615dde
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/PlanNodeVisualizer.java
@@ -0,0 +1,266 @@
+/*
+ * 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.iotdb.db.mpp.sql.planner.plan.node;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PlanNodeVisualizer {
+  private static final String INDENT = " ";
+  private static final String HENG = "─";
+  private static final String SHU = "│";
+  private static final String LEFT_BOTTOM = "└";
+  private static final String RIGHT_BOTTOM = "┘";
+  private static final String LEFT_TOP = "┌";
+  private static final String RIGHT_TOP = "┐";
+  private static final String SHANG = "┴";
+  private static final String XIA = "┬";
+
+
+  private static class Box {
+    private PlanNode node;
+    private List<Box> children;
+    private int width;
+    private int maxWidth;
+    private List<String> lines;
+    private int leftIndent;
+    private int lastCharPosition;
+
+    public Box(PlanNode node) {
+      this.node = node;
+      this.width = getSelfWidth();
+      this.children = new ArrayList<>();
+      this.lines = new ArrayList<>();
+    }
+
+    public int getSelfWidth() {
+      List<String> boxLines = node.getBoxString();
+      int width = 0;
+      for (String line : boxLines) {
+        width = Math.max(width, line.length());
+      }
+      return width + 2;
+    }
+
+    public String getLine(int idx) {
+      if (idx < lines.size()) {
+        return lines.get(idx);
+      }
+      return printIndent(maxWidth);
+    }
+
+    public int getChildrenLineCount() {
+      int count = 0;
+      for (Box child : children) {
+        count = Math.max(count, child.lines.size());
+      }
+      return count;
+    }
+
+    public int childCount() {
+      return children.size();
+    }
+
+    public Box getChild(int idx) {
+      return children.get(idx);
+    }
+  }
+
+  public static List<String> getBoxLines(PlanNode root) {
+    Box box = buildBoxTree(root);
+    calculateBoxMaxWidth(box);
+    buildBoxLines(box);
+    return box.lines;
+  }
+
+  public static void printAsBox(PlanNode root) {
+    for (String line : getBoxLines(root)) {
+      System.out.println(line);
+    }
+  }
+
+  private static Box buildBoxTree(PlanNode root) {
+    Box box = new Box(root);
+    for (PlanNode child : root.getChildren()) {
+      box.children.add(buildBoxTree(child));
+    }
+    return box;
+  }
+
+  private static void calculateBoxMaxWidth(Box box) {
+    int childrenWidth = 0;
+    for (Box child : box.children) {
+      calculateBoxMaxWidth(child);
+      childrenWidth += child.maxWidth;
+    }
+    childrenWidth += box.children.size() > 1 ? box.children.size() - 1 : 0;
+    box.maxWidth = Math.max(box.width, childrenWidth);
+    box.leftIndent = (box.maxWidth - box.width) / 2;
+    box.lastCharPosition = box.leftIndent + box.width - 1;
+  }
+
+  private static void buildBoxLines(Box box) {
+    box.lines.add(printBoxEdge(box, true));
+    // Print value
+    for (String valueLine : box.node.getBoxString()) {
+      StringBuilder line = new StringBuilder();
+      for (int i = 0; i < box.maxWidth; i++) {
+        if (i < box.leftIndent) {
+          line.append(INDENT);
+          continue;
+        }
+        if (i > box.lastCharPosition) {
+          line.append(INDENT);
+          continue;
+        }
+        if (i == box.leftIndent || i == box.lastCharPosition) {
+          line.append(SHU);
+          continue;
+        }
+        if (i - box.leftIndent - 1 < valueLine.length()) {
+          line.append(valueLine.charAt(i - box.leftIndent - 1));
+        } else {
+          line.append(INDENT);
+        }
+      }
+      box.lines.add(line.toString());
+    }
+    box.lines.add(printBoxEdge(box, false));
+
+    // No child, return
+    if (box.children.size() == 0) {
+      return;
+    }
+
+    // Print Connection Line
+    int shangPosition = box.maxWidth / 2 - 1;
+    if (box.children.size() == 1) {
+      for (int i = 0; i < 2; i++) {
+        StringBuilder sb = new StringBuilder();
+        for (int j = 0; j < box.maxWidth ; j ++) {
+          if (j == shangPosition) {
+            sb.append(SHU);
+          } else {
+            sb.append(INDENT);
+          }
+        }
+        box.lines.add(sb.toString());
+      }
+    } else {
+      Map<Integer, String> symbolMap = new HashMap<>();
+      symbolMap.put(shangPosition, SHANG);
+      for (int i = 0; i < box.children.size(); i++) {
+        symbolMap.put(getChildMidPosition(box, i), i == 0 ? LEFT_TOP : i == box.children.size() - 1 ? RIGHT_TOP : XIA);
+      }
+      StringBuilder line1 = new StringBuilder();
+      for (int i = 0; i < box.maxWidth; i++) {
+        if (i < getChildMidPosition(box, 0)) {
+          line1.append(INDENT);
+          continue;
+        }
+        if (i > getChildMidPosition(box, box.childCount() - 1)) {
+          line1.append(INDENT);
+          continue;
+        }
+        line1.append(symbolMap.getOrDefault(i, HENG));
+
+      }
+      box.lines.add(line1.toString());
+
+      StringBuilder line2 = new StringBuilder();
+      for (int i = 0; i < box.maxWidth; i++) {
+        if (i < getChildMidPosition(box, 0)) {
+          line2.append(INDENT);
+          continue;
+        }
+        if (i > getChildMidPosition(box, box.childCount() - 1)) {
+          line2.append(INDENT);
+          continue;
+        }
+        if (symbolMap.containsKey(i) && i != shangPosition) {
+          line2.append(SHU);
+        } else {
+          line2.append(INDENT);
+        }
+      }
+      box.lines.add(line2.toString());
+    }
+
+    for (Box child : box.children) {
+      buildBoxLines(child);
+    }
+
+    for (int i = 0; i < box.getChildrenLineCount(); i++) {
+      StringBuilder line = new StringBuilder();
+      for (int j = 0; j < box.childCount(); j++) {
+        line.append(box.getChild(j).getLine(i));
+        line.append(INDENT);
+      }
+      box.lines.add(line.toString());
+    }
+  }
+
+  private static int getChildMidPosition(Box box, int idx) {
+    int left = 0;
+    for (int i = 0; i < idx; i++) {
+      left += box.children.get(i).maxWidth;
+      left += 1;
+    }
+    left += box.children.get(idx).maxWidth / 2;
+    return left;
+  }
+
+  private static String printIndent(int count) {
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < count; i++) {
+      sb.append(INDENT);
+    }
+    return sb.toString();
+  }
+
+  private static String printBoxEdge(Box box, boolean top) {
+    int leftIndent = (box.maxWidth - box.width) / 2;
+    StringBuilder sb = new StringBuilder();
+
+
+    for (int i = 0; i < box.maxWidth; i++) {
+      if (i < leftIndent) {
+        sb.append(INDENT);
+        continue;
+      }
+      if (i > box.lastCharPosition) {
+        sb.append(INDENT);
+        continue;
+      }
+      if (i == leftIndent) {
+        sb.append(top ? LEFT_TOP : LEFT_BOTTOM);
+        continue;
+      }
+      if (i == box.lastCharPosition) {
+        sb.append(top ? RIGHT_TOP : RIGHT_BOTTOM);
+        continue;
+      }
+      sb.append(HENG);
+    }
+    return sb.toString();
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/ExchangeNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/ExchangeNode.java
index 4c3c47e..7d45d47 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/ExchangeNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/ExchangeNode.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.service.rpc.thrift.EndPoint;
 import com.google.common.collect.ImmutableList;
 
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.List;
 
 public class ExchangeNode extends PlanNode {
@@ -138,4 +139,10 @@ public class ExchangeNode extends PlanNode {
   public PlanNodeId getUpstreamPlanNodeId() {
     return upstreamPlanNodeId;
   }
+
+  public List<String> getBoxString() {
+    List<String> ret = new ArrayList<>();
+    ret.add(String.format("ExchangeNode-%s", getId().getId()));
+    return ret;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/LimitNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/LimitNode.java
index 5b888d8..3cba9cb 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/LimitNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/LimitNode.java
@@ -108,4 +108,11 @@ public class LimitNode extends ProcessNode {
     attributes.add("RowLimit: " + this.getLimit());
     return new Pair<>(title, attributes);
   }
+
+  public List<String> getBoxString() {
+    List<String> ret = new ArrayList<>();
+    ret.add(String.format("LimitNode-%s", getId().getId()));
+    ret.add(String.format("Count: %d", limit));
+    return ret;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/TimeJoinNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/TimeJoinNode.java
index 67e874e..4d2dce7 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/TimeJoinNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/process/TimeJoinNode.java
@@ -141,4 +141,10 @@ public class TimeJoinNode extends ProcessNode {
             + (this.getFilterNullPolicy() == null ? "null" : this.getFilterNullPolicy()));
     return new Pair<>(title, attributes);
   }
+
+  public List<String> getBoxString() {
+    List<String> ret = new ArrayList<>();
+    ret.add(String.format("TimeJoinNode-%s", getId().getId()));
+    return ret;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/sink/FragmentSinkNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/sink/FragmentSinkNode.java
index 7c28d2d..9cb66d9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/sink/FragmentSinkNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/sink/FragmentSinkNode.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.service.rpc.thrift.EndPoint;
 import com.google.common.collect.ImmutableList;
 
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.List;
 
 public class FragmentSinkNode extends SinkNode {
@@ -128,4 +129,10 @@ public class FragmentSinkNode extends SinkNode {
   public PlanNodeId getDownStreamPlanNodeId() {
     return downStreamPlanNodeId;
   }
+
+  public List<String> getBoxString() {
+    List<String> ret = new ArrayList<>();
+    ret.add(String.format("FragmentSinkNode-%s", getId().getId()));
+    return ret;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/source/SeriesScanNode.java b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/source/SeriesScanNode.java
index a51adb5..271ae0e 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/source/SeriesScanNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/sql/planner/plan/node/source/SeriesScanNode.java
@@ -205,4 +205,16 @@ public class SeriesScanNode extends SourceNode {
     attributes.add("scanOrder: " + this.getScanOrder());
     return new Pair<>(title, attributes);
   }
+
+  public List<String> getBoxString() {
+    List<String> ret = new ArrayList<>();
+    ret.add(String.format("SeriesScan-%s", getId().getId()));
+    ret.add(String.format("Path:%s", getSeriesPath()));
+    ret.add(String.format("Partition:%s", getPartitionId()));
+    return ret;
+  }
+
+  private String getPartitionId() {
+    return getDataRegionReplicaSet() == null ? "Not Assigned" : getDataRegionReplicaSet().getId().toString();
+  }
 }
diff --git a/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/DistributionPlannerTest.java b/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/DistributionPlannerTest.java
index d002001..413bfc6 100644
--- a/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/DistributionPlannerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/DistributionPlannerTest.java
@@ -37,6 +37,7 @@ import org.apache.iotdb.db.mpp.sql.planner.plan.SubPlan;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.PlanNodeIdAllocator;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.PlanNodeUtil;
+import org.apache.iotdb.db.mpp.sql.planner.plan.node.PlanNodeVisualizer;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.process.LimitNode;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.process.TimeJoinNode;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.source.SeriesScanNode;
@@ -74,6 +75,7 @@ public class DistributionPlannerTest {
     PlanNode newRoot = planner.rewriteSource();
 
     System.out.println(PlanNodeUtil.nodeToString(newRoot));
+    PlanNodeVisualizer.printAsBox(newRoot);
     assertEquals(newRoot.getChildren().get(0).getChildren().size(), 3);
   }
 
diff --git a/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/QueryPlannerTest.java b/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/QueryPlannerTest.java
index 62cb663..296a450 100644
--- a/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/QueryPlannerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/mpp/sql/plan/QueryPlannerTest.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.db.mpp.sql.analyze.QueryType;
 import org.apache.iotdb.db.mpp.sql.parser.StatementGenerator;
 import org.apache.iotdb.db.mpp.sql.planner.plan.DistributedQueryPlan;
 import org.apache.iotdb.db.mpp.sql.planner.plan.node.PlanNodeUtil;
+import org.apache.iotdb.db.mpp.sql.planner.plan.node.PlanNodeVisualizer;
 import org.apache.iotdb.db.mpp.sql.statement.Statement;
 
 import org.junit.Test;
@@ -51,6 +52,7 @@ public class QueryPlannerTest {
     System.out.printf("SQL: %s%n%n", querySql);
     System.out.println("===== Step 1: Logical Plan =====");
     System.out.println(PlanNodeUtil.nodeToString(queryExecution.getLogicalPlan().getRootNode()));
+    PlanNodeVisualizer.printAsBox(queryExecution.getLogicalPlan().getRootNode());
 
     queryExecution.doDistributedPlan();
     DistributedQueryPlan distributedQueryPlan = queryExecution.getDistributedPlan();