You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2023/10/30 08:30:53 UTC

(iotdb) branch master updated: [IOTDB-6219] Fix the display problem of explain that the print result is not aligned

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 41a516618fd [IOTDB-6219] Fix the display problem of explain that the print result is not aligned
41a516618fd is described below

commit 41a516618fd20ec40f9aca36331576f7084aadfc
Author: Beyyes <cg...@foxmail.com>
AuthorDate: Mon Oct 30 16:30:47 2023 +0800

    [IOTDB-6219] Fix the display problem of explain that the print result is not aligned
---
 .../plan/planner/plan/node/PlanGraphPrinter.java   | 80 +++++++++++-----------
 .../plan/plan/node/PlanGraphPrinterTest.java       | 70 +++++++++++++++++++
 2 files changed, 110 insertions(+), 40 deletions(-)

diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
index 3de01571cb4..79165695b7d 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
@@ -493,9 +493,7 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
   private List<String> render(PlanNode node, List<String> nodeBoxString, GraphContext context) {
     Box box = new Box(nodeBoxString);
     List<List<String>> children = new ArrayList<>();
-    for (PlanNode child : node.getChildren()) {
-      children.add(child.accept(this, context));
-    }
+    node.getChildren().forEach(child -> children.add(child.accept(this, context)));
     box.calculateBoxParams(children);
 
     box.lines.add(printBoxEdge(box, true));
@@ -528,6 +526,24 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
       return box.lines;
     }
 
+    addConnectionLine(box, children);
+
+    for (int i = 0; i < getChildrenLineCount(children); i++) {
+      StringBuilder line = new StringBuilder();
+      for (int j = 0; j < children.size(); j++) {
+        line.append(getLine(children, j, i, box.childExtraSpace));
+        if (j != children.size() - 1) {
+          for (int m = 0; m < BOX_MARGIN; m++) {
+            line.append(INDENT);
+          }
+        }
+      }
+      box.lines.add(line.toString());
+    }
+    return box.lines;
+  }
+
+  private void addConnectionLine(Box box, List<List<String>> children) {
     // Print Connection Line
     if (children.size() == 1) {
       for (int i = 0; i < CONNECTION_LINE_HEIGHT; i++) {
@@ -570,20 +586,6 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
         box.lines.add(nextLine.toString());
       }
     }
-
-    for (int i = 0; i < getChildrenLineCount(children); i++) {
-      StringBuilder line = new StringBuilder();
-      for (int j = 0; j < children.size(); j++) {
-        line.append(getLine(children, j, i));
-        if (j != children.size() - 1) {
-          for (int m = 0; m < BOX_MARGIN; m++) {
-            line.append(INDENT);
-          }
-        }
-      }
-      box.lines.add(line.toString());
-    }
-    return box.lines;
   }
 
   private String printBoxEdge(Box box, boolean isTopEdge) {
@@ -604,9 +606,17 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
     return line.toString();
   }
 
-  private String getLine(List<List<String>> children, int child, int line) {
+  private String getLine(List<List<String>> children, int child, int line, int extraSpace) {
     if (line < children.get(child).size()) {
-      return children.get(child).get(line);
+      StringBuilder ret = new StringBuilder();
+      for (int i = 0; i < extraSpace; i++) {
+        ret.append(INDENT);
+      }
+      ret.append(children.get(child).get(line));
+      for (int i = 0; i < extraSpace; i++) {
+        ret.append(INDENT);
+      }
+      return ret.toString();
     }
     return genEmptyLine(children.get(child).get(0).length());
   }
@@ -638,13 +648,14 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
   }
 
   private static class Box {
-    private List<String> boxString;
-    private int boxWidth;
+    private final List<String> boxString;
+    private final int boxWidth;
     private int lineWidth;
-    private List<String> lines;
+    private final List<String> lines;
     private int startPosition;
     private int endPosition;
     private int midPosition;
+    private int childExtraSpace;
 
     public Box(List<String> boxString) {
       this.boxString = boxString;
@@ -660,21 +671,6 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
       return width + 2;
     }
 
-    public String getLine(int idx) {
-      if (idx < lines.size()) {
-        return lines.get(idx);
-      }
-      return genEmptyLine(lineWidth);
-    }
-
-    private String genEmptyLine(int lineWidth) {
-      StringBuilder line = new StringBuilder();
-      for (int i = 0; i < lineWidth; i++) {
-        line.append(INDENT);
-      }
-      return line.toString();
-    }
-
     public void calculateBoxParams(List<List<String>> childBoxStrings) {
       int childrenWidth = 0;
       for (List<String> childBoxString : childBoxStrings) {
@@ -686,6 +682,12 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
       this.startPosition = (this.lineWidth - this.boxWidth) / 2;
       this.endPosition = this.startPosition + this.boxWidth - 1;
       this.midPosition = this.lineWidth / 2;
+
+      // fix the situation that current line width is longer than width of children
+      int extraSpace = this.lineWidth - childrenWidth;
+      if (extraSpace > 0) {
+        this.childExtraSpace = extraSpace / 2;
+      }
     }
   }
 
@@ -697,8 +699,6 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter
 
   public static void print(PlanNode node) {
     List<String> lines = getGraph(node);
-    for (String line : lines) {
-      System.out.println(line);
-    }
+    lines.forEach(System.out::println);
   }
 }
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/PlanGraphPrinterTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/PlanGraphPrinterTest.java
new file mode 100644
index 00000000000..5965e442c8e
--- /dev/null
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/PlanGraphPrinterTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.queryengine.plan.plan.node;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.MeasurementPath;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.DeviceViewNode;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.TopKNode;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.SeriesScanNode;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.OrderByParameter;
+import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
+import org.apache.iotdb.db.queryengine.plan.statement.component.SortItem;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanGraphPrinter.getGraph;
+import static org.junit.Assert.assertEquals;
+
+public class PlanGraphPrinterTest {
+
+  @Test
+  public void topKNodeTest() throws IllegalPathException {
+    OrderByParameter orderByParameter =
+        new OrderByParameter(
+            Arrays.asList(
+                new SortItem("Device", Ordering.ASC), new SortItem("Time", Ordering.DESC)));
+    TopKNode topKNode =
+        new TopKNode(
+            new PlanNodeId("1"), 2, orderByParameter, Arrays.asList("Device", "Time", "s1"));
+    DeviceViewNode deviceViewNode =
+        new DeviceViewNode(
+            new PlanNodeId("2"),
+            new OrderByParameter(),
+            Collections.emptyList(),
+            Collections.emptyMap());
+
+    SeriesScanNode scanNode = new SeriesScanNode(new PlanNodeId("3"), new MeasurementPath("s1"));
+    deviceViewNode.addChildDeviceNode("d1", scanNode);
+
+    topKNode.addChild(deviceViewNode);
+
+    List<String> result = getGraph(topKNode);
+    assertEquals(19, result.size());
+    assertEquals("│TopK-1                                 │", result.get(1));
+    assertEquals("            │DeviceView-2  │             ", result.get(8));
+    assertEquals("        │SeriesScan-3           │        ", result.get(14));
+  }
+}