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

caogaofei pushed a commit to branch beyyes/fix_plan_graph
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 6576c4e1fed1df8562b6104f5a09b0061575dfc4
Author: Beyyes <[email protected]>
AuthorDate: Mon Oct 30 00:19:16 2023 +0800

    fix the situation that the print result of explain is not aligned
---
 .../plan/planner/plan/node/PlanGraphPrinter.java   | 87 ++++++++++++----------
 .../plan/plan/node/PlanGraphPrinterTest.java       | 70 +++++++++++++++++
 2 files changed, 117 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..5feaf73782f 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
@@ -20,7 +20,9 @@
 package org.apache.iotdb.db.queryengine.plan.planner.plan.node;
 
 import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
+import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.partition.DataPartition;
+import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.queryengine.plan.expression.Expression;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.AggregationNode;
@@ -60,12 +62,17 @@ import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.AggregationDe
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.CrossSeriesAggregationDescriptor;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.DeviceViewIntoPathDescriptor;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.IntoPathDescriptor;
+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.apache.iotdb.tsfile.utils.Pair;
 
 import org.apache.commons.lang3.Validate;
 import org.eclipse.jetty.util.StringUtil;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -493,9 +500,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 +533,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 +593,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 +613,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 +655,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 +678,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 +689,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 +706,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));
+  }
+}

Reply via email to