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

haonan 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 b986cd1  [ISSUE-2493]  Support show child nodes (#2732)
b986cd1 is described below

commit b986cd1e5fffa7c50d16ea183c796b8f3b66d8eb
Author: WilliamSong11 <[email protected]>
AuthorDate: Fri Feb 26 18:46:24 2021 +0800

    [ISSUE-2493]  Support show child nodes (#2732)
    
    Co-authored-by: yuxiang song <[email protected]>
---
 .../antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4   |  1 +
 .../DDL Data Definition Language.md                | 31 ++++++++++
 .../DDL Data Definition Language.md                | 31 ++++++++++
 .../org/apache/iotdb/db/conf/IoTDBConstant.java    |  1 +
 .../org/apache/iotdb/db/metadata/MManager.java     | 13 ++++
 .../java/org/apache/iotdb/db/metadata/MTree.java   | 72 ++++++++++++++++++++++
 .../apache/iotdb/db/qp/constant/SQLConstant.java   |  2 +
 .../apache/iotdb/db/qp/executor/PlanExecutor.java  | 26 ++++++++
 .../db/qp/logical/sys/ShowChildNodesOperator.java  | 36 +++++++++++
 .../db/qp/physical/sys/ShowChildNodesPlan.java     | 39 ++++++++++++
 .../apache/iotdb/db/qp/physical/sys/ShowPlan.java  |  1 +
 .../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java    | 13 ++++
 .../iotdb/db/qp/strategy/PhysicalGenerator.java    |  5 ++
 .../iotdb/db/integration/IoTDBMetadataFetchIT.java | 35 +++++++++++
 .../iotdb/db/metadata/MManagerBasicTest.java       | 43 +++++++++++++
 .../org/apache/iotdb/db/metadata/MTreeTest.java    | 46 ++++++++++++++
 .../java/org/apache/iotdb/db/qp/PlannerTest.java   |  7 +++
 17 files changed, 402 insertions(+)

diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 
b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
index 30809e3..0d065b4 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
@@ -77,6 +77,7 @@ statement
     | SHOW LATEST? TIMESERIES prefixPath? showWhereClause? limitClause? 
#showTimeseries
     | SHOW STORAGE GROUP prefixPath? #showStorageGroup
     | SHOW CHILD PATHS prefixPath? #showChildPaths
+    | SHOW CHILD NODES prefixPath? #showChildNodes
     | SHOW DEVICES prefixPath? (WITH STORAGE GROUP)? limitClause? #showDevices
     | SHOW MERGE #showMergeStatus
     | SHOW QUERY PROCESSLIST #showQueryProcesslist
diff --git a/docs/UserGuide/Operation Manual/DDL Data Definition Language.md 
b/docs/UserGuide/Operation Manual/DDL Data Definition Language.md
index 5002893..7fa2108 100644
--- a/docs/UserGuide/Operation Manual/DDL Data Definition Language.md   
+++ b/docs/UserGuide/Operation Manual/DDL Data Definition Language.md   
@@ -264,6 +264,37 @@ It costs 0.002s
 
 > get all paths in form of root.xx.xx.xx:show child paths root.xx.xx
 
+## Show Child Nodes
+
+```
+SHOW CHILD NODES prefixPath
+```
+
+Return all child nodes of the prefixPath.
+
+Example:
+
+* return the child nodes of root:show child paths root
+
+```
++------------+
+| child nodes|
++------------+
+|          ln|
++------------+
+```
+
+* return the child nodes of root.vehicle:show child paths root.ln
+
+```
++------------+
+| child nodes|
++------------+
+|        wf01|
+|        wf02|
++------------+
+```
+
 ## Count Timeseries
 
 IoTDB is able to use `COUNT TIMESERIES <Path>` to count the number of 
timeseries in the path. SQL statements are as follows:
diff --git a/docs/zh/UserGuide/Operation Manual/DDL Data Definition Language.md 
b/docs/zh/UserGuide/Operation Manual/DDL Data Definition Language.md
index 217d27d..9cddac2 100644
--- a/docs/zh/UserGuide/Operation Manual/DDL Data Definition Language.md        
+++ b/docs/zh/UserGuide/Operation Manual/DDL Data Definition Language.md        
@@ -271,6 +271,37 @@ SHOW CHILD PATHS prefixPath
 +---------------+
 ```
 
+## 查看子节点
+
+```
+SHOW CHILD NODES prefixPath
+```
+
+可以查看此前缀路径的下一层的所有节点。
+
+示例:
+
+* 查询 root 的下一层:show child paths root
+
+```
++------------+
+| child nodes|
++------------+
+|          ln|
++------------+
+```
+
+* 查询 root.vehicle的下一层 :show child paths root.ln
+
+```
++------------+
+| child nodes|
++------------+
+|        wf01|
+|        wf02|
++------------+
+```
+
 ## 统计时间序列总数
 
 IoTDB支持使用`COUNT TIMESERIES<Path>`来统计一条路径中的时间序列个数。SQL语句如下所示:
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java 
b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
index c1db7e9..cb1027b 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
@@ -68,6 +68,7 @@ public class IoTDBConstant {
   public static final String COLUMN_TIMESERIES_ENCODING = "encoding";
   public static final String COLUMN_TIMESERIES_COMPRESSION = "compression";
   public static final String COLUMN_CHILD_PATHS = "child paths";
+  public static final String COLUMN_CHILD_NODES = "child nodes";
   public static final String COLUMN_DEVICES = "devices";
   public static final String COLUMN_COLUMN = "column";
   public static final String COLUMN_COUNT = "count";
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index 844d023..c6bcb78 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -1012,6 +1012,7 @@ public class MManager {
    * <p>e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given 
path = root.sg1,
    * return [root.sg1.d1, root.sg1.d2]
    *
+   * @param path The given path
    * @return All child nodes' seriesPath(s) of given seriesPath.
    */
   public Set<String> getChildNodePathInNextLevel(PartialPath path) throws 
MetadataException {
@@ -1019,6 +1020,18 @@ public class MManager {
   }
 
   /**
+   * Get child node in the next level of the given path.
+   *
+   * <p>e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given 
path = root.sg1,
+   * return [d1, d2] given path = root.sg.d1 return [s1,s2]
+   *
+   * @return All child nodes of given seriesPath.
+   */
+  public Set<String> getChildNodeInNextLevel(PartialPath path) throws 
MetadataException {
+    return mtree.getChildNodeInNextLevel(path);
+  }
+
+  /**
    * Check whether the path exists.
    *
    * @param path a full path or a prefix path
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
index a9bc505..1693866 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
@@ -1118,6 +1118,7 @@ public class MTree implements Serializable {
    * <p>e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given 
path = root.sg1,
    * return [root.sg1.d1, root.sg1.d2]
    *
+   * @param path The given path
    * @return All child nodes' seriesPath(s) of given seriesPath.
    */
   Set<String> getChildNodePathInNextLevel(PartialPath path) throws 
MetadataException {
@@ -1180,6 +1181,77 @@ public class MTree implements Serializable {
   }
 
   /**
+   * Get child node in the next level of the given path.
+   *
+   * <p>e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given 
path = root.sg1,
+   * return [d1, d2]
+   *
+   * <p>e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given 
path = root.sg1.d1
+   * return [s1, s2]
+   *
+   * @param partial Path
+   * @return All child nodes' seriesPath(s) of given seriesPath.
+   */
+  Set<String> getChildNodeInNextLevel(PartialPath path) throws 
MetadataException {
+    String[] nodes = path.getNodes();
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(path.getFullPath());
+    }
+    Set<String> childNodes = new TreeSet<>();
+    findChildNodeInNextLevel(root, nodes, 1, "", childNodes, nodes.length + 1);
+    return childNodes;
+  }
+
+  /**
+   * Traverse the MTree to match all child node path in next level
+   *
+   * @param node the current traversing node
+   * @param nodes split the prefix path with '.'
+   * @param idx the current index of array nodes
+   * @param parent store the node string having traversed
+   * @param res store all matched device names
+   * @param length expected length of path
+   */
+  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity 
warning
+  private void findChildNodeInNextLevel(
+      MNode node, String[] nodes, int idx, String parent, Set<String> res, int 
length) {
+    if (node == null) {
+      return;
+    }
+    String nodeReg = MetaUtils.getNodeRegByIdx(idx, nodes);
+    if (!nodeReg.contains(PATH_WILDCARD)) {
+      if (idx == length) {
+        res.add(node.getName());
+      } else {
+        findChildNodeInNextLevel(
+            node.getChild(nodeReg),
+            nodes,
+            idx + 1,
+            parent + node.getName() + PATH_SEPARATOR,
+            res,
+            length);
+      }
+    } else {
+      if (node.getChildren().size() > 0) {
+        for (MNode child : node.getChildren().values()) {
+          if (!Pattern.matches(nodeReg.replace("*", ".*"), child.getName())) {
+            continue;
+          }
+          if (idx == length) {
+            res.add(node.getName());
+          } else {
+            findChildNodeInNextLevel(
+                child, nodes, idx + 1, parent + node.getName() + 
PATH_SEPARATOR, res, length);
+          }
+        }
+      } else if (idx == length) {
+        String nodeName = node.getName();
+        res.add(nodeName);
+      }
+    }
+  }
+
+  /**
    * Get all devices under give path
    *
    * @return a list contains all distinct devices names
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java 
b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
index b6780e0..c13f7fb 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
@@ -170,6 +170,8 @@ public class SQLConstant {
   public static final int TOK_QUERY_PROCESSLIST = 97;
   public static final int TOK_KILL_QUERY = 98;
 
+  public static final int TOK_CHILD_NODES = 99;
+
   public static final Map<Integer, String> tokenSymbol = new HashMap<>();
   public static final Map<Integer, String> tokenNames = new HashMap<>();
   public static final Map<Integer, Integer> reverseWords = new HashMap<>();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java 
b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index 85fce24..b7a1abf 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -90,6 +90,7 @@ import org.apache.iotdb.db.qp.physical.sys.MergePlan;
 import org.apache.iotdb.db.qp.physical.sys.OperateFilePlan;
 import org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetTTLPlan;
+import org.apache.iotdb.db.qp.physical.sys.ShowChildNodesPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowChildPathsPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowDevicesPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowFunctionsPlan;
@@ -148,6 +149,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_CANCELLED;
+import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_CHILD_NODES;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_CHILD_PATHS;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_COLUMN;
 import static org.apache.iotdb.db.conf.IoTDBConstant.COLUMN_COUNT;
@@ -485,6 +487,8 @@ public class PlanExecutor implements IPlanExecutor {
         return processShowDevices((ShowDevicesPlan) showPlan);
       case CHILD_PATH:
         return processShowChildPaths((ShowChildPathsPlan) showPlan);
+      case CHILD_NODE:
+        return processShowChildNodes((ShowChildNodesPlan) showPlan);
       case COUNT_TIMESERIES:
         return processCountTimeSeries((CountPlan) showPlan);
       case COUNT_NODE_TIMESERIES:
@@ -635,6 +639,28 @@ public class PlanExecutor implements IPlanExecutor {
     return IoTDB.metaManager.getChildNodePathInNextLevel(path);
   }
 
+  private QueryDataSet processShowChildNodes(ShowChildNodesPlan 
showChildNodesPlan)
+      throws MetadataException {
+    // getNodeNextChildren
+    Set<String> childNodesList = 
getNodeNextChildren(showChildNodesPlan.getPath());
+    ListDataSet listDataSet =
+        new ListDataSet(
+            Collections.singletonList(new PartialPath(COLUMN_CHILD_NODES, 
false)),
+            Collections.singletonList(TSDataType.TEXT));
+    for (String s : childNodesList) {
+      RowRecord record = new RowRecord(0);
+      Field field = new Field(TSDataType.TEXT);
+      field.setBinaryV(new Binary(s));
+      record.addField(field);
+      listDataSet.putRecord(record);
+    }
+    return listDataSet;
+  }
+
+  protected Set<String> getNodeNextChildren(PartialPath path) throws 
MetadataException {
+    return IoTDB.metaManager.getChildNodeInNextLevel(path);
+  }
+
   protected List<PartialPath> getStorageGroupNames(PartialPath path) throws 
MetadataException {
     return IoTDB.metaManager.getStorageGroupPaths(path);
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowChildNodesOperator.java
 
b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowChildNodesOperator.java
new file mode 100644
index 0000000..15b882b
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/ShowChildNodesOperator.java
@@ -0,0 +1,36 @@
+/*
+ * 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.qp.logical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+
+public class ShowChildNodesOperator extends ShowOperator {
+
+  private PartialPath path;
+
+  public ShowChildNodesOperator(int tokenIntType, PartialPath path) {
+    super(tokenIntType);
+    this.path = path;
+  }
+
+  public PartialPath getPath() {
+    return path;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowChildNodesPlan.java
 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowChildNodesPlan.java
new file mode 100644
index 0000000..94e74ec
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowChildNodesPlan.java
@@ -0,0 +1,39 @@
+/*
+ * 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.qp.physical.sys;
+
+import org.apache.iotdb.db.metadata.PartialPath;
+
+public class ShowChildNodesPlan extends ShowPlan {
+
+  // the path could be a prefix path with wildcard
+  private PartialPath prefixPath;
+
+  public ShowChildNodesPlan(ShowContentType showContentType, PartialPath 
prefixPath) {
+    super(showContentType);
+    this.prefixPath = prefixPath;
+    canBeSplit = false;
+  }
+
+  @Override
+  public PartialPath getPath() {
+    return this.prefixPath;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java
index 6c6d4c8..1a9e906 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/ShowPlan.java
@@ -107,6 +107,7 @@ public class ShowPlan extends PhysicalPlan {
     TIMESERIES,
     STORAGE_GROUP,
     CHILD_PATH,
+    CHILD_NODE,
     DEVICES,
     COUNT_TIMESERIES,
     COUNT_NODE_TIMESERIES,
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java 
b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 83a6802..9c622f8 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -61,6 +61,7 @@ import org.apache.iotdb.db.qp.logical.sys.MoveFileOperator;
 import org.apache.iotdb.db.qp.logical.sys.RemoveFileOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetTTLOperator;
+import org.apache.iotdb.db.qp.logical.sys.ShowChildNodesOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowChildPathsOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowDevicesOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowFunctionsOperator;
@@ -169,6 +170,7 @@ import 
org.apache.iotdb.db.qp.sql.SqlBaseParser.SequenceClauseContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SetStorageGroupContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.SetTTLStatementContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowAllTTLStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowChildNodesContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowChildPathsContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowDevicesContext;
 import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowFlushTaskInfoContext;
@@ -783,6 +785,17 @@ public class IoTDBSqlVisitor extends 
SqlBaseBaseVisitor<Operator> {
   }
 
   @Override
+  public Operator visitShowChildNodes(ShowChildNodesContext ctx) {
+    if (ctx.prefixPath() != null) {
+      return new ShowChildNodesOperator(
+          SQLConstant.TOK_CHILD_NODES, parsePrefixPath(ctx.prefixPath()));
+    } else {
+      return new ShowChildNodesOperator(
+          SQLConstant.TOK_CHILD_NODES, new 
PartialPath(SQLConstant.getSingleRootArray()));
+    }
+  }
+
+  @Override
   public Operator visitShowDevices(ShowDevicesContext ctx) {
     ShowDevicesOperator showDevicesOperator;
     if (ctx.prefixPath() != null) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java 
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
index a454661..f40c94a 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
@@ -56,6 +56,7 @@ import org.apache.iotdb.db.qp.logical.sys.MoveFileOperator;
 import org.apache.iotdb.db.qp.logical.sys.RemoveFileOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetTTLOperator;
+import org.apache.iotdb.db.qp.logical.sys.ShowChildNodesOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowChildPathsOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowDevicesOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowFunctionsOperator;
@@ -100,6 +101,7 @@ import org.apache.iotdb.db.qp.physical.sys.MergePlan;
 import org.apache.iotdb.db.qp.physical.sys.OperateFilePlan;
 import org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetTTLPlan;
+import org.apache.iotdb.db.qp.physical.sys.ShowChildNodesPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowChildPathsPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowDevicesPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowFunctionsPlan;
@@ -313,6 +315,9 @@ public class PhysicalGenerator {
           case SQLConstant.TOK_CHILD_PATHS:
             return new ShowChildPathsPlan(
                 ShowContentType.CHILD_PATH, ((ShowChildPathsOperator) 
operator).getPath());
+          case SQLConstant.TOK_CHILD_NODES:
+            return new ShowChildNodesPlan(
+                ShowContentType.CHILD_NODE, ((ShowChildNodesOperator) 
operator).getPath());
           case SQLConstant.TOK_QUERY_PROCESSLIST:
             return new 
ShowQueryProcesslistPlan(ShowContentType.QUERY_PROCESSLIST);
           case SQLConstant.TOK_SHOW_FUNCTIONS:
diff --git 
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
 
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
index 5359640..de1f43b 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
@@ -368,6 +368,41 @@ public class IoTDBMetadataFetchIT {
   }
 
   @Test
+  public void showChildNodes() throws SQLException, ClassNotFoundException {
+    Class.forName(Config.JDBC_DRIVER_NAME);
+    try (Connection connection =
+            DriverManager.getConnection(
+                Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+        Statement statement = connection.createStatement()) {
+      String[] sqls = new String[] {"show child nodes root.ln"};
+      String[] standards = new String[] {"wf01,\n"};
+      for (int n = 0; n < sqls.length; n++) {
+        String sql = sqls[n];
+        String standard = standards[n];
+        StringBuilder builder = new StringBuilder();
+        try {
+          boolean hasResultSet = statement.execute(sql);
+          if (hasResultSet) {
+            try (ResultSet resultSet = statement.getResultSet()) {
+              ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+              while (resultSet.next()) {
+                for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+                  builder.append(resultSet.getString(i)).append(",");
+                }
+                builder.append("\n");
+              }
+            }
+          }
+          Assert.assertEquals(standard, builder.toString());
+        } catch (SQLException e) {
+          logger.error("showChildNodes() failed", e);
+          fail(e.getMessage());
+        }
+      }
+    }
+  }
+
+  @Test
   public void showCountTimeSeries() throws SQLException, 
ClassNotFoundException {
     Class.forName(Config.JDBC_DRIVER_NAME);
     try (Connection connection =
diff --git 
a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java 
b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
index 9d4ea9d..670ef94 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
@@ -34,7 +34,9 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
@@ -457,6 +459,47 @@ public class MManagerBasicTest {
   }
 
   @Test
+  public void testShowChildNodesWithGivenPrefix() {
+    MManager manager = IoTDB.metaManager;
+    try {
+      manager.setStorageGroup(new PartialPath("root.laptop"));
+      manager.createTimeseries(
+          new PartialPath("root.laptop.d1.s1"),
+          TSDataType.INT32,
+          TSEncoding.PLAIN,
+          CompressionType.GZIP,
+          null);
+      manager.createTimeseries(
+          new PartialPath("root.laptop.d2.s1"),
+          TSDataType.INT32,
+          TSEncoding.PLAIN,
+          CompressionType.GZIP,
+          null);
+      manager.createTimeseries(
+          new PartialPath("root.laptop.d1.s2"),
+          TSDataType.INT32,
+          TSEncoding.PLAIN,
+          CompressionType.GZIP,
+          null);
+      Set<String> nodes = new HashSet<>(Arrays.asList("s1", "s2"));
+      Set<String> nodes2 = new HashSet<>(Arrays.asList("laptop"));
+      Set<String> nodes3 = new HashSet<>(Arrays.asList("d1", "d2"));
+      Set<String> nexLevelNodes1 =
+          manager.getChildNodeInNextLevel(new PartialPath("root.laptop.d1"));
+      Set<String> nexLevelNodes2 = manager.getChildNodeInNextLevel(new 
PartialPath("root"));
+      Set<String> nexLevelNodes3 = manager.getChildNodeInNextLevel(new 
PartialPath("root.laptop"));
+      // usual condition
+      assertEquals(nodes, nexLevelNodes1);
+      assertEquals(nodes2, nexLevelNodes2);
+      assertEquals(nodes3, nexLevelNodes3);
+
+    } catch (MetadataException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  @Test
   public void testGetStorageGroupNameByAutoLevel() {
     int level = 
IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel();
 
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java 
b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
index 14f5e39..ff7895f 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
@@ -35,8 +35,11 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -373,6 +376,49 @@ public class MTreeTest {
   }
 
   @Test
+  public void testGetAllChildNodeNamesByPath() {
+    MTree root = new MTree();
+    try {
+      root.setStorageGroup(new PartialPath("root.a.d0"));
+      root.createTimeseries(
+          new PartialPath("root.a.d0.s0"),
+          TSDataType.INT32,
+          TSEncoding.RLE,
+          TSFileDescriptor.getInstance().getConfig().getCompressor(),
+          Collections.emptyMap(),
+          null);
+      root.createTimeseries(
+          new PartialPath("root.a.d0.s1"),
+          TSDataType.INT32,
+          TSEncoding.RLE,
+          TSFileDescriptor.getInstance().getConfig().getCompressor(),
+          Collections.emptyMap(),
+          null);
+      root.createTimeseries(
+          new PartialPath("root.a.d5"),
+          TSDataType.INT32,
+          TSEncoding.RLE,
+          TSFileDescriptor.getInstance().getConfig().getCompressor(),
+          Collections.emptyMap(),
+          null);
+
+      // getChildNodeByPath
+      Set<String> result1 = root.getChildNodeInNextLevel(new 
PartialPath("root.a.d0"));
+      Set<String> result2 = root.getChildNodeInNextLevel(new 
PartialPath("root.a"));
+      Set<String> result3 = root.getChildNodeInNextLevel(new 
PartialPath("root"));
+      assertEquals(result1, new HashSet<>(Arrays.asList("s0", "s1")));
+      assertEquals(result2, new HashSet<>(Arrays.asList("d0", "d5")));
+      assertEquals(result3, new HashSet<>(Arrays.asList("a")));
+
+      // if child node is nll   will return  null HashSet
+      Set<String> result5 = root.getChildNodeInNextLevel(new 
PartialPath("root.a.d5"));
+      assertEquals(result5, new HashSet<>(Arrays.asList()));
+    } catch (MetadataException e1) {
+      e1.printStackTrace();
+    }
+  }
+
+  @Test
   public void testSetStorageGroup() throws IllegalPathException {
     // set storage group first
     MTree root = new MTree();
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java 
b/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java
index 4e7f5dd..508ebe4 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java
@@ -211,6 +211,13 @@ public class PlannerTest {
     }
   }
 
+  @Test
+  public void parseShowChildNodeToPhysicalPlan() throws Exception {
+    String showChildNodesStatement = "show child nodes root.vehicle1.device1";
+    PhysicalPlan plan14 = 
processor.parseSQLToPhysicalPlan(showChildNodesStatement);
+    assertEquals(OperatorType.SHOW, plan14.getOperatorType());
+  }
+
   @Test(expected = ParseCancellationException.class)
   public void parseErrorSQLToPhysicalPlan() throws QueryProcessException {
     String createTSStatement =

Reply via email to