This is an automated email from the ASF dual-hosted git repository.
Caideyipi 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 e71275167e8 count database
e71275167e8 is described below
commit e71275167e86dd7b79f82feeb6be93e02c9c3614
Author: Caideyipi <[email protected]>
AuthorDate: Mon May 18 11:24:42 2026 +0800
count database
---
.../relational/it/schema/IoTDBDatabaseIT.java | 35 ++++++++++
.../iotdb/db/queryengine/plan/Coordinator.java | 2 +
.../execution/config/TableConfigTaskVisitor.java | 11 +++
.../config/executor/ClusterConfigTaskExecutor.java | 20 ++++++
.../config/executor/IConfigTaskExecutor.java | 4 ++
.../config/metadata/relational/CountDBTask.java | 78 ++++++++++++++++++++++
.../plan/relational/sql/ast/AstVisitor.java | 4 ++
.../plan/relational/sql/ast/CountDB.java | 77 +++++++++++++++++++++
.../plan/relational/sql/parser/AstBuilder.java | 7 ++
.../relational/sql/util/DataNodeSqlFormatter.java | 9 ++-
.../db/relational/grammar/sql/RelationalSql.g4 | 5 ++
11 files changed, 251 insertions(+), 1 deletion(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
index 2b367b70b22..d52036ba75b 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
@@ -825,6 +825,29 @@ public class IoTDBDatabaseIT {
}
}
+ @Test
+ public void testCountDatabases() throws SQLException {
+ try (final Connection connection =
+ EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ final Statement statement = connection.createStatement()) {
+ statement.execute("create database db1");
+ statement.execute("create database db2");
+
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("count databases"),
+ "count,",
+ Collections.singleton("3,"));
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("count database"),
+ "count,",
+ Collections.singleton("3,"));
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("select count(*) from
information_schema.databases"),
+ "_col0,",
+ Collections.singleton("3,"));
+ }
+ }
+
@Test
public void testDBAuth() throws SQLException {
try (final Connection adminCon =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
@@ -838,6 +861,14 @@ public class IoTDBDatabaseIT {
try (final Connection userCon =
EnvFactory.getEnv().getConnection("test", "password123456",
BaseEnv.TABLE_SQL_DIALECT);
final Statement userStmt = userCon.createStatement()) {
+ TestUtils.assertResultSetEqual(
+ userStmt.executeQuery("count databases"),
+ "count,",
+ Collections.singleton("1,"));
+ TestUtils.assertResultSetEqual(
+ userStmt.executeQuery("count database"),
+ "count,",
+ Collections.singleton("1,"));
TestUtils.assertResultSetEqual(
userStmt.executeQuery("show databases"),
"Database,TTL(ms),SchemaReplicationFactor,DataReplicationFactor,TimePartitionInterval,",
@@ -869,6 +900,10 @@ public class IoTDBDatabaseIT {
try (final Connection userCon =
EnvFactory.getEnv().getConnection("test", "password123456",
BaseEnv.TABLE_SQL_DIALECT);
final Statement userStmt = userCon.createStatement()) {
+ TestUtils.assertResultSetEqual(
+ userStmt.executeQuery("count databases"),
+ "count,",
+ Collections.singleton("2,"));
try (final ResultSet resultSet = userStmt.executeQuery("SHOW
DATABASES")) {
final ResultSetMetaData metaData = resultSet.getMetaData();
assertEquals(showDBColumnHeaders.size(), metaData.getColumnCount());
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
index d2e76b218b1..bd1512aa428 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
@@ -78,6 +78,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AddColumn;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterColumnDataType;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ClearCache;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateExternalService;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction;
@@ -610,6 +611,7 @@ public class Coordinator {
queryContext.setTimeOut(timeOut);
queryContext.setStartTime(startTime);
if (statement instanceof DropDB
+ || statement instanceof CountDB
|| statement instanceof ShowDB
|| statement instanceof CreateDB
|| statement instanceof AlterDB
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
index e07bc920313..827590e86a0 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
@@ -99,6 +99,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableRenameTableTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableSetPropertiesTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ClearCacheTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CountDBTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateTableTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateTableViewTask;
@@ -156,6 +157,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterPipe;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ClearCache;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateExternalService;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction;
@@ -424,6 +426,15 @@ public class TableConfigTaskVisitor implements
AstVisitor<IConfigTask, MPPQueryC
canShowDB(accessControl, context.getSession().getUserName(),
databaseName, context));
}
+ @Override
+ public IConfigTask visitCountDB(final CountDB node, final MPPQueryContext
context) {
+ context.setQueryType(QueryType.READ);
+ return new CountDBTask(
+ node,
+ databaseName ->
+ canShowDB(accessControl, context.getSession().getUserName(),
databaseName, context));
+ }
+
public static boolean canShowDB(
final AccessControl accessControl,
final String userName,
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 3f632c9a987..ae4168eb132 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -229,6 +229,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.Ext
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.MigrateRegionTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.ReconstructRegionTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.RemoveRegionTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CountDBTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.DeleteDeviceTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.DescribeTableDetailsTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.DescribeTableTask;
@@ -255,6 +256,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.sys.subscription.Sh
import org.apache.iotdb.db.queryengine.plan.expression.Expression;
import
org.apache.iotdb.db.queryengine.plan.expression.visitor.TransformToViewExpressionVisitor;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.write.view.AlterLogicalViewNode;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DeleteDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCluster;
@@ -4140,6 +4142,24 @@ public class ClusterConfigTaskExecutor implements
IConfigTaskExecutor {
return future;
}
+ @Override
+ public SettableFuture<ConfigTaskResult> countDatabases(
+ final CountDB countDB, final Predicate<String> canSeenDB) {
+ final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
+ final List<String> databasePathPattern = Arrays.asList(ALL_RESULT_NODES);
+ try (final ConfigNodeClient client =
+
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
+ final TGetDatabaseReq req =
+ new TGetDatabaseReq(databasePathPattern, ALL_MATCH_SCOPE.serialize())
+ .setIsTableModel(true);
+ final TShowDatabaseResp resp = client.showDatabase(req);
+ CountDBTask.buildTSBlock(resp.getDatabaseInfoMap(), future, canSeenDB);
+ } catch (final IOException | ClientManagerException | TException e) {
+ future.setException(e);
+ }
+ return future;
+ }
+
@Override
public SettableFuture<ConfigTaskResult> showCluster(final ShowCluster
showCluster) {
// As the implementation is identical, we'll simply translate to the
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
index b4b928ba0b6..42caa6cd92e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
@@ -41,6 +41,7 @@ import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.Mig
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.ReconstructRegionTask;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.RemoveRegionTask;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.write.view.AlterLogicalViewNode;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DeleteDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowCluster;
@@ -333,6 +334,9 @@ public interface IConfigTaskExecutor {
SettableFuture<ConfigTaskResult> showDatabases(
final ShowDB showDB, final Predicate<String> canSeenDB);
+ SettableFuture<ConfigTaskResult> countDatabases(
+ final CountDB countDB, final Predicate<String> canSeenDB);
+
SettableFuture<ConfigTaskResult> showCluster(ShowCluster showCluster);
SettableFuture<ConfigTaskResult> useDatabase(final Use useDB, final
IClientSession clientSession);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/CountDBTask.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/CountDBTask.java
new file mode 100644
index 00000000000..0b6e2864e2e
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/CountDBTask.java
@@ -0,0 +1,78 @@
+/*
+ * 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.execution.config.metadata.relational;
+
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.schema.column.ColumnHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
+import org.apache.iotdb.db.queryengine.plan.execution.config.IConfigTask;
+import
org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlockBuilder;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.Predicate;
+
+import static
org.apache.iotdb.commons.schema.table.InformationSchema.INFORMATION_DATABASE;
+
+public class CountDBTask implements IConfigTask {
+
+ private final CountDB node;
+ private final Predicate<String> canSeenDB;
+
+ public CountDBTask(final CountDB node, final Predicate<String> canSeenDB) {
+ this.node = node;
+ this.canSeenDB = canSeenDB;
+ }
+
+ @Override
+ public ListenableFuture<ConfigTaskResult> execute(final IConfigTaskExecutor
configTaskExecutor)
+ throws InterruptedException {
+ return configTaskExecutor.countDatabases(node, canSeenDB);
+ }
+
+ public static void buildTSBlock(
+ final Map<String, ?> databaseInfoMap,
+ final SettableFuture<ConfigTaskResult> future,
+ final Predicate<String> canSeenDB) {
+ final long databaseCount =
+ databaseInfoMap.keySet().stream().filter(canSeenDB::test).count()
+ + (canSeenDB.test(INFORMATION_DATABASE) ? 1 : 0);
+
+ final TsBlockBuilder builder = new
TsBlockBuilder(Collections.singletonList(TSDataType.INT32));
+ builder.getTimeColumnBuilder().writeLong(0L);
+ builder.getColumnBuilder(0).writeInt((int) databaseCount);
+ builder.declarePosition();
+
+ final DatasetHeader datasetHeader =
+ new DatasetHeader(
+ Collections.singletonList(
+ new ColumnHeader(IoTDBConstant.COLUMN_COUNT,
TSDataType.INT32)),
+ true);
+ future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS,
builder.build(), datasetHeader));
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
index 2e236e116e8..7c311fa7f62 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
@@ -79,6 +79,10 @@ public interface AstVisitor<R, C> extends
CommonQueryAstVisitor<R, C> {
return visitStatement(node, context);
}
+ default R visitCountDB(final CountDB node, final C context) {
+ return visitStatement(node, context);
+ }
+
default R visitCreateTable(final CreateTable node, final C context) {
return visitStatement(node, context);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDB.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDB.java
new file mode 100644
index 00000000000..49f113421b2
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDB.java
@@ -0,0 +1,77 @@
+/*
+ * 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.relational.sql.ast;
+
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.AstMemoryEstimationHelper;
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.IAstVisitor;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Node;
+import
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.NodeLocation;
+import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.tsfile.utils.RamUsageEstimator;
+
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+public class CountDB extends Statement {
+
+ private static final long INSTANCE_SIZE =
RamUsageEstimator.shallowSizeOfInstance(CountDB.class);
+
+ public CountDB(final NodeLocation location) {
+ super(requireNonNull(location, "location is null"));
+ }
+
+ @Override
+ public <R, C> R accept(final IAstVisitor<R, C> visitor, final C context) {
+ return ((AstVisitor<R, C>) visitor).visitCountDB(this, context);
+ }
+
+ @Override
+ public List<Node> getChildren() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ return (obj != null) && (getClass() == obj.getClass());
+ }
+
+ @Override
+ public String toString() {
+ return "COUNT DATABASES";
+ }
+
+ @Override
+ public long ramBytesUsed() {
+ long size = INSTANCE_SIZE;
+ size +=
AstMemoryEstimationHelper.getEstimatedSizeOfNodeLocation(getLocationInternal());
+ return size;
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index 768a05689e8..25d68eba6be 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -162,6 +162,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AsofJoinOn;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ClearCache;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CopyTo;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountStatement;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
@@ -406,6 +407,12 @@ public class AstBuilder extends
RelationalSqlBaseVisitor<Node> {
return new ShowDB(getLocation(ctx), Objects.nonNull(ctx.DETAILS()));
}
+ @Override
+ public Node visitCountDatabasesStatement(
+ final RelationalSqlParser.CountDatabasesStatementContext ctx) {
+ return new CountDB(getLocation(ctx));
+ }
+
@Override
public Node visitCreateDbStatement(final
RelationalSqlParser.CreateDbStatementContext ctx) {
List<Property> properties = ImmutableList.of();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
index 4797d43cf21..b806fd72592 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/DataNodeSqlFormatter.java
@@ -32,6 +32,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterPipe;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CopyTo;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreatePipe;
@@ -134,7 +135,13 @@ public final class DataNodeSqlFormatter extends
CommonQuerySqlFormatter
@Override
public Void visitShowDB(ShowDB node, Integer indent) {
- builder.append("SHOW DATABASE");
+ builder.append("SHOW DATABASES");
+ return null;
+ }
+
+ @Override
+ public Void visitCountDB(CountDB node, Integer indent) {
+ builder.append("COUNT DATABASES");
return null;
}
diff --git
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index ca766464686..9263323b8f6 100644
---
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -49,6 +49,7 @@ statement
// Database Statement
| useDatabaseStatement
| showDatabasesStatement
+ | countDatabasesStatement
| createDbStatement
| alterDbStatement
| dropDbStatement
@@ -203,6 +204,10 @@ showDatabasesStatement
: SHOW DATABASES (DETAILS)?
;
+countDatabasesStatement
+ : COUNT (DATABASE | DATABASES)
+ ;
+
createDbStatement
: CREATE DATABASE (IF NOT EXISTS)? database=identifier (WITH properties)?
;