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 312d3841a97 Excluded system & audit from COUNT TIMESERIES and included 
views (#17703)
312d3841a97 is described below

commit 312d3841a9715f3ad24394ff38bb5ceccfb5183a
Author: Caideyipi <[email protected]>
AuthorDate: Thu May 28 18:02:47 2026 +0800

    Excluded system & audit from COUNT TIMESERIES and included views (#17703)
---
 .../iotdb/db/it/schema/IoTDBMetadataFetchIT.java   |  28 ++++
 .../regionscan/IoTDBActiveSchemaQueryIT.java       |  34 +++++
 .../db/queryengine/common/TimeseriesContext.java   | 106 ++++++++++++-
 .../schema/CountGroupByLevelScanOperator.java      |  15 +-
 .../operator/schema/SchemaCountOperator.java       |   4 +
 .../operator/schema/source/ISchemaSource.java      |   4 +
 .../schema/source/SchemaSourceFactory.java         |   3 +-
 .../schema/source/TimeSeriesSchemaSource.java      |  23 +++
 .../source/ActiveTimeSeriesRegionScanOperator.java |  15 +-
 .../queryengine/plan/analyze/AnalyzeVisitor.java   | 136 ++++++++++++++---
 .../plan/planner/OperatorTreeGenerator.java        |  44 ++++--
 .../operator/schema/SchemaCountOperatorTest.java   | 113 ++++++++++++++
 .../schema/source/TimeSeriesSchemaSourceTest.java  | 168 +++++++++++++++++++++
 13 files changed, 653 insertions(+), 40 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
index 1b6818d39f0..82f08cb81fc 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.util.AbstractSchemaIT;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runners.Parameterized;
@@ -494,6 +495,26 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT 
{
     }
   }
 
+  @Test
+  @Ignore
+  public void showCountTimeSeriesExcludeInternalDatabaseAndIncludeView() 
throws SQLException {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      final long baseVisibleCount = queryCount(statement, "COUNT TIMESERIES 
root.ln*.**");
+      statement.execute("CREATE DATABASE root.count_it");
+      statement.execute(
+          "CREATE TIMESERIES root.count_it.src.s1 WITH DATATYPE = INT32, 
ENCODING = PLAIN");
+      statement.execute(
+          "CREATE TIMESERIES root.count_it.src.s2 WITH DATATYPE = INT32, 
ENCODING = PLAIN");
+      statement.execute("CREATE VIEW root.count_it.dst.v1 AS SELECT s1 FROM 
root.count_it.src;");
+
+      final long localCount = queryCount(statement, "COUNT TIMESERIES 
root.count_it.**");
+      assertEquals(3L, localCount);
+      assertEquals(
+          baseVisibleCount + localCount, queryCount(statement, "COUNT 
TIMESERIES root.**"));
+    }
+  }
+
   @Test
   public void showCountTimeSeriesWithTag() throws SQLException {
     try (Connection connection = EnvFactory.getEnv().getConnection();
@@ -865,4 +886,11 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT 
{
       }
     }
   }
+
+  private long queryCount(final Statement statement, final String sql) throws 
SQLException {
+    try (ResultSet resultSet = statement.executeQuery(sql)) {
+      Assert.assertTrue(resultSet.next());
+      return resultSet.getLong(1);
+    }
+  }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/regionscan/IoTDBActiveSchemaQueryIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/regionscan/IoTDBActiveSchemaQueryIT.java
index c0e7673d7d6..dc706140fd3 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/regionscan/IoTDBActiveSchemaQueryIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/regionscan/IoTDBActiveSchemaQueryIT.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.util.AbstractSchemaIT;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runners.Parameterized;
@@ -236,6 +237,39 @@ public class IoTDBActiveSchemaQueryIT extends 
AbstractSchemaIT {
     }
   }
 
+  @Test
+  @Ignore
+  public void testCountTimeSeriesWithTimeConditionIncludesView() {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      statement.execute("CREATE DATABASE root.view_count");
+      statement.execute(
+          "CREATE TIMESERIES root.view_count.src.s1 WITH DATATYPE = INT32, 
ENCODING = PLAIN");
+      statement.execute(
+          "CREATE TIMESERIES root.view_count.src.s2 WITH DATATYPE = INT32, 
ENCODING = PLAIN");
+      statement.execute("CREATE VIEW root.view_count.dst.v1 AS SELECT s1 FROM 
root.view_count.src");
+
+      checkResultSet(
+          statement,
+          "count timeseries root.view_count.**",
+          new HashSet<>(Collections.singletonList("3,")));
+
+      statement.execute("insert into root.view_count.src(timestamp,s1) 
values(1,1)");
+
+      checkResultSet(
+          statement,
+          "count timeseries root.view_count.** where time>0",
+          new HashSet<>(Collections.singletonList("2,")));
+      checkResultSet(
+          statement,
+          "count timeseries root.view_count.dst.** where time>0",
+          new HashSet<>(Collections.singletonList("1,")));
+    } catch (Exception e) {
+      e.printStackTrace();
+      Assert.fail(e.getMessage());
+    }
+  }
+
   @Test
   public void testShowDevices() {
     try (Connection connection = EnvFactory.getEnv().getConnection();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/TimeseriesContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/TimeseriesContext.java
index 9225b97fc70..aaf8b51787d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/TimeseriesContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/TimeseriesContext.java
@@ -28,7 +28,10 @@ import org.apache.tsfile.utils.ReadWriteIOUtils;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Set;
 
 import static 
org.apache.iotdb.db.queryengine.execution.operator.schema.source.TimeSeriesSchemaSource.mapToString;
 
@@ -42,8 +45,17 @@ public class TimeseriesContext {
 
   private final String deadband;
   private final String deadbandParameters;
+  private final int activeCountMultiplier;
+  private final Set<String> activeLogicalViewCountSet;
 
   public TimeseriesContext(IMeasurementSchemaInfo schemaInfo) {
+    this(schemaInfo, 1, Collections.emptySet());
+  }
+
+  public TimeseriesContext(
+      IMeasurementSchemaInfo schemaInfo,
+      int activeCountMultiplier,
+      Set<String> activeLogicalViewCountSet) {
     this.dataType = schemaInfo.getSchema().getType().toString();
     this.encoding = schemaInfo.getSchema().getEncodingType().toString();
     this.compression = schemaInfo.getSchema().getCompressor().toString();
@@ -54,6 +66,8 @@ public class TimeseriesContext {
         MetaUtils.parseDeadbandInfo(schemaInfo.getSchema().getProps());
     this.deadband = deadbandInfo.left;
     this.deadbandParameters = deadbandInfo.right;
+    this.activeCountMultiplier = activeCountMultiplier;
+    this.activeLogicalViewCountSet = new HashSet<>(activeLogicalViewCountSet);
   }
 
   public String getDataType() {
@@ -88,6 +102,14 @@ public class TimeseriesContext {
     return deadband;
   }
 
+  public int getActiveCountMultiplier() {
+    return activeCountMultiplier;
+  }
+
+  public Set<String> getActiveLogicalViewCountSet() {
+    return activeLogicalViewCountSet;
+  }
+
   public TimeseriesContext(
       String dataType,
       String alias,
@@ -97,6 +119,30 @@ public class TimeseriesContext {
       String attributes,
       String deadband,
       String deadbandParameters) {
+    this(
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        1,
+        Collections.emptySet());
+  }
+
+  public TimeseriesContext(
+      String dataType,
+      String alias,
+      String encoding,
+      String compression,
+      String tags,
+      String attributes,
+      String deadband,
+      String deadbandParameters,
+      int activeCountMultiplier,
+      Set<String> activeLogicalViewCountSet) {
     this.dataType = dataType;
     this.alias = alias;
     this.encoding = encoding;
@@ -105,6 +151,24 @@ public class TimeseriesContext {
     this.attributes = attributes;
     this.deadband = deadband;
     this.deadbandParameters = deadbandParameters;
+    this.activeCountMultiplier = activeCountMultiplier;
+    this.activeLogicalViewCountSet = new HashSet<>(activeLogicalViewCountSet);
+  }
+
+  public TimeseriesContext mergeActiveCount(TimeseriesContext that) {
+    Set<String> mergedActiveLogicalViewCountSet = new 
HashSet<>(activeLogicalViewCountSet);
+    mergedActiveLogicalViewCountSet.addAll(that.activeLogicalViewCountSet);
+    return new TimeseriesContext(
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier + that.activeCountMultiplier,
+        mergedActiveLogicalViewCountSet);
   }
 
   public void serializeAttributes(ByteBuffer byteBuffer) {
@@ -116,6 +180,11 @@ public class TimeseriesContext {
     ReadWriteIOUtils.write(attributes, byteBuffer);
     ReadWriteIOUtils.write(deadband, byteBuffer);
     ReadWriteIOUtils.write(deadbandParameters, byteBuffer);
+    ReadWriteIOUtils.write(activeCountMultiplier, byteBuffer);
+    ReadWriteIOUtils.write(activeLogicalViewCountSet.size(), byteBuffer);
+    for (String logicalView : activeLogicalViewCountSet) {
+      ReadWriteIOUtils.write(logicalView, byteBuffer);
+    }
   }
 
   public void serializeAttributes(DataOutputStream stream) throws IOException {
@@ -127,6 +196,11 @@ public class TimeseriesContext {
     ReadWriteIOUtils.write(attributes, stream);
     ReadWriteIOUtils.write(deadband, stream);
     ReadWriteIOUtils.write(deadbandParameters, stream);
+    ReadWriteIOUtils.write(activeCountMultiplier, stream);
+    ReadWriteIOUtils.write(activeLogicalViewCountSet.size(), stream);
+    for (String logicalView : activeLogicalViewCountSet) {
+      ReadWriteIOUtils.write(logicalView, stream);
+    }
   }
 
   public static TimeseriesContext deserialize(ByteBuffer buffer) {
@@ -138,8 +212,23 @@ public class TimeseriesContext {
     String attributes = ReadWriteIOUtils.readString(buffer);
     String deadband = ReadWriteIOUtils.readString(buffer);
     String deadbandParameters = ReadWriteIOUtils.readString(buffer);
+    int activeCountMultiplier = ReadWriteIOUtils.readInt(buffer);
+    int activeLogicalViewCountSetSize = ReadWriteIOUtils.readInt(buffer);
+    Set<String> activeLogicalViewCountSet = new HashSet<>();
+    for (int i = 0; i < activeLogicalViewCountSetSize; i++) {
+      activeLogicalViewCountSet.add(ReadWriteIOUtils.readString(buffer));
+    }
     return new TimeseriesContext(
-        dataType, alias, encoding, compression, tags, attributes, deadband, 
deadbandParameters);
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier,
+        activeLogicalViewCountSet);
   }
 
   @Override
@@ -159,13 +248,24 @@ public class TimeseriesContext {
             && Objects.equals(tags, that.tags)
             && Objects.equals(attributes, that.attributes)
             && Objects.equals(deadband, that.deadband)
-            && Objects.equals(deadbandParameters, that.deadbandParameters);
+            && Objects.equals(deadbandParameters, that.deadbandParameters)
+            && activeCountMultiplier == that.activeCountMultiplier
+            && Objects.equals(activeLogicalViewCountSet, 
that.activeLogicalViewCountSet);
     return res;
   }
 
   @Override
   public int hashCode() {
     return Objects.hash(
-        dataType, alias, encoding, compression, tags, attributes, deadband, 
deadbandParameters);
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier,
+        activeLogicalViewCountSet);
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/CountGroupByLevelScanOperator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/CountGroupByLevelScanOperator.java
index 69f36680fb7..35c57dafa4d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/CountGroupByLevelScanOperator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/CountGroupByLevelScanOperator.java
@@ -27,6 +27,7 @@ import 
org.apache.iotdb.db.queryengine.execution.driver.SchemaDriverContext;
 import org.apache.iotdb.db.queryengine.execution.operator.OperatorContext;
 import 
org.apache.iotdb.db.queryengine.execution.operator.schema.source.ISchemaSource;
 import 
org.apache.iotdb.db.queryengine.execution.operator.source.SourceOperator;
+import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ISchemaInfo;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.reader.ISchemaReader;
 
@@ -95,6 +96,10 @@ public class CountGroupByLevelScanOperator<T extends 
ISchemaInfo> implements Sou
     return operatorContext;
   }
 
+  private ISchemaRegion getSchemaRegion() {
+    return ((SchemaDriverContext) 
operatorContext.getDriverContext()).getSchemaRegion();
+  }
+
   @Override
   public ListenableFuture<?> isBlocked() {
     if (isBlocked == null) {
@@ -109,6 +114,11 @@ public class CountGroupByLevelScanOperator<T extends 
ISchemaInfo> implements Sou
    */
   private ListenableFuture<?> tryGetNext() {
     if (schemaReader == null) {
+      if (schemaSource.shouldSkipSchemaRegion(getSchemaRegion())) {
+        next = null;
+        isFinished = true;
+        return NOT_BLOCKED;
+      }
       schemaReader = createTimeSeriesReader();
     }
     while (true) {
@@ -172,15 +182,14 @@ public class CountGroupByLevelScanOperator<T extends 
ISchemaInfo> implements Sou
   @Override
   public boolean hasNext() throws Exception {
     isBlocked().get(); // wait for the next TsBlock
-    if (!schemaReader.isSuccess()) {
+    if (schemaReader != null && !schemaReader.isSuccess()) {
       throw new SchemaExecutionException(schemaReader.getFailure());
     }
     return next != null;
   }
 
   public ISchemaReader<T> createTimeSeriesReader() {
-    return schemaSource.getSchemaReader(
-        ((SchemaDriverContext) 
operatorContext.getDriverContext()).getSchemaRegion());
+    return schemaSource.getSchemaReader(getSchemaRegion());
   }
 
   private TsBlock constructTsBlockAndClearMap(Map<PartialPath, Long> countMap) 
{
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
index 9b2884233c1..4cafe40c36b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperator.java
@@ -100,6 +100,10 @@ public class SchemaCountOperator<T extends ISchemaInfo> 
implements SourceOperato
    */
   private ListenableFuture<?> tryGetNext() {
     ISchemaRegion schemaRegion = getSchemaRegion();
+    if (schemaSource.shouldSkipSchemaRegion(schemaRegion)) {
+      next = constructTsBlock(0);
+      return NOT_BLOCKED;
+    }
     if (schemaSource.hasSchemaStatistic(schemaRegion)) {
       long statisticCount = schemaSource.getSchemaStatistic(schemaRegion);
       // Check if database path itself is counted as a device (bug fix)
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/ISchemaSource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/ISchemaSource.java
index 41bd5f3fbe0..4417203fdc8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/ISchemaSource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/ISchemaSource.java
@@ -57,6 +57,10 @@ public interface ISchemaSource<T extends ISchemaInfo> {
 
   long getSchemaStatistic(final ISchemaRegion schemaRegion);
 
+  default boolean shouldSkipSchemaRegion(final ISchemaRegion schemaRegion) {
+    return false;
+  }
+
   default boolean checkRegionDatabaseIncluded(final ISchemaRegion 
schemaRegion) {
     return true;
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
index 87560ad47be..f45dc6a9b06 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/SchemaSourceFactory.java
@@ -48,7 +48,7 @@ public class SchemaSourceFactory {
       Map<Integer, Template> templateMap,
       PathPatternTree scope) {
     return new TimeSeriesSchemaSource(
-        pathPattern, isPrefixMatch, 0, 0, schemaFilter, templateMap, false, 
scope, null);
+        pathPattern, isPrefixMatch, 0, 0, schemaFilter, templateMap, false, 
true, scope, null);
   }
 
   // show time series
@@ -69,6 +69,7 @@ public class SchemaSourceFactory {
         schemaFilter,
         templateMap,
         true,
+        false,
         scope,
         timeseriesOrdering);
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSource.java
index a56cfa228bf..5ac6d59b089 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSource.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.commons.schema.SchemaConstant;
 import org.apache.iotdb.commons.schema.column.ColumnHeader;
 import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
 import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.commons.schema.table.Audit;
 import org.apache.iotdb.commons.schema.template.Template;
 import org.apache.iotdb.commons.schema.view.ViewType;
 import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
@@ -55,6 +56,7 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
   private final SchemaFilter schemaFilter;
   private final Map<Integer, Template> templateMap;
   private final boolean needViewDetail;
+  private final boolean excludeInternalDatabase;
   private final Ordering timeseriesOrdering;
 
   TimeSeriesSchemaSource(
@@ -65,6 +67,7 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
       SchemaFilter schemaFilter,
       Map<Integer, Template> templateMap,
       boolean needViewDetail,
+      boolean excludeInternalDatabase,
       PathPatternTree scope,
       Ordering timeseriesOrdering) {
     this.pathPattern = pathPattern;
@@ -74,6 +77,7 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
     this.schemaFilter = schemaFilter;
     this.templateMap = templateMap;
     this.needViewDetail = needViewDetail;
+    this.excludeInternalDatabase = excludeInternalDatabase;
     this.scope = scope;
     this.timeseriesOrdering = timeseriesOrdering;
   }
@@ -141,6 +145,25 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
     return schemaRegion.getSchemaRegionStatistics().getSeriesNumber(true);
   }
 
+  @Override
+  public boolean shouldSkipSchemaRegion(final ISchemaRegion schemaRegion) {
+    if (!excludeInternalDatabase) {
+      return false;
+    }
+
+    final String database = schemaRegion.getDatabaseFullPath();
+    if (!SchemaConstant.SYSTEM_DATABASE.equals(database)
+        && !SchemaConstant.AUDIT_DATABASE.equals(database)
+        && !Audit.TABLE_MODEL_AUDIT_DATABASE.equals(database)) {
+      return false;
+    }
+
+    final String[] nodes = pathPattern.getNodes();
+    return nodes.length < 2
+        || !SchemaConstant.ROOT.equals(nodes[0])
+        || !database.endsWith("." + nodes[1]);
+  }
+
   public static String mapToString(Map<String, String> map) {
     if (map == null || map.isEmpty()) {
       return null;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/ActiveTimeSeriesRegionScanOperator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/ActiveTimeSeriesRegionScanOperator.java
index b6ac9ecd850..2dd1272f473 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/ActiveTimeSeriesRegionScanOperator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/ActiveTimeSeriesRegionScanOperator.java
@@ -35,13 +35,16 @@ import org.apache.tsfile.utils.Binary;
 import org.apache.tsfile.utils.RamUsageEstimator;
 
 import java.io.IOException;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSourceOperator {
   // Timeseries which need to be checked.
   private final Map<IDeviceID, Map<String, TimeseriesContext>> 
timeSeriesToSchemasInfo;
+  private final Set<String> countedLogicalViews;
   private static final Binary VIEW_TYPE = new Binary("BASE".getBytes());
   private final Binary dataBaseName;
   private static final long INSTANCE_SIZE =
@@ -60,6 +63,7 @@ public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSo
     this.operatorContext = operatorContext;
     this.sourceId = sourceId;
     this.timeSeriesToSchemasInfo = timeSeriesToSchemasInfo;
+    this.countedLogicalViews = new HashSet<>();
     this.regionScanUtil = new RegionScanForActiveTimeSeriesUtil(timeFilter, 
ttlCache);
     this.dataBaseName =
         new Binary(
@@ -101,7 +105,16 @@ public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSo
     if (outputCount) {
       for (Map.Entry<IDeviceID, List<String>> entry : 
activeTimeSeries.entrySet()) {
         List<String> timeSeriesList = entry.getValue();
-        count += timeSeriesList.size();
+        Map<String, TimeseriesContext> timeSeriesInfo = 
timeSeriesToSchemasInfo.get(entry.getKey());
+        for (String timeSeries : timeSeriesList) {
+          TimeseriesContext schemaInfo = timeSeriesInfo.get(timeSeries);
+          count += schemaInfo.getActiveCountMultiplier();
+          for (String logicalView : schemaInfo.getActiveLogicalViewCountSet()) 
{
+            if (countedLogicalViews.add(logicalView)) {
+              count++;
+            }
+          }
+        }
         removeTimeseriesListFromDevice(entry.getKey(), timeSeriesList);
       }
       return;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 7aa8d1e8636..9d91a29d78b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -2931,7 +2931,8 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       Analysis analysis,
       MPPQueryContext context,
       PathPatternTree authorityScope,
-      boolean canSeeAuditDB)
+      boolean canSeeAuditDB,
+      boolean includeLogicalView)
       throws IllegalPathException {
     analyzeGlobalTimeConditionInShowMetaData(timeCondition, analysis);
     context.generateGlobalTimeFilter(analysis);
@@ -2944,7 +2945,15 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       analysis.setFinishQueryAfterAnalyze(true);
       return false;
     }
-    removeLogicViewMeasurement(schemaTree);
+    List<DeviceSchemaInfo> deviceSchemaInfoList;
+    if (includeLogicalView) {
+      deviceSchemaInfoList = schemaTree.getMatchedDevices(ALL_MATCH_PATTERN);
+      updateSchemaTreeByViews(analysis, schemaTree, context, canSeeAuditDB);
+    } else {
+      removeLogicViewMeasurement(schemaTree);
+      deviceSchemaInfoList = schemaTree.getMatchedDevices(ALL_MATCH_PATTERN);
+    }
+
     Map<PartialPath, Map<PartialPath, List<TimeseriesContext>>> 
deviceToTimeseriesContext =
         new HashMap<>();
     /**
@@ -2952,38 +2961,56 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
      * as a normal node, not a device+templateId. This means that all nodes 
are what we need.). We
      * can use ALL_MATCH_PATTERN to get result.
      */
-    List<DeviceSchemaInfo> deviceSchemaInfoList = 
schemaTree.getMatchedDevices(ALL_MATCH_PATTERN);
     Set<IDeviceID> deviceSet = new HashSet<>();
     for (DeviceSchemaInfo deviceSchemaInfo : deviceSchemaInfoList) {
       boolean isAligned = deviceSchemaInfo.isAligned();
       PartialPath devicePath = deviceSchemaInfo.getDevicePath();
-      deviceSet.add(devicePath.getIDeviceIDAsFullDevice());
       if (isAligned) {
         List<String> measurementList = new ArrayList<>();
         List<IMeasurementSchema> schemaList = new ArrayList<>();
         List<TimeseriesContext> timeseriesContextList = new ArrayList<>();
         for (IMeasurementSchemaInfo measurementSchemaInfo :
             deviceSchemaInfo.getMeasurementSchemaInfoList()) {
+          if (includeLogicalView && measurementSchemaInfo.isLogicalView()) {
+            addLogicalViewSourcesForActiveCount(
+                devicePath,
+                measurementSchemaInfo,
+                schemaTree,
+                deviceToTimeseriesContext,
+                deviceSet);
+            continue;
+          }
           schemaList.add(measurementSchemaInfo.getSchema());
           measurementList.add(measurementSchemaInfo.getName());
           timeseriesContextList.add(new 
TimeseriesContext(measurementSchemaInfo));
         }
-        AlignedPath alignedPath =
-            new AlignedPath(devicePath.getNodes(), measurementList, 
schemaList);
-        deviceToTimeseriesContext
-            .computeIfAbsent(devicePath, k -> new HashMap<>())
-            .put(alignedPath, timeseriesContextList);
+        if (!measurementList.isEmpty()) {
+          deviceSet.add(devicePath.getIDeviceIDAsFullDevice());
+          AlignedPath alignedPath =
+              new AlignedPath(devicePath.getNodes(), measurementList, 
schemaList);
+          deviceToTimeseriesContext
+              .computeIfAbsent(devicePath, k -> new HashMap<>())
+              .put(alignedPath, timeseriesContextList);
+        }
       } else {
         for (IMeasurementSchemaInfo measurementSchemaInfo :
             deviceSchemaInfo.getMeasurementSchemaInfoList()) {
-          MeasurementPath measurementPath =
-              new MeasurementPath(
-                  
devicePath.concatNode(measurementSchemaInfo.getName()).getNodes());
-          deviceToTimeseriesContext
-              .computeIfAbsent(devicePath, k -> new HashMap<>())
-              .put(
-                  measurementPath,
-                  Collections.singletonList(new 
TimeseriesContext(measurementSchemaInfo)));
+          if (includeLogicalView && measurementSchemaInfo.isLogicalView()) {
+            addLogicalViewSourcesForActiveCount(
+                devicePath,
+                measurementSchemaInfo,
+                schemaTree,
+                deviceToTimeseriesContext,
+                deviceSet);
+          } else {
+            addPhysicalTimeseriesForActiveCount(
+                devicePath,
+                measurementSchemaInfo,
+                false,
+                new TimeseriesContext(measurementSchemaInfo),
+                deviceToTimeseriesContext,
+                deviceSet);
+          }
         }
       }
     }
@@ -2995,6 +3022,75 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     return true;
   }
 
+  private void addLogicalViewSourcesForActiveCount(
+      PartialPath viewDevicePath,
+      IMeasurementSchemaInfo viewSchemaInfo,
+      ISchemaTree schemaTree,
+      Map<PartialPath, Map<PartialPath, List<TimeseriesContext>>> 
deviceToTimeseriesContext,
+      Set<IDeviceID> deviceSet) {
+    LogicalViewSchema logicalViewSchema = 
viewSchemaInfo.getSchemaAsLogicalViewSchema();
+    if (logicalViewSchema == null) {
+      return;
+    }
+
+    String viewPath = 
viewDevicePath.concatNode(viewSchemaInfo.getName()).getFullPath();
+    for (PartialPath sourcePath : 
getSourcePaths(logicalViewSchema.getExpression())) {
+      if (sourcePath.getNodeLength() <= 1) {
+        continue;
+      }
+      PartialPath sourceDevicePath =
+          new PartialPath(Arrays.copyOf(sourcePath.getNodes(), 
sourcePath.getNodeLength() - 1));
+      DeviceSchemaInfo sourceDeviceSchemaInfo =
+          schemaTree.searchDeviceSchemaInfo(
+              sourceDevicePath, 
Collections.singletonList(sourcePath.getMeasurement()));
+      if (sourceDeviceSchemaInfo == null
+          || sourceDeviceSchemaInfo.getMeasurementSchemaInfoList().isEmpty()) {
+        continue;
+      }
+
+      IMeasurementSchemaInfo sourceSchemaInfo =
+          sourceDeviceSchemaInfo.getMeasurementSchemaInfoList().get(0);
+      if (sourceSchemaInfo == null || sourceSchemaInfo.isLogicalView()) {
+        continue;
+      }
+
+      addPhysicalTimeseriesForActiveCount(
+          sourceDevicePath,
+          sourceSchemaInfo,
+          sourceDeviceSchemaInfo.isAligned(),
+          new TimeseriesContext(sourceSchemaInfo, 0, 
Collections.singleton(viewPath)),
+          deviceToTimeseriesContext,
+          deviceSet);
+    }
+  }
+
+  private void addPhysicalTimeseriesForActiveCount(
+      PartialPath devicePath,
+      IMeasurementSchemaInfo measurementSchemaInfo,
+      boolean isAligned,
+      TimeseriesContext timeseriesContext,
+      Map<PartialPath, Map<PartialPath, List<TimeseriesContext>>> 
deviceToTimeseriesContext,
+      Set<IDeviceID> deviceSet) {
+    deviceSet.add(devicePath.getIDeviceIDAsFullDevice());
+    PartialPath timeseriesPath =
+        isAligned
+            ? new AlignedPath(
+                devicePath.getNodes(),
+                Collections.singletonList(measurementSchemaInfo.getName()),
+                Collections.singletonList(measurementSchemaInfo.getSchema()))
+            : new MeasurementPath(
+                
devicePath.concatNode(measurementSchemaInfo.getName()).getNodes());
+    Map<PartialPath, List<TimeseriesContext>> timeseriesContextMap =
+        deviceToTimeseriesContext.computeIfAbsent(devicePath, k -> new 
HashMap<>());
+    List<TimeseriesContext> existingContextList = 
timeseriesContextMap.get(timeseriesPath);
+    if (existingContextList == null) {
+      timeseriesContextMap.put(
+          timeseriesPath, new 
ArrayList<>(Collections.singletonList(timeseriesContext)));
+    } else {
+      existingContextList.set(0, 
existingContextList.get(0).mergeActiveCount(timeseriesContext));
+    }
+  }
+
   @Override
   public Analysis visitShowTimeSeries(
       ShowTimeSeriesStatement showTimeSeriesStatement, MPPQueryContext 
context) {
@@ -3020,7 +3116,8 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
                 analysis,
                 context,
                 showTimeSeriesStatement.getAuthorityScope(),
-                showTimeSeriesStatement.isCanSeeAuditDB());
+                showTimeSeriesStatement.isCanSeeAuditDB(),
+                false);
         if (!hasSchema) {
           
analysis.setRespDatasetHeader(DatasetHeaderFactory.getShowTimeSeriesHeader());
           return analysis;
@@ -3271,7 +3368,8 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
                 analysis,
                 context,
                 countTimeSeriesStatement.getAuthorityScope(),
-                countTimeSeriesStatement.isCanSeeAuditDB());
+                countTimeSeriesStatement.isCanSeeAuditDB(),
+                true);
         if (!hasSchema) {
           
analysis.setRespDatasetHeader(DatasetHeaderFactory.getCountTimeSeriesHeader());
           return analysis;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
index 9f1aa7fc291..7ed81c7e842 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
@@ -3745,13 +3745,20 @@ public class OperatorTreeGenerator implements 
PlanVisitor<Operator, LocalExecuti
     for (Map.Entry<PartialPath, List<TimeseriesContext>> entry : 
entryMap.getValue().entrySet()) {
       PartialPath path = entry.getKey();
       if (path instanceof MeasurementPath) {
-        timeseriesSchemaInfoMap.put(path.getMeasurement(), 
entry.getValue().get(0));
-        context.addPath(
-            new NonAlignedFullPath(
-                path.getIDeviceID(),
-                new MeasurementSchema(
-                    path.getMeasurement(),
-                    
TSDataType.valueOf(entry.getValue().get(0).getDataType()))));
+        String measurement = path.getMeasurement();
+        TimeseriesContext timeseriesContext = entry.getValue().get(0);
+        TimeseriesContext existingContext = 
timeseriesSchemaInfoMap.get(measurement);
+        if (existingContext == null) {
+          timeseriesSchemaInfoMap.put(measurement, timeseriesContext);
+          context.addPath(
+              new NonAlignedFullPath(
+                  path.getIDeviceID(),
+                  new MeasurementSchema(
+                      measurement, 
TSDataType.valueOf(timeseriesContext.getDataType()))));
+        } else {
+          timeseriesSchemaInfoMap.put(
+              measurement, 
existingContext.mergeActiveCount(timeseriesContext));
+        }
       } else if (path instanceof AlignedPath) {
         AlignedPath alignedPath = (AlignedPath) path;
         List<String> measurementList = alignedPath.getMeasurementList();
@@ -3761,14 +3768,25 @@ public class OperatorTreeGenerator implements 
PlanVisitor<Operator, LocalExecuti
         }
         int size = measurementList.size();
         List<IMeasurementSchema> schemaList = new ArrayList<>(size);
+        List<String> newMeasurementList = new ArrayList<>(size);
         for (int i = 0; i < size; i++) {
-          timeseriesSchemaInfoMap.put(measurementList.get(i), 
entry.getValue().get(i));
-          schemaList.add(
-              new MeasurementSchema(
-                  measurementList.get(i),
-                  TSDataType.valueOf(entry.getValue().get(i).getDataType())));
+          String measurement = measurementList.get(i);
+          TimeseriesContext timeseriesContext = entry.getValue().get(i);
+          TimeseriesContext existingContext = 
timeseriesSchemaInfoMap.get(measurement);
+          if (existingContext == null) {
+            timeseriesSchemaInfoMap.put(measurement, timeseriesContext);
+            newMeasurementList.add(measurement);
+            schemaList.add(
+                new MeasurementSchema(
+                    measurement, 
TSDataType.valueOf(timeseriesContext.getDataType())));
+          } else {
+            timeseriesSchemaInfoMap.put(
+                measurement, 
existingContext.mergeActiveCount(timeseriesContext));
+          }
+        }
+        if (!newMeasurementList.isEmpty()) {
+          context.addPath(new AlignedFullPath(path.getIDeviceID(), 
newMeasurementList, schemaList));
         }
-        context.addPath(new AlignedFullPath(path.getIDeviceID(), 
measurementList, schemaList));
       }
     }
     return timeseriesSchemaInfoMap;
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperatorTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperatorTest.java
index b59689a8deb..3cd50ebf513 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperatorTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaCountOperatorTest.java
@@ -114,6 +114,82 @@ public class SchemaCountOperatorTest {
     }
   }
 
+  @Test
+  public void testSchemaCountOperatorSkipSchemaRegion() throws Exception {
+    ExecutorService instanceNotificationExecutor =
+        IoTDBThreadPoolFactory.newFixedThreadPool(1, 
"test-instance-notification");
+    try {
+      QueryId queryId = new QueryId("stub_query");
+      FragmentInstanceId instanceId =
+          new FragmentInstanceId(new PlanFragmentId(queryId, 0), 
"stub-instance");
+      FragmentInstanceStateMachine stateMachine =
+          new FragmentInstanceStateMachine(instanceId, 
instanceNotificationExecutor);
+      FragmentInstanceContext fragmentInstanceContext =
+          createFragmentInstanceContext(instanceId, stateMachine);
+      DriverContext driverContext = new DriverContext(fragmentInstanceContext, 
0);
+      PlanNodeId planNodeId = queryId.genPlanNodeId();
+      ISchemaRegion schemaRegion = Mockito.mock(ISchemaRegion.class);
+      OperatorContext operatorContext =
+          driverContext.addOperatorContext(
+              1, planNodeId, SchemaCountOperator.class.getSimpleName());
+      operatorContext.setDriverContext(
+          new SchemaDriverContext(fragmentInstanceContext, schemaRegion, 0));
+      ISchemaSource<ISchemaInfo> schemaSource = 
Mockito.mock(ISchemaSource.class);
+      
Mockito.when(schemaSource.shouldSkipSchemaRegion(schemaRegion)).thenReturn(true);
+
+      SchemaCountOperator<?> schemaCountOperator =
+          new SchemaCountOperator<>(
+              planNodeId, driverContext.getOperatorContexts().get(0), 
schemaSource);
+
+      assertTrue(schemaCountOperator.hasNext());
+      TsBlock tsBlock = schemaCountOperator.next();
+      assertEquals(0, tsBlock.getColumn(0).getLong(0));
+      assertTrue(schemaCountOperator.isFinished());
+      Mockito.verify(schemaSource, 
Mockito.never()).getSchemaReader(schemaRegion);
+    } finally {
+      instanceNotificationExecutor.shutdown();
+    }
+  }
+
+  @Test
+  public void testSchemaCountOperatorUseSchemaStatistic() throws Exception {
+    ExecutorService instanceNotificationExecutor =
+        IoTDBThreadPoolFactory.newFixedThreadPool(1, 
"test-instance-notification");
+    try {
+      QueryId queryId = new QueryId("stub_query");
+      FragmentInstanceId instanceId =
+          new FragmentInstanceId(new PlanFragmentId(queryId, 0), 
"stub-instance");
+      FragmentInstanceStateMachine stateMachine =
+          new FragmentInstanceStateMachine(instanceId, 
instanceNotificationExecutor);
+      FragmentInstanceContext fragmentInstanceContext =
+          createFragmentInstanceContext(instanceId, stateMachine);
+      DriverContext driverContext = new DriverContext(fragmentInstanceContext, 
0);
+      PlanNodeId planNodeId = queryId.genPlanNodeId();
+      ISchemaRegion schemaRegion = Mockito.mock(ISchemaRegion.class);
+      OperatorContext operatorContext =
+          driverContext.addOperatorContext(
+              1, planNodeId, SchemaCountOperator.class.getSimpleName());
+      operatorContext.setDriverContext(
+          new SchemaDriverContext(fragmentInstanceContext, schemaRegion, 0));
+      ISchemaSource<ISchemaInfo> schemaSource = 
Mockito.mock(ISchemaSource.class);
+      
Mockito.when(schemaSource.hasSchemaStatistic(schemaRegion)).thenReturn(true);
+      
Mockito.when(schemaSource.getSchemaStatistic(schemaRegion)).thenReturn(7L);
+      
Mockito.when(schemaSource.checkRegionDatabaseIncluded(schemaRegion)).thenReturn(true);
+
+      SchemaCountOperator<?> schemaCountOperator =
+          new SchemaCountOperator<>(
+              planNodeId, driverContext.getOperatorContexts().get(0), 
schemaSource);
+
+      assertTrue(schemaCountOperator.hasNext());
+      TsBlock tsBlock = schemaCountOperator.next();
+      assertEquals(7, tsBlock.getColumn(0).getLong(0));
+      Mockito.verify(schemaSource).getSchemaStatistic(schemaRegion);
+      Mockito.verify(schemaSource, 
Mockito.never()).getSchemaReader(schemaRegion);
+    } finally {
+      instanceNotificationExecutor.shutdown();
+    }
+  }
+
   @Test
   public void testLevelTimeSeriesCountOperator() {
     ExecutorService instanceNotificationExecutor =
@@ -185,6 +261,43 @@ public class SchemaCountOperatorTest {
     }
   }
 
+  @Test
+  public void testLevelTimeSeriesCountOperatorSkipSchemaRegion() {
+    ExecutorService instanceNotificationExecutor =
+        IoTDBThreadPoolFactory.newFixedThreadPool(1, 
"test-instance-notification");
+    try {
+      QueryId queryId = new QueryId("stub_query");
+      FragmentInstanceId instanceId =
+          new FragmentInstanceId(new PlanFragmentId(queryId, 0), 
"stub-instance");
+      FragmentInstanceStateMachine stateMachine =
+          new FragmentInstanceStateMachine(instanceId, 
instanceNotificationExecutor);
+      FragmentInstanceContext fragmentInstanceContext =
+          createFragmentInstanceContext(instanceId, stateMachine);
+      DriverContext driverContext = new DriverContext(fragmentInstanceContext, 
0);
+      PlanNodeId planNodeId = queryId.genPlanNodeId();
+      OperatorContext operatorContext =
+          driverContext.addOperatorContext(
+              1, planNodeId, 
CountGroupByLevelScanOperator.class.getSimpleName());
+      ISchemaRegion schemaRegion = Mockito.mock(ISchemaRegion.class);
+      operatorContext.setDriverContext(
+          new SchemaDriverContext(fragmentInstanceContext, schemaRegion, 0));
+      ISchemaSource<ITimeSeriesSchemaInfo> schemaSource = 
Mockito.mock(ISchemaSource.class);
+      
Mockito.when(schemaSource.shouldSkipSchemaRegion(schemaRegion)).thenReturn(true);
+
+      CountGroupByLevelScanOperator<ITimeSeriesSchemaInfo> 
timeSeriesCountOperator =
+          new CountGroupByLevelScanOperator<>(
+              planNodeId, driverContext.getOperatorContexts().get(0), 1, 
schemaSource);
+
+      assertTrue(collectResult(timeSeriesCountOperator).isEmpty());
+      Mockito.verify(schemaSource, 
Mockito.never()).getSchemaReader(schemaRegion);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail();
+    } finally {
+      instanceNotificationExecutor.shutdown();
+    }
+  }
+
   private List<TsBlock> collectResult(CountGroupByLevelScanOperator<?> 
operator) throws Exception {
     List<TsBlock> tsBlocks = new ArrayList<>();
     while (operator.hasNext()) {
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSourceTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSourceTest.java
new file mode 100644
index 00000000000..3769018ed46
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSourceTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.execution.operator.schema.source;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.SchemaConstant;
+import org.apache.iotdb.commons.schema.table.Audit;
+import org.apache.iotdb.db.schemaengine.rescon.ISchemaRegionStatistics;
+import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
+import 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.ITimeSeriesSchemaInfo;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class TimeSeriesSchemaSourceTest {
+
+  @Test
+  public void testCountSourceSkipsImplicitInternalDatabases() throws Exception 
{
+    final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+
+    assertTrue(
+        
countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+    
assertTrue(countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+    assertTrue(
+        
countSource.shouldSkipSchemaRegion(mockSchemaRegion(Audit.TABLE_MODEL_AUDIT_DATABASE)));
+    
assertFalse(countSource.shouldSkipSchemaRegion(mockSchemaRegion("root.sg")));
+  }
+
+  @Test
+  public void testCountSourceKeepsExplicitInternalDatabaseQueries() throws 
Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> systemCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.__system.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+    assertFalse(
+        
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+    assertTrue(
+        
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+
+    final ISchemaSource<ITimeSeriesSchemaInfo> auditCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.__audit.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+    assertFalse(
+        
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+    assertTrue(
+        
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+  }
+
+  @Test
+  public void testCountSourceSkipsWildcardSecondNodeForInternalDatabases() 
throws Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.*.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+
+    assertTrue(
+        
countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+    
assertTrue(countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+    
assertFalse(countSource.shouldSkipSchemaRegion(mockSchemaRegion("root.sg")));
+  }
+
+  @Test
+  public void testCountSourceKeepsExactInternalDatabaseQueries() throws 
Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> systemCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.__system"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+    assertFalse(
+        
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+
+    final ISchemaSource<ITimeSeriesSchemaInfo> auditCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.__audit"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+    assertFalse(
+        
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+  }
+
+  @Test
+  public void testShowSourceDoesNotSkipInternalDatabases() throws Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> showSource =
+        SchemaSourceFactory.getTimeSeriesSchemaScanSource(
+            new PartialPath("root.**"),
+            false,
+            0,
+            0,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE,
+            null);
+
+    assertFalse(
+        
showSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+    
assertFalse(showSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+  }
+
+  @Test
+  public void testCountStatisticIncludesView() throws Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.sg.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE);
+    final ISchemaRegion schemaRegion = mockSchemaRegion("root.sg");
+    final ISchemaRegionStatistics schemaRegionStatistics =
+        Mockito.mock(ISchemaRegionStatistics.class);
+
+    
Mockito.when(schemaRegion.getSchemaRegionStatistics()).thenReturn(schemaRegionStatistics);
+    Mockito.when(schemaRegionStatistics.getSeriesNumber(true)).thenReturn(5L);
+
+    assertEquals(5L, countSource.getSchemaStatistic(schemaRegion));
+    Mockito.verify(schemaRegionStatistics).getSeriesNumber(true);
+    Mockito.verify(schemaRegionStatistics, 
Mockito.never()).getSeriesNumber(false);
+  }
+
+  private ISchemaRegion mockSchemaRegion(final String database) {
+    final ISchemaRegion schemaRegion = Mockito.mock(ISchemaRegion.class);
+    Mockito.when(schemaRegion.getDatabaseFullPath()).thenReturn(database);
+    return schemaRegion;
+  }
+}

Reply via email to