You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2019/09/03 11:45:07 UTC
[incubator-iotdb] branch master updated: [IoTDB-174]Add interfaces
for querying device or timeseries number
This is an automated email from the ASF dual-hosted git repository.
qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new c4b39b7 [IoTDB-174]Add interfaces for querying device or timeseries number
new 8ead902 Merge pull request #352 from jack870131/query_device_and_node_num
c4b39b7 is described below
commit c4b39b7996be0f82c5419bd05f70fb6d2d6d6b60
Author: jack870131 <ja...@outlook.com>
AuthorDate: Tue Aug 20 16:26:19 2019 +0800
[IoTDB-174]Add interfaces for querying device or timeseries number
---
.../UserGuide/6-JDBC API/1-JDBC API.md | 12 ++
.../main/java/org/apache/iotdb/jdbc/Constant.java | 9 ++
.../apache/iotdb/jdbc/IoTDBDatabaseMetadata.java | 91 ++++++++++++--
.../apache/iotdb/jdbc/IoTDBMetadataResultSet.java | 135 +++++++++++++++------
.../java/org/apache/iotdb/jdbc/IoTDBStatement.java | 31 +++++
.../iotdb/jdbc/IoTDBDatabaseMetadataTest.java | 134 ++++++++++++++++++--
.../java/org/apache/iotdb/db/metadata/MGraph.java | 4 +
.../org/apache/iotdb/db/metadata/MManager.java | 32 ++---
.../java/org/apache/iotdb/db/metadata/MNode.java | 10 ++
.../java/org/apache/iotdb/db/metadata/MTree.java | 41 +++++--
.../org/apache/iotdb/db/service/TSServiceImpl.java | 32 +++++
.../iotdb/db/integration/IoTDBMetadataFetchIT.java | 4 +-
service-rpc/src/main/thrift/rpc.thrift | 3 +
13 files changed, 460 insertions(+), 78 deletions(-)
diff --git a/docs/Documentation/UserGuide/6-JDBC API/1-JDBC API.md b/docs/Documentation/UserGuide/6-JDBC API/1-JDBC API.md
index d1c865f..e895a06 100644
--- a/docs/Documentation/UserGuide/6-JDBC API/1-JDBC API.md
+++ b/docs/Documentation/UserGuide/6-JDBC API/1-JDBC API.md
@@ -63,6 +63,7 @@ Requires that you include the packages containing the JDBC classes needed for da
import java.sql.*;
import org.apache.iotdb.jdbc.IoTDBSQLException;
+public class JDBCExample {
/**
* Before executing a SQL statement with a Statement object, you need to create a Statement object using the createStatement() method of the Connection object.
* After creating a Statement object, you can use its execute() method to execute a SQL statement
@@ -98,6 +99,16 @@ import org.apache.iotdb.jdbc.IoTDBSQLException;
//Show time series
statement.execute("SHOW TIMESERIES root.demo");
outputResult(statement.getResultSet());
+ //Count time series
+ statement.execute("COUNT TIMESERIES root");
+ outputResult(statement.getResultSet());
+ //Count nodes at the given level
+ statement.execute("COUNT NODES root LEVEL=3");
+ outputResult(statement.getResultSet());
+ //Count timeseries group by each node at the given level
+ statement.execute("COUNT TIMESERIES root GROUP BY LEVEL=3");
+ outputResult(statement.getResultSet());
+
//Execute insert statements in batch
statement.addBatch("insert into root.demo(timestamp,s0) values(1,1);");
@@ -187,4 +198,5 @@ import org.apache.iotdb.jdbc.IoTDBSQLException;
System.out.println("--------------------------\n");
}
}
+}
```
\ No newline at end of file
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
index faa79c7..0ae18cb 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/Constant.java
@@ -32,6 +32,12 @@ public class Constant {
public static final String GLOBAL_SHOW_TIMESERIES_REQ = "SHOW_TIMESERIES";
+ public static final String GLOBAL_COUNT_TIMESERIES_REQ = "COUNT_TIMESERIES";
+
+ public static final String GLOBAL_COUNT_NODE_TIMESERIES_REQ = "COUNT_NODE_TIMESERIES";
+
+ public static final String GLOBAL_COUNT_NODES_REQ = "COUNT_NODES";
+
public static final String GLOBAL_SHOW_STORAGE_GROUP_REQ = "SHOW_STORAGE_GROUP";
public static final String GLOBAL_COLUMNS_REQ = "ALL_COLUMNS";
@@ -41,4 +47,7 @@ public class Constant {
public static final String CATALOG_TIMESERIES = "ts";
public static final String CATALOG_STORAGE_GROUP = "sg";
public static final String CATALOG_DEVICE = "delta";
+ public static final String COUNT_TIMESERIES = "cntts";
+ public static final String COUNT_NODE_TIMESERIES = "cnttsbg";
+ public static final String COUNT_NODES = "cntnode";
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
index 36d01c2..1344c2d 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
@@ -18,11 +18,7 @@
*/
package org.apache.iotdb.jdbc;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.RowIdLifetime;
-import java.sql.SQLException;
+import java.sql.*;
import java.util.List;
import java.util.Set;
import org.apache.iotdb.rpc.IoTDBRPCException;
@@ -89,7 +85,7 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
} catch (IoTDBRPCException e) {
throw new IoTDBSQLException(e.getMessage());
}
- return new IoTDBMetadataResultSet(resp.getColumnsList(), null, null);
+ return new IoTDBMetadataResultSet(resp.getColumnsList(), IoTDBMetadataResultSet.MetadataType.COLUMN);
} catch (TException e) {
throw new TException("Conncetion error when fetching column metadata", e);
}
@@ -103,7 +99,7 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
} catch (IoTDBRPCException e) {
throw new IoTDBSQLException(e.getMessage());
}
- return new IoTDBMetadataResultSet(resp.getColumnsList(), null, null);
+ return new IoTDBMetadataResultSet(resp.getColumnsList(), IoTDBMetadataResultSet.MetadataType.COLUMN);
} catch (TException e) {
throw new TException("Conncetion error when fetching delta object metadata", e);
}
@@ -117,7 +113,7 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
throw new IoTDBSQLException(e.getMessage());
}
Set<String> showStorageGroup = resp.getShowStorageGroups();
- return new IoTDBMetadataResultSet(null, showStorageGroup, null);
+ return new IoTDBMetadataResultSet(showStorageGroup, IoTDBMetadataResultSet.MetadataType.STORAGE_GROUP);
} catch (TException e) {
throw new TException("Conncetion error when fetching storage group metadata", e);
}
@@ -132,10 +128,87 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
throw new IoTDBSQLException(e.getMessage());
}
List<List<String>> showTimeseriesList = resp.getShowTimeseriesList();
- return new IoTDBMetadataResultSet(null, null, showTimeseriesList);
+ return new IoTDBMetadataResultSet(showTimeseriesList, IoTDBMetadataResultSet.MetadataType.TIMESERIES);
} catch (TException e) {
throw new TException("Conncetion error when fetching timeseries metadata", e);
}
+ case Constant.COUNT_TIMESERIES:
+ req = new TSFetchMetadataReq(Constant.GLOBAL_COUNT_TIMESERIES_REQ);
+ req.setColumnPath(schemaPattern);
+ try {
+ TSFetchMetadataResp resp = client.fetchMetadata(req);
+ try {
+ RpcUtils.verifySuccess(resp.getStatus());
+ } catch (IoTDBRPCException e) {
+ throw new IoTDBSQLException(e.getMessage());
+ }
+ return new IoTDBMetadataResultSet(resp.getColumnsList().size(), IoTDBMetadataResultSet.MetadataType.COUNT_TIMESERIES);
+ } catch (TException e) {
+ throw new TException("Connection error when fetching timeseries metadata", e);
+ }
+ default:
+ throw new SQLException(catalog + " is not supported. Please refer to the user guide"
+ + " for more details.");
+ }
+ }
+
+ public ResultSet getNodes(String catalog, String schemaPattern, String columnPattern,
+ String devicePattern, String nodeLevel) throws SQLException {
+ try {
+ return getNodesFunc(catalog, nodeLevel);
+ } catch (TException e) {
+ boolean flag = connection.reconnect();
+ this.client = connection.client;
+ if (flag) {
+ try {
+ return getNodesFunc(catalog, nodeLevel);
+ } catch (TException e2) {
+ throw new SQLException(String.format("Fail to get columns catalog=%s, schemaPattern=%s,"
+ + " columnPattern=%s, devicePattern=%s, nodeLevel=%s after reconnecting."
+ + " please check server status",
+ catalog, schemaPattern, columnPattern, devicePattern, nodeLevel));
+ }
+ } else {
+ throw new SQLException(String.format(
+ "Fail to reconnect to server when getting columns catalog=%s, schemaPattern=%s,"
+ + " columnPattern=%s, devicePattern=%s, nodeLevel=%s after reconnecting. "
+ + "please check server status",
+ catalog, schemaPattern, columnPattern, devicePattern, nodeLevel));
+ }
+ }
+ }
+
+ private ResultSet getNodesFunc(String catalog, String nodeLevel) throws TException, SQLException {
+ TSFetchMetadataReq req;
+ switch (catalog) {
+ case Constant.COUNT_NODES:
+ req = new TSFetchMetadataReq(Constant.GLOBAL_COUNT_NODES_REQ);
+ req.setNodeLevel(nodeLevel);
+ try {
+ TSFetchMetadataResp resp = client.fetchMetadata(req);
+ try {
+ RpcUtils.verifySuccess(resp.getStatus());
+ } catch (IoTDBRPCException e) {
+ throw new IoTDBSQLException(e.getMessage());
+ }
+ return new IoTDBMetadataResultSet(resp.getNodesList().size(), IoTDBMetadataResultSet.MetadataType.COUNT_NODES);
+ } catch (TException e) {
+ throw new TException("Conncetion error when fetching node metadata", e);
+ }
+ case Constant.COUNT_NODE_TIMESERIES:
+ req = new TSFetchMetadataReq(Constant.GLOBAL_COUNT_NODE_TIMESERIES_REQ);
+ req.setNodeLevel(nodeLevel);
+ try {
+ TSFetchMetadataResp resp = client.fetchMetadata(req);
+ try {
+ RpcUtils.verifySuccess(resp.getStatus());
+ } catch (IoTDBRPCException e) {
+ throw new IoTDBSQLException(e.getMessage());
+ }
+ return new IoTDBMetadataResultSet(resp.getNodeTimeseriesNum(), IoTDBMetadataResultSet.MetadataType.COUNT_NODE_TIMESERIES);
+ } catch (TException e) {
+ throw new TException("Conncetion error when fetching node metadata", e);
+ }
default:
throw new SQLException(catalog + " is not supported. Please refer to the user guide"
+ " for more details.");
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java
index a0ad409..c52d327 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java
@@ -20,19 +20,17 @@ package org.apache.iotdb.jdbc;
import java.math.BigDecimal;
import java.sql.Date;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Statement;
-import java.sql.Time;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
+import java.sql.*;
+import java.util.*;
public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
public static final String GET_STRING_COLUMN = "COLUMN";
public static final String GET_STRING_STORAGE_GROUP = "STORAGE_GROUP";
+ public static final String GET_STRING_TIMESERIES_NUM = "TIMESERIES_NUM";
+ public static final String GET_STRING_NODES_NUM = "NODE_NUM";
+ public static final String GET_STRING_NODE_PATH = "NODE_PATH";
+ public static final String GET_STRING_NODE_TIMESERIES_NUM = "NODE_TIMESERIES_NUM";
public static final String GET_STRING_TIMESERIES_NAME = "Timeseries";
public static final String GET_STRING_TIMESERIES_STORAGE_GROUP = "Storage Group";
public static final String GET_STRING_TIMESERIES_DATATYPE = "DataType";
@@ -42,6 +40,13 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
private String currentColumn;
private String currentStorageGroup;
private List<String> currentTimeseries;
+ private List<String> timeseriesNumList;
+ private List<String> nodesNumList;
+ private Map<String, String> nodeTimeseriesNumMap;
+ private String timeseriesNum;
+ private String nodesNum;
+ private String currentNode;
+ private String currentNodeTimeseriesNum;
// for display
private int colCount; // the number of columns for show
private String[] showLabels; // headers for show
@@ -51,26 +56,52 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
/**
* Constructor used for the result of DatabaseMetadata.getColumns()
*/
- public IoTDBMetadataResultSet(List<String> columns, Set<String> storageGroupSet,
- List<List<String>> showTimeseriesList) throws SQLException {
- if (columns != null) {
- type = MetadataType.COLUMN;
- colCount = 1;
- showLabels = new String[]{"Column"};
- columnItr = columns.iterator();
- } else if (storageGroupSet != null) {
- type = MetadataType.STORAGE_GROUP;
- colCount = 1;
- showLabels = new String[]{"Storage Group"};
- columnItr = storageGroupSet.iterator();
- } else if (showTimeseriesList != null) {
- type = MetadataType.TIMESERIES;
- colCount = 4;
- showLabels = new String[]{GET_STRING_TIMESERIES_NAME, GET_STRING_TIMESERIES_STORAGE_GROUP,
+ public IoTDBMetadataResultSet(Object object, MetadataType type) throws SQLException {
+ this.type = type;
+ switch (type) {
+ case COLUMN:
+ List<String> columns = (List<String>) object;
+ colCount = 1;
+ showLabels = new String[]{"column"};
+ columnItr = columns.iterator();
+ break;
+ case STORAGE_GROUP:
+ Set<String> storageGroupSet = (Set<String>) object;
+ colCount = 1;
+ showLabels = new String[]{"Storage Group"};
+ columnItr = storageGroupSet.iterator();
+ break;
+ case TIMESERIES:
+ List<List<String>> showTimeseriesList = (List<List<String>>) object;
+ colCount = 4;
+ showLabels = new String[]{GET_STRING_TIMESERIES_NAME, GET_STRING_TIMESERIES_STORAGE_GROUP,
GET_STRING_TIMESERIES_DATATYPE, GET_STRING_TIMESERIES_ENCODING};
- columnItr = showTimeseriesList.iterator();
- } else {
- throw new SQLException("TsfileMetadataResultSet constructor is wrongly used.");
+ columnItr = showTimeseriesList.iterator();
+ break;
+ case COUNT_TIMESERIES:
+ String tsNum = (String) object.toString();
+ timeseriesNumList = new ArrayList<>();
+ timeseriesNumList.add(tsNum);
+ colCount = 1;
+ showLabels = new String[]{"count"};
+ columnItr = timeseriesNumList.iterator();
+ break;
+ case COUNT_NODES:
+ String ndNum = (String) object.toString();
+ nodesNumList = new ArrayList<>();
+ nodesNumList.add(ndNum);
+ colCount = 1;
+ showLabels = new String[]{"count"};
+ columnItr = nodesNumList.iterator();
+ break;
+ case COUNT_NODE_TIMESERIES:
+ nodeTimeseriesNumMap = (Map<String, String>) object;
+ colCount = 2;
+ showLabels = new String[]{"column", "count"};
+ columnItr = nodeTimeseriesNumMap.entrySet().iterator();
+ break;
+ default:
+ throw new SQLException("TsfileMetadataResultSet constructor is wrongly used.");
}
}
@@ -198,12 +229,29 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
public boolean next() throws SQLException {
boolean hasNext = columnItr.hasNext();
if (hasNext) {
- if (type == MetadataType.STORAGE_GROUP) {
- currentStorageGroup = (String) columnItr.next();
- } else if (type == MetadataType.COLUMN) {
- currentColumn = (String) columnItr.next();
- } else {
- currentTimeseries = (List<String>) columnItr.next();
+ switch (type) {
+ case STORAGE_GROUP:
+ currentStorageGroup = (String) columnItr.next();
+ break;
+ case TIMESERIES:
+ currentTimeseries = (List<String>) columnItr.next();
+ break;
+ case COLUMN:
+ currentColumn = (String) columnItr.next();
+ break;
+ case COUNT_TIMESERIES:
+ timeseriesNum = (String) columnItr.next();
+ break;
+ case COUNT_NODES:
+ nodesNum = (String) columnItr.next();
+ break;
+ case COUNT_NODE_TIMESERIES:
+ Map.Entry pair = (Map.Entry) columnItr.next();
+ currentNode = (String) pair.getKey();
+ currentNodeTimeseriesNum = (String) pair.getValue();
+ break;
+ default:
+ break;
}
}
return hasNext;
@@ -252,6 +300,17 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
return getString(GET_STRING_COLUMN);
}
break;
+ case COUNT_TIMESERIES:
+ if (columnIndex == 1) {
+ return getString(GET_STRING_TIMESERIES_NUM);
+ }
+ break;
+ case COUNT_NODES:
+ if (columnIndex == 1) {
+ return getString(GET_STRING_NODES_NUM);
+ }
+ case COUNT_NODE_TIMESERIES:
+ return columnIndex == 1 ? getString(GET_STRING_NODE_PATH) : getString(GET_STRING_NODE_TIMESERIES_NUM);
default:
break;
}
@@ -274,6 +333,14 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
return currentTimeseries.get(3);
case GET_STRING_COLUMN:
return currentColumn;
+ case GET_STRING_TIMESERIES_NUM:
+ return timeseriesNum;
+ case GET_STRING_NODES_NUM:
+ return nodesNum;
+ case GET_STRING_NODE_PATH:
+ return currentNode;
+ case GET_STRING_NODE_TIMESERIES_NUM:
+ return currentNodeTimeseriesNum;
default:
break;
}
@@ -311,6 +378,6 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
}
public enum MetadataType {
- STORAGE_GROUP, TIMESERIES, COLUMN
+ STORAGE_GROUP, TIMESERIES, COLUMN, COUNT_TIMESERIES, COUNT_NODES, COUNT_NODE_TIMESERIES
}
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index b728831..35b2361 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -41,6 +41,8 @@ public class IoTDBStatement implements Statement {
private static final String SHOW_TIMESERIES_COMMAND_LOWERCASE = "show timeseries";
private static final String SHOW_STORAGE_GROUP_COMMAND_LOWERCASE = "show storage group";
+ private static final String COUNT_TIMESERIES_COMMAND_LOWERCASE = "count timeseries";
+ private static final String COUNT_NODES_COMMAND_LOWERCASE = "count nodes";
private static final String METHOD_NOT_SUPPORTED_STRING = "Method not supported";
ZoneId zoneId;
@@ -236,6 +238,35 @@ public class IoTDBStatement implements Statement {
DatabaseMetaData databaseMetaData = connection.getMetaData();
resultSet = databaseMetaData.getColumns(Constant.CATALOG_STORAGE_GROUP, null, null, null);
return true;
+ } else if (sqlToLowerCase.startsWith(COUNT_TIMESERIES_COMMAND_LOWERCASE)) {
+ String[] cmdSplited = sqlToLowerCase.split("\\s+", 4);
+ if (cmdSplited.length != 3 && !(cmdSplited.length == 4 && cmdSplited[3].startsWith("group by level"))) {
+ throw new SQLException(
+ "Error format of \'COUNT TIMESERIES <PATH>\' or \'COUNT TIMESERIES <PATH> GROUP BY LEVEL=<INTEGER>\'");
+ }
+ if (cmdSplited.length == 3) {
+ String path = cmdSplited[2];
+ DatabaseMetaData databaseMetaData = connection.getMetaData();
+ resultSet = databaseMetaData.getColumns(Constant.COUNT_TIMESERIES, path, null, null);
+ return true;
+ } else {
+ String path = cmdSplited[2];
+ String level = cmdSplited[3].replaceAll(" ", "").substring(13);
+ IoTDBDatabaseMetadata databaseMetadata = (IoTDBDatabaseMetadata) connection.getMetaData();
+ resultSet = databaseMetadata.getNodes(Constant.COUNT_NODE_TIMESERIES, path, null, null, level);
+ return true;
+ }
+ } else if (sqlToLowerCase.startsWith(COUNT_NODES_COMMAND_LOWERCASE)) {
+ String[] cmdSplited = sql.split("\\s+", 4);
+ if (cmdSplited.length != 4 && !(cmdSplited[3].startsWith("level"))) {
+ throw new SQLException("Error format of \'COUNT NODES LEVEL=<INTEGER>\'");
+ } else {
+ String path = cmdSplited[2];
+ String level = cmdSplited[3].replaceAll(" ", "").substring(6);
+ IoTDBDatabaseMetadata databaseMetaData = (IoTDBDatabaseMetadata) connection.getMetaData();
+ resultSet = databaseMetaData.getNodes(Constant.COUNT_NODES, path, null, null, level);
+ return true;
+ }
} else {
TSExecuteStatementReq execReq = new TSExecuteStatementReq(sessionHandle, sql);
TSExecuteStatementResp execResp = client.executeStatement(execReq);
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
index 2fdb406..f0a20a1 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
@@ -21,16 +21,11 @@ package org.apache.iotdb.jdbc;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
-
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
+import java.util.*;
import org.apache.iotdb.rpc.TSStatusType;
import org.apache.iotdb.service.rpc.thrift.*;
import org.junit.Assert;
@@ -94,8 +89,124 @@ public class IoTDBDatabaseMetadataTest {
when(fetchMetadataResp.getColumnsList()).thenReturn(columnList);
String standard =
- "Column,\n" + "root.vehicle.d0.s0,\n" + "root.vehicle.d0.s1,\n" + "root.vehicle.d0.s2,\n";
- try (ResultSet resultSet = databaseMetaData.getColumns(Constant.CATALOG_COLUMN, "root", null, null)) {
+ "column,\n" + "root.vehicle.d0.s0,\n" + "root.vehicle.d0.s1,\n" + "root.vehicle.d0.s2,\n";
+ try {
+ ResultSet resultSet = databaseMetaData.getColumns(Constant.CATALOG_COLUMN, "root", null, null);
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ int colCount = resultSetMetaData.getColumnCount();
+ StringBuilder resultStr = new StringBuilder();
+ for (int i = 1; i < colCount + 1; i++) {
+ resultStr.append(resultSetMetaData.getColumnName(i)).append(",");
+ }
+ resultStr.append("\n");
+ while (resultSet.next()) {
+ for (int i = 1; i <= colCount; i++) {
+ resultStr.append(resultSet.getString(i)).append(",");
+ }
+ resultStr.append("\n");
+ }
+ Assert.assertEquals(resultStr.toString(), standard);
+ } catch (SQLException e) {
+ System.out.println(e);
+ }
+ }
+
+ /**
+ * get the timeseries number under a given path
+ */
+ @SuppressWarnings("resource")
+ @Test
+ public void CountTimeseries() throws Exception {
+ List<String> columnList = new ArrayList<>();
+ columnList.add("root.vehicle.d0.s0");
+ columnList.add("root.vehicle.d0.s1");
+ columnList.add("root.vehicle.d0.s2");
+
+ when(fetchMetadataResp.getColumnsList()).thenReturn(columnList);
+
+ String standard = "count,\n" + "3,\n";
+ try {
+ ResultSet resultSet = databaseMetaData.getColumns(Constant.COUNT_TIMESERIES, "root", null, null);
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ int colCount = resultSetMetaData.getColumnCount();
+ StringBuilder resultStr = new StringBuilder();
+ for (int i = 1; i < colCount + 1; i++) {
+ resultStr.append(resultSetMetaData.getColumnName(i)).append(",");
+ }
+ resultStr.append("\n");
+ while (resultSet.next()) {
+ for (int i = 1; i <= colCount; i++) {
+ resultStr.append(resultSet.getString(i)).append(",");
+ }
+ resultStr.append("\n");
+ }
+ Assert.assertEquals(resultStr.toString(), standard);
+ } catch (SQLException e) {
+ System.out.println(e);
+ }
+ }
+
+ /**
+ * get node number under a given node level
+ */
+ @SuppressWarnings("resource")
+ @Test
+ public void CountNodes() throws Exception {
+ List<String> nodes = new ArrayList<>();
+ nodes.add("root.vehicle1.d1");
+ nodes.add("root.vehicle1.d2");
+ nodes.add("root.vehicle2.d3");
+ nodes.add("root.vehicle2.d4");
+
+ when(fetchMetadataResp.getNodesList()).thenReturn(nodes);
+
+ String standard = "count,\n" + "4,\n";
+ try {
+ IoTDBDatabaseMetadata metadata = (IoTDBDatabaseMetadata) databaseMetaData;
+ String level = "3";
+ ResultSet resultSet = metadata.getNodes(Constant.COUNT_NODES, "root", null, null, level);
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ int colCount = resultSetMetaData.getColumnCount();
+ StringBuilder resultStr = new StringBuilder();
+ for (int i = 1; i < colCount + 1; i++) {
+ resultStr.append(resultSetMetaData.getColumnName(i)).append(",");
+ }
+ resultStr.append("\n");
+ while (resultSet.next()) {
+ for (int i = 1; i <= colCount; i++) {
+ resultStr.append(resultSet.getString(i)).append(",");
+ }
+ resultStr.append("\n");
+ }
+ Assert.assertEquals(resultStr.toString(), standard);
+ } catch (SQLException e) {
+ System.out.println(e);
+ }
+ }
+
+ /**
+ * get the timeseries number under a given node level
+ */
+ @SuppressWarnings("resource")
+ @Test
+ public void CountNodeTimeseries() throws Exception {
+ Map<String, String> nodeTimeseriesNum = new LinkedHashMap<>();
+ nodeTimeseriesNum.put("root.vehicle.d1", "3");
+ nodeTimeseriesNum.put("root.vehicle.d2", "2");
+ nodeTimeseriesNum.put("root.vehicle.d3", "4");
+ nodeTimeseriesNum.put("root.vehicle.d4", "2");
+
+ when(fetchMetadataResp.getNodeTimeseriesNum()).thenReturn(nodeTimeseriesNum);
+
+ String standard = "column,count,\n"
+ + "root.vehicle.d1,3,\n"
+ + "root.vehicle.d2,2,\n"
+ + "root.vehicle.d3,4,\n"
+ + "root.vehicle.d4,2,\n";
+ try {
+ IoTDBDatabaseMetadata metadata = (IoTDBDatabaseMetadata) databaseMetaData;
+ String level = "3";
+ ResultSet resultSet = metadata.getNodes(Constant.COUNT_NODE_TIMESERIES, "root", null, null, level);
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int colCount = resultSetMetaData.getColumnCount();
StringBuilder resultStr = new StringBuilder();
@@ -126,9 +237,10 @@ public class IoTDBDatabaseMetadataTest {
when(fetchMetadataResp.getColumnsList()).thenReturn(columnList);
- String standard = "Column,\n" + "root.vehicle.d0,\n";
- try (ResultSet resultSet = databaseMetaData
- .getColumns(Constant.CATALOG_DEVICE, "vehicle", null, null)) {
+ String standard = "column,\n" + "root.vehicle.d0,\n";
+ try {
+ ResultSet resultSet = databaseMetaData
+ .getColumns(Constant.CATALOG_DEVICE, "vehicle", null, null);
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int colCount = resultSetMetaData.getColumnCount();
StringBuilder resultStr = new StringBuilder();
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java b/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
index 64d10d5..c35e710 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
@@ -247,6 +247,10 @@ public class MGraph implements Serializable {
return mtree.getAllStorageGroup();
}
+ List<String> getNodesList(String nodeLevel) {
+ return mtree.getNodesList(nodeLevel);
+ }
+
List<String> getLeafNodePathInNextLevel(String path) throws PathErrorException {
return mtree.getLeafNodePathInNextLevel(path);
}
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 1116ff9..2da2f6c 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
@@ -18,23 +18,12 @@
*/
package org.apache.iotdb.db.metadata;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.io.*;
+import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.conf.adapter.IoTDBConfigDynamicAdapter;
-import org.apache.iotdb.db.engine.StorageEngine;
import org.apache.iotdb.db.exception.ConfigAdjusterException;
import org.apache.iotdb.db.exception.MetadataErrorException;
import org.apache.iotdb.db.exception.PathErrorException;
@@ -771,6 +760,21 @@ public class MManager {
}
/**
+ * Get all nodes from the given level
+ *
+ * @return A List instance which stores all node at given level
+ */
+ public List<String> getNodesList(String nodeLevel) {
+
+ lock.readLock().lock();
+ try {
+ return mgraph.getNodesList(nodeLevel);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /**
* @param path A seriesPath represented one Delta object
* @return a list contains all column schema
* @deprecated Get all MeasurementSchemas for given delta object type.
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java
index 13cfe0b..433b7d5 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java
@@ -106,6 +106,16 @@ public class MNode implements Serializable {
}
/**
+ * function for checking whether the mnode has child mnode.
+ */
+ public boolean hasChildren() {
+ if (!isLeaf) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
* function for checking whether mnode's children contain the given key.
*/
public boolean hasChild(String key) {
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 3c63144..df0032b 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
@@ -18,17 +18,12 @@
*/
package org.apache.iotdb.db.metadata;
+import java.io.Serializable;
+import java.util.*;
+
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
import org.apache.iotdb.db.exception.PathErrorException;
import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
@@ -765,6 +760,36 @@ public class MTree implements Serializable {
}
/**
+ * Get all nodes at the given level in current Metadata Tree.
+ *
+ * @return a list contains all nodes at the given level
+ */
+ List<String> getNodesList(String nodeLevel) {
+ List<String> res = new ArrayList<>();
+ int level = Integer.parseInt(nodeLevel);
+ MNode rootNode;
+ if ((rootNode = getRoot()) != null) {
+ findNodes(rootNode, "root", res, level);
+ }
+ return res;
+ }
+
+ private void findNodes(MNode node, String path, List<String> res, int targetLevel) {
+ if (node == null) {
+ return;
+ }
+ if (targetLevel == 1) {
+ res.add(path);
+ return;
+ }
+ if (node.hasChildren()) {
+ for (MNode child : node.getChildren().values()) {
+ findNodes(child, path + "." + child.toString(), res, targetLevel - 1);
+ }
+ }
+ }
+
+ /**
* Get all delta objects for given type.
*
* @param type device Type
diff --git a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 493331c..1c27656 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -18,6 +18,17 @@
*/
package org.apache.iotdb.db.service;
+import static org.apache.iotdb.db.conf.IoTDBConstant.*;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.regex.Pattern;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.AuthorityChecker;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
@@ -281,10 +292,19 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
resp.setDataType(getSeriesType(req.getColumnPath()).toString());
status = new TS_Status(getStatus(TSStatusType.SUCCESS_STATUS));
break;
+ case "COUNT_TIMESERIES":
case "ALL_COLUMNS":
resp.setColumnsList(getPaths(req.getColumnPath()));
status = new TS_Status(getStatus(TSStatusType.SUCCESS_STATUS));
break;
+ case "COUNT_NODES":
+ resp.setNodesList(getNodesList(req.getNodeLevel()));
+ status = new TS_Status(getStatus(TSStatusType.SUCCESS_STATUS));
+ break;
+ case "COUNT_NODE_TIMESERIES":
+ resp.setNodeTimeseriesNum(getNodeTimeseriesNum(getNodesList(req.getNodeLevel())));
+ status = new TS_Status(getStatus(TSStatusType.SUCCESS_STATUS));
+ break;
default:
status = getStatus(TSStatusType.FETCH_METADATA_ERROR, req.getType());
break;
@@ -302,6 +322,18 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
return resp;
}
+ private Map<String, String> getNodeTimeseriesNum(List<String> nodes) throws MetadataErrorException {
+ Map<String, String> nodeColumnsNum = new HashMap<>();
+ for (String columnPath : nodes) {
+ nodeColumnsNum.put(columnPath, Integer.toString(getPaths(columnPath).size()));
+ }
+ return nodeColumnsNum;
+ }
+
+ private List<String> getNodesList(String level) throws PathErrorException {
+ return MManager.getInstance().getNodesList(level);
+ }
+
private Set<String> getAllStorageGroups() throws PathErrorException {
return MManager.getInstance().getAllStorageGroup();
}
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 acdf8af..f50ab02 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
@@ -214,7 +214,7 @@ public class IoTDBMetadataFetchIT {
*/
private void allColumns() throws SQLException {
String standard =
- "Column,\n" + "root.ln.wf01.wt01.status,\n" + "root.ln.wf01.wt01.temperature,\n";
+ "column,\n" + "root.ln.wf01.wt01.status,\n" + "root.ln.wf01.wt01.temperature,\n";
try (ResultSet resultSet = databaseMetaData.getColumns(Constant.CATALOG_COLUMN, "root", null, null);) {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
@@ -238,7 +238,7 @@ public class IoTDBMetadataFetchIT {
* get all delta objects under a given column
*/
private void device() throws SQLException {
- String standard = "Column,\n" + "root.ln.wf01.wt01,\n";
+ String standard = "column,\n" + "root.ln.wf01.wt01,\n";
try (ResultSet resultSet = databaseMetaData.getColumns(Constant.CATALOG_DEVICE, "ln", null,
diff --git a/service-rpc/src/main/thrift/rpc.thrift b/service-rpc/src/main/thrift/rpc.thrift
index ec05a27..7727a66 100644
--- a/service-rpc/src/main/thrift/rpc.thrift
+++ b/service-rpc/src/main/thrift/rpc.thrift
@@ -196,11 +196,14 @@ struct TSFetchMetadataResp{
4: optional string dataType
5: optional list<list<string>> showTimeseriesList
7: optional set<string> showStorageGroups
+ 8: optional list<string> nodesList
+ 9: optional map<string, string> nodeTimeseriesNum
}
struct TSFetchMetadataReq{
1: required string type
2: optional string columnPath
+ 3: optional string nodeLevel
}
struct TSColumnSchema{