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();