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)); + } +}
