This is an automated email from the ASF dual-hosted git repository. Caideyipi pushed a commit to branch count-db in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 14d2d0b74553665e40ec2a6ba1e5c2b251f99159 Author: Caideyipi <[email protected]> AuthorDate: Mon May 18 12:27:29 2026 +0800 fix --- .../config/metadata/relational/CountDBTask.java | 6 +- .../metadata/relational/CountDBTaskTest.java | 107 +++++++++++++++++++++ .../sql/parser/CountDBStatementTest.java | 66 +++++++++++++ 3 files changed, 178 insertions(+), 1 deletion(-) 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 index 0b6e2864e2e..293d216856c 100644 --- 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 @@ -59,8 +59,12 @@ public class CountDBTask implements IConfigTask { final Map<String, ?> databaseInfoMap, final SettableFuture<ConfigTaskResult> future, final Predicate<String> canSeenDB) { + // information_schema is synthesized in table model rather than returned from ConfigNode. final long databaseCount = - databaseInfoMap.keySet().stream().filter(canSeenDB::test).count() + databaseInfoMap.keySet().stream() + .filter(databaseName -> !INFORMATION_DATABASE.equals(databaseName)) + .filter(canSeenDB::test) + .count() + (canSeenDB.test(INFORMATION_DATABASE) ? 1 : 0); final TsBlockBuilder builder = new TsBlockBuilder(Collections.singletonList(TSDataType.INT32)); diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/CountDBTaskTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/CountDBTaskTest.java new file mode 100644 index 00000000000..b29c11c2a91 --- /dev/null +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/CountDBTaskTest.java @@ -0,0 +1,107 @@ +/* + * 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.queryengine.plan.relational.sql.ast.NodeLocation; +import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult; +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.SettableFuture; +import org.apache.tsfile.read.common.block.TsBlock; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; + +import static org.apache.iotdb.commons.schema.table.InformationSchema.INFORMATION_DATABASE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class CountDBTaskTest { + + @Test + public void testBuildTSBlockCountsVisibleDatabases() throws Exception { + final Map<String, Object> databaseInfoMap = new HashMap<>(); + databaseInfoMap.put("db1", new Object()); + databaseInfoMap.put("db2", new Object()); + + final SettableFuture<ConfigTaskResult> future = SettableFuture.create(); + CountDBTask.buildTSBlock(databaseInfoMap, future, databaseName -> !"db2".equals(databaseName)); + + final ConfigTaskResult result = future.get(); + final TsBlock resultSet = result.getResultSet(); + + assertEquals(TSStatusCode.SUCCESS_STATUS, result.getStatusCode()); + assertEquals( + Collections.singletonList(IoTDBConstant.COLUMN_COUNT), + result.getResultSetHeader().getRespColumns()); + assertEquals(1, resultSet.getPositionCount()); + assertEquals(2, resultSet.getColumn(0).getInt(0)); + } + + @Test + public void testBuildTSBlockCanHideInformationSchema() throws Exception { + final Map<String, Object> databaseInfoMap = new HashMap<>(); + databaseInfoMap.put("db1", new Object()); + databaseInfoMap.put("db2", new Object()); + + final SettableFuture<ConfigTaskResult> future = SettableFuture.create(); + CountDBTask.buildTSBlock(databaseInfoMap, future, databaseName -> "db1".equals(databaseName)); + + final ConfigTaskResult result = future.get(); + assertEquals(1, result.getResultSet().getColumn(0).getInt(0)); + } + + @Test + public void testBuildTSBlockDoesNotDoubleCountInformationSchema() throws Exception { + final Map<String, Object> databaseInfoMap = new HashMap<>(); + databaseInfoMap.put("db1", new Object()); + databaseInfoMap.put(INFORMATION_DATABASE, new Object()); + + final SettableFuture<ConfigTaskResult> future = SettableFuture.create(); + CountDBTask.buildTSBlock(databaseInfoMap, future, databaseName -> true); + + final ConfigTaskResult result = future.get(); + assertEquals(2, result.getResultSet().getColumn(0).getInt(0)); + } + + @Test + public void testExecuteDelegatesToExecutor() throws Exception { + final CountDB node = new CountDB(new NodeLocation(1, 1)); + final Predicate<String> canSeenDB = databaseName -> true; + final CountDBTask task = new CountDBTask(node, canSeenDB); + final IConfigTaskExecutor executor = Mockito.mock(IConfigTaskExecutor.class); + final SettableFuture<ConfigTaskResult> future = SettableFuture.create(); + + when(executor.countDatabases(same(node), same(canSeenDB))).thenReturn(future); + + assertSame(future, task.execute(executor)); + verify(executor).countDatabases(same(node), same(canSeenDB)); + } +} diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/CountDBStatementTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/CountDBStatementTest.java new file mode 100644 index 00000000000..6d3dcc6bf52 --- /dev/null +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/CountDBStatementTest.java @@ -0,0 +1,66 @@ +/* + * 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.parser; + +import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement; +import org.apache.iotdb.db.protocol.session.IClientSession; +import org.apache.iotdb.db.protocol.session.InternalClientSession; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB; +import org.apache.iotdb.db.queryengine.plan.relational.sql.util.DataNodeSqlFormatter; + +import org.junit.Before; +import org.junit.Test; + +import java.time.ZoneId; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CountDBStatementTest { + + private SqlParser sqlParser; + private IClientSession clientSession; + + @Before + public void setUp() { + sqlParser = new SqlParser(); + clientSession = new InternalClientSession("testClient"); + } + + @Test + public void testCountDatabaseStatement() { + final Statement statement = + sqlParser.createStatement("count database", ZoneId.systemDefault(), clientSession); + + assertTrue(statement instanceof CountDB); + assertEquals("COUNT DATABASES", statement.toString()); + assertEquals("COUNT DATABASES", DataNodeSqlFormatter.formatDataNodeSql(statement)); + } + + @Test + public void testCountDatabasesStatement() { + final Statement statement = + sqlParser.createStatement("count databases", ZoneId.systemDefault(), clientSession); + + assertTrue(statement instanceof CountDB); + assertEquals("COUNT DATABASES", statement.toString()); + assertEquals("COUNT DATABASES", DataNodeSqlFormatter.formatDataNodeSql(statement)); + } +}
