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

Caideyipi pushed a commit to branch to-rc/2010
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 3c45f43308c67ed3a88cb98754246a50f72b22b4
Author: Caideyipi <[email protected]>
AuthorDate: Wed Jun 3 15:45:39 2026 +0800

    Fix count and show timeseries follow-up (#17804)
    
    * Fix count and show timeseries follow-up
    
    * Refine internal timeseries count permissions
    
    * fix
---
 .../regionscan/IoTDBActiveSchemaQueryIT.java       |  47 ++++
 .../impl/DataNodeInternalRPCServiceImpl.java       |   6 +-
 .../db/queryengine/common/TimeseriesContext.java   | 294 ++++++++++++++++++++-
 .../schema/CountGroupByLevelScanOperator.java      |  15 +-
 .../operator/schema/SchemaCountOperator.java       |   4 +
 .../operator/schema/source/ISchemaSource.java      |   4 +
 .../schema/source/SchemaSourceFactory.java         |  18 +-
 .../schema/source/TimeSeriesSchemaSource.java      |  20 ++
 .../source/ActiveTimeSeriesRegionScanOperator.java |  92 +++++--
 .../queryengine/plan/analyze/AnalyzeVisitor.java   | 189 +++++++++++--
 .../plan/planner/LogicalPlanBuilder.java           |  16 +-
 .../plan/planner/LogicalPlanVisitor.java           |   8 +-
 .../plan/planner/OperatorTreeGenerator.java        |   8 +-
 .../plan/planner/distribution/SourceRewriter.java  |  10 +-
 .../metadata/read/LevelTimeSeriesCountNode.java    |  48 +++-
 .../node/metadata/read/TimeSeriesCountNode.java    |  49 +++-
 .../plan/node/source/TimeseriesRegionScanNode.java |   7 +
 .../security/TreeAccessCheckVisitor.java           |  99 ++++++-
 .../plan/statement/metadata/CountStatement.java    |   9 +
 .../org/apache/iotdb/db/auth/TreeAccessTest.java   | 133 ++++++++++
 .../schema/source/TimeSeriesSchemaSourceTest.java  | 183 +++++++++++++
 .../distribution/RegionScanPlanningTest.java       |  81 ++++++
 .../logical/RegionScanLogicalPlannerTest.java      |  47 ++++
 .../metadata/read/SchemaCountNodeSerdeTest.java    |   8 +-
 24 files changed, 1312 insertions(+), 83 deletions(-)

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..1361f360202 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,52 @@ 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,
+          "show timeseries root.view_count.** where time>0",
+          new HashSet<>(
+              Arrays.asList(
+                  
"root.view_count.src.s1,null,root.view_count,INT32,PLAIN,LZ4,null,null,null,null,BASE,",
+                  
"root.view_count.dst.v1,null,root.view_count,INT32,null,null,null,null,null,null,VIEW,")));
+      checkResultSet(
+          statement,
+          "count timeseries root.view_count.dst.** where time>0",
+          new HashSet<>(Collections.singletonList("1,")));
+      checkResultSet(
+          statement,
+          "show timeseries root.view_count.dst.** where time>0",
+          new HashSet<>(
+              Collections.singletonList(
+                  
"root.view_count.dst.v1,null,root.view_count,INT32,null,null,null,null,null,null,VIEW,")));
+    } 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/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
index e5c99640564..ebef68b0486 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -1153,7 +1153,7 @@ public class DataNodeInternalRPCServiceImpl implements 
IDataNodeRPCService.Iface
                 for (final PartialPath pattern : 
filteredPatternTree.getAllPathPatterns()) {
                   ISchemaSource<ITimeSeriesSchemaInfo> schemaSource =
                       SchemaSourceFactory.getTimeSeriesSchemaCountSource(
-                          pattern, false, null, null, 
SchemaConstant.ALL_MATCH_SCOPE);
+                          pattern, false, null, null, 
SchemaConstant.ALL_MATCH_SCOPE, true, true);
                   try (final ISchemaReader<ITimeSeriesSchemaInfo> schemaReader 
=
                       schemaSource.getSchemaReader(schemaRegion)) {
                     if (schemaReader.hasNext()) {
@@ -1996,7 +1996,9 @@ public class DataNodeInternalRPCServiceImpl implements 
IDataNodeRPCService.Iface
                       // Does not support logical view currently
                       SchemaFilterFactory.createViewTypeFilter(ViewType.BASE),
                       null,
-                      SchemaConstant.ALL_MATCH_SCOPE);
+                      SchemaConstant.ALL_MATCH_SCOPE,
+                      true,
+                      true);
               try (final ISchemaReader<ITimeSeriesSchemaInfo> schemaReader =
                   schemaSource.getSchemaReader(schemaRegion)) {
                 final Map<String, Byte> updateMap = 
resp.getDeviewViewFieldTypeMap();
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..ecad26bac00 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,11 @@ 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.HashMap;
+import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 import static 
org.apache.iotdb.db.queryengine.execution.operator.schema.source.TimeSeriesSchemaSource.mapToString;
 
@@ -42,11 +46,70 @@ public class TimeseriesContext {
 
   private final String deadband;
   private final String deadbandParameters;
+  private final String database;
+  private final int activeCountMultiplier;
+  private final boolean logicalView;
+  private final Map<String, TimeseriesContext> activeLogicalViewContextMap;
 
   public TimeseriesContext(IMeasurementSchemaInfo schemaInfo) {
+    this(schemaInfo, 1, Collections.emptyMap());
+  }
+
+  public TimeseriesContext(
+      IMeasurementSchemaInfo schemaInfo,
+      int activeCountMultiplier,
+      Set<String> activeLogicalViewCountSet) {
+    this(schemaInfo, activeCountMultiplier, 
createLogicalViewContextMap(activeLogicalViewCountSet));
+  }
+
+  public TimeseriesContext(
+      IMeasurementSchemaInfo schemaInfo,
+      int activeCountMultiplier,
+      Map<String, TimeseriesContext> activeLogicalViewContextMap) {
     this.dataType = schemaInfo.getSchema().getType().toString();
-    this.encoding = schemaInfo.getSchema().getEncodingType().toString();
-    this.compression = schemaInfo.getSchema().getCompressor().toString();
+    this.logicalView = schemaInfo.isLogicalView();
+    if (logicalView) {
+      this.encoding = null;
+      this.compression = null;
+    } else {
+      this.encoding = schemaInfo.getSchema().getEncodingType().toString();
+      this.compression = schemaInfo.getSchema().getCompressor().toString();
+    }
+    this.alias = schemaInfo.getAlias();
+    this.tags = mapToString(schemaInfo.getTagMap());
+    this.attributes = mapToString(schemaInfo.getAttributeMap());
+    Pair<String, String> deadbandInfo =
+        MetaUtils.parseDeadbandInfo(schemaInfo.getSchema().getProps());
+    this.deadband = deadbandInfo.left;
+    this.deadbandParameters = deadbandInfo.right;
+    this.database = null;
+    this.activeCountMultiplier = activeCountMultiplier;
+    this.activeLogicalViewContextMap = new 
HashMap<>(activeLogicalViewContextMap);
+  }
+
+  public TimeseriesContext(
+      IMeasurementSchemaInfo schemaInfo,
+      String dataType,
+      int activeCountMultiplier,
+      Map<String, TimeseriesContext> activeLogicalViewContextMap) {
+    this(schemaInfo, dataType, null, activeCountMultiplier, 
activeLogicalViewContextMap);
+  }
+
+  public TimeseriesContext(
+      IMeasurementSchemaInfo schemaInfo,
+      String dataType,
+      String database,
+      int activeCountMultiplier,
+      Map<String, TimeseriesContext> activeLogicalViewContextMap) {
+    this.dataType = dataType;
+    this.logicalView = schemaInfo.isLogicalView();
+    if (logicalView) {
+      this.encoding = null;
+      this.compression = null;
+    } else {
+      this.encoding = schemaInfo.getSchema().getEncodingType().toString();
+      this.compression = schemaInfo.getSchema().getCompressor().toString();
+    }
     this.alias = schemaInfo.getAlias();
     this.tags = mapToString(schemaInfo.getTagMap());
     this.attributes = mapToString(schemaInfo.getAttributeMap());
@@ -54,6 +117,9 @@ public class TimeseriesContext {
         MetaUtils.parseDeadbandInfo(schemaInfo.getSchema().getProps());
     this.deadband = deadbandInfo.left;
     this.deadbandParameters = deadbandInfo.right;
+    this.database = database;
+    this.activeCountMultiplier = activeCountMultiplier;
+    this.activeLogicalViewContextMap = new 
HashMap<>(activeLogicalViewContextMap);
   }
 
   public String getDataType() {
@@ -88,6 +154,26 @@ public class TimeseriesContext {
     return deadband;
   }
 
+  public String getDatabase() {
+    return database;
+  }
+
+  public int getActiveCountMultiplier() {
+    return activeCountMultiplier;
+  }
+
+  public Set<String> getActiveLogicalViewCountSet() {
+    return activeLogicalViewContextMap.keySet();
+  }
+
+  public Map<String, TimeseriesContext> getActiveLogicalViewContextMap() {
+    return activeLogicalViewContextMap;
+  }
+
+  public boolean isLogicalView() {
+    return logicalView;
+  }
+
   public TimeseriesContext(
       String dataType,
       String alias,
@@ -97,6 +183,113 @@ public class TimeseriesContext {
       String attributes,
       String deadband,
       String deadbandParameters) {
+    this(
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        1,
+        false,
+        null,
+        Collections.emptyMap());
+  }
+
+  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,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier,
+        false,
+        null,
+        createLogicalViewContextMap(activeLogicalViewCountSet));
+  }
+
+  public TimeseriesContext(
+      String dataType,
+      String alias,
+      String encoding,
+      String compression,
+      String tags,
+      String attributes,
+      String deadband,
+      String deadbandParameters,
+      int activeCountMultiplier,
+      Map<String, TimeseriesContext> activeLogicalViewContextMap) {
+    this(
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier,
+        false,
+        null,
+        activeLogicalViewContextMap);
+  }
+
+  public TimeseriesContext(
+      String dataType,
+      String alias,
+      String encoding,
+      String compression,
+      String tags,
+      String attributes,
+      String deadband,
+      String deadbandParameters,
+      int activeCountMultiplier,
+      boolean logicalView,
+      Map<String, TimeseriesContext> activeLogicalViewContextMap) {
+    this(
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier,
+        logicalView,
+        null,
+        activeLogicalViewContextMap);
+  }
+
+  public TimeseriesContext(
+      String dataType,
+      String alias,
+      String encoding,
+      String compression,
+      String tags,
+      String attributes,
+      String deadband,
+      String deadbandParameters,
+      int activeCountMultiplier,
+      boolean logicalView,
+      String database,
+      Map<String, TimeseriesContext> activeLogicalViewContextMap) {
     this.dataType = dataType;
     this.alias = alias;
     this.encoding = encoding;
@@ -105,6 +298,44 @@ public class TimeseriesContext {
     this.attributes = attributes;
     this.deadband = deadband;
     this.deadbandParameters = deadbandParameters;
+    this.database = database;
+    this.activeCountMultiplier = activeCountMultiplier;
+    this.logicalView = logicalView;
+    this.activeLogicalViewContextMap = new 
HashMap<>(activeLogicalViewContextMap);
+  }
+
+  private static Map<String, TimeseriesContext> createLogicalViewContextMap(
+      Set<String> activeLogicalViewCountSet) {
+    if (activeLogicalViewCountSet.isEmpty()) {
+      return Collections.emptyMap();
+    }
+    Map<String, TimeseriesContext> activeLogicalViewContextMap = new 
HashMap<>();
+    for (String logicalView : activeLogicalViewCountSet) {
+      activeLogicalViewContextMap.put(
+          logicalView,
+          new TimeseriesContext(
+              null, null, null, null, null, null, null, null, 1, true, 
Collections.emptyMap()));
+    }
+    return activeLogicalViewContextMap;
+  }
+
+  public TimeseriesContext mergeActiveCount(TimeseriesContext that) {
+    Map<String, TimeseriesContext> mergedActiveLogicalViewContextMap =
+        new HashMap<>(activeLogicalViewContextMap);
+    mergedActiveLogicalViewContextMap.putAll(that.activeLogicalViewContextMap);
+    return new TimeseriesContext(
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier + that.activeCountMultiplier,
+        logicalView,
+        database,
+        mergedActiveLogicalViewContextMap);
   }
 
   public void serializeAttributes(ByteBuffer byteBuffer) {
@@ -116,6 +347,14 @@ public class TimeseriesContext {
     ReadWriteIOUtils.write(attributes, byteBuffer);
     ReadWriteIOUtils.write(deadband, byteBuffer);
     ReadWriteIOUtils.write(deadbandParameters, byteBuffer);
+    ReadWriteIOUtils.write(database, byteBuffer);
+    ReadWriteIOUtils.write(activeCountMultiplier, byteBuffer);
+    ReadWriteIOUtils.write(logicalView, byteBuffer);
+    ReadWriteIOUtils.write(activeLogicalViewContextMap.size(), byteBuffer);
+    for (Map.Entry<String, TimeseriesContext> entry : 
activeLogicalViewContextMap.entrySet()) {
+      ReadWriteIOUtils.write(entry.getKey(), byteBuffer);
+      entry.getValue().serializeAttributes(byteBuffer);
+    }
   }
 
   public void serializeAttributes(DataOutputStream stream) throws IOException {
@@ -127,6 +366,14 @@ public class TimeseriesContext {
     ReadWriteIOUtils.write(attributes, stream);
     ReadWriteIOUtils.write(deadband, stream);
     ReadWriteIOUtils.write(deadbandParameters, stream);
+    ReadWriteIOUtils.write(database, stream);
+    ReadWriteIOUtils.write(activeCountMultiplier, stream);
+    ReadWriteIOUtils.write(logicalView, stream);
+    ReadWriteIOUtils.write(activeLogicalViewContextMap.size(), stream);
+    for (Map.Entry<String, TimeseriesContext> entry : 
activeLogicalViewContextMap.entrySet()) {
+      ReadWriteIOUtils.write(entry.getKey(), stream);
+      entry.getValue().serializeAttributes(stream);
+    }
   }
 
   public static TimeseriesContext deserialize(ByteBuffer buffer) {
@@ -138,8 +385,28 @@ public class TimeseriesContext {
     String attributes = ReadWriteIOUtils.readString(buffer);
     String deadband = ReadWriteIOUtils.readString(buffer);
     String deadbandParameters = ReadWriteIOUtils.readString(buffer);
+    String database = ReadWriteIOUtils.readString(buffer);
+    int activeCountMultiplier = ReadWriteIOUtils.readInt(buffer);
+    boolean logicalView = ReadWriteIOUtils.readBool(buffer);
+    int activeLogicalViewContextMapSize = ReadWriteIOUtils.readInt(buffer);
+    Map<String, TimeseriesContext> activeLogicalViewContextMap = new 
HashMap<>();
+    for (int i = 0; i < activeLogicalViewContextMapSize; i++) {
+      activeLogicalViewContextMap.put(
+          ReadWriteIOUtils.readString(buffer), 
TimeseriesContext.deserialize(buffer));
+    }
     return new TimeseriesContext(
-        dataType, alias, encoding, compression, tags, attributes, deadband, 
deadbandParameters);
+        dataType,
+        alias,
+        encoding,
+        compression,
+        tags,
+        attributes,
+        deadband,
+        deadbandParameters,
+        activeCountMultiplier,
+        logicalView,
+        database,
+        activeLogicalViewContextMap);
   }
 
   @Override
@@ -154,18 +421,33 @@ public class TimeseriesContext {
     boolean res =
         Objects.equals(dataType, that.dataType)
             && Objects.equals(alias, that.alias)
-            && encoding.equals(that.encoding)
+            && Objects.equals(encoding, that.encoding)
             && Objects.equals(compression, that.compression)
             && 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)
+            && Objects.equals(database, that.database)
+            && activeCountMultiplier == that.activeCountMultiplier
+            && logicalView == that.logicalView
+            && Objects.equals(activeLogicalViewContextMap, 
that.activeLogicalViewContextMap);
     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,
+        database,
+        activeCountMultiplier,
+        logicalView,
+        activeLogicalViewContextMap);
   }
 }
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..85bc9bcb77c 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
@@ -46,9 +46,21 @@ public class SchemaSourceFactory {
       boolean isPrefixMatch,
       SchemaFilter schemaFilter,
       Map<Integer, Template> templateMap,
-      PathPatternTree scope) {
+      PathPatternTree scope,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase) {
     return new TimeSeriesSchemaSource(
-        pathPattern, isPrefixMatch, 0, 0, schemaFilter, templateMap, false, 
scope, null);
+        pathPattern,
+        isPrefixMatch,
+        0,
+        0,
+        schemaFilter,
+        templateMap,
+        false,
+        includeSystemDatabase,
+        includeAuditDatabase,
+        scope,
+        null);
   }
 
   // show time series
@@ -69,6 +81,8 @@ public class SchemaSourceFactory {
         schemaFilter,
         templateMap,
         true,
+        true,
+        true,
         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..0b89998052b 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,8 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
   private final SchemaFilter schemaFilter;
   private final Map<Integer, Template> templateMap;
   private final boolean needViewDetail;
+  private final boolean includeSystemDatabase;
+  private final boolean includeAuditDatabase;
   private final Ordering timeseriesOrdering;
 
   TimeSeriesSchemaSource(
@@ -65,6 +68,8 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
       SchemaFilter schemaFilter,
       Map<Integer, Template> templateMap,
       boolean needViewDetail,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase,
       PathPatternTree scope,
       Ordering timeseriesOrdering) {
     this.pathPattern = pathPattern;
@@ -74,6 +79,8 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
     this.schemaFilter = schemaFilter;
     this.templateMap = templateMap;
     this.needViewDetail = needViewDetail;
+    this.includeSystemDatabase = includeSystemDatabase;
+    this.includeAuditDatabase = includeAuditDatabase;
     this.scope = scope;
     this.timeseriesOrdering = timeseriesOrdering;
   }
@@ -141,6 +148,19 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
     return schemaRegion.getSchemaRegionStatistics().getSeriesNumber(true);
   }
 
+  @Override
+  public boolean shouldSkipSchemaRegion(final ISchemaRegion schemaRegion) {
+    final String database = schemaRegion.getDatabaseFullPath();
+    if (SchemaConstant.SYSTEM_DATABASE.equals(database)) {
+      return !includeSystemDatabase;
+    }
+    if (SchemaConstant.AUDIT_DATABASE.equals(database)
+        || Audit.TABLE_MODEL_AUDIT_DATABASE.equals(database)) {
+      return !includeAuditDatabase;
+    }
+    return false;
+  }
+
   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..e61de2818b6 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,15 +35,22 @@ 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 static final Binary VIEW_TYPE = new Binary("BASE".getBytes());
+  private final Set<String> countedLogicalViews;
+  private static final Binary BASE_VIEW_TYPE =
+      new Binary("BASE".getBytes(TSFileConfig.STRING_CHARSET));
+  private static final Binary LOGICAL_VIEW_TYPE =
+      new Binary("VIEW".getBytes(TSFileConfig.STRING_CHARSET));
   private final Binary dataBaseName;
+  private final String dataBaseNameString;
   private static final long INSTANCE_SIZE =
       
RamUsageEstimator.shallowSizeOfInstance(ActiveTimeSeriesRegionScanOperator.class)
           + RamUsageEstimator.shallowSizeOfInstance(Map.class)
@@ -60,15 +67,15 @@ 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(
-            operatorContext
-                .getDriverContext()
-                .getFragmentInstanceContext()
-                .getDataRegion()
-                .getDatabaseName()
-                .getBytes(TSFileConfig.STRING_CHARSET));
+    this.dataBaseNameString =
+        operatorContext
+            .getDriverContext()
+            .getFragmentInstanceContext()
+            .getDataRegion()
+            .getDatabaseName();
+    this.dataBaseName = new 
Binary(this.dataBaseNameString.getBytes(TSFileConfig.STRING_CHARSET));
   }
 
   @Override
@@ -92,16 +99,22 @@ public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSo
 
   @Override
   protected void updateActiveData() {
-    TimeColumnBuilder timeColumnBuilder = 
resultTsBlockBuilder.getTimeColumnBuilder();
-    ColumnBuilder[] columnBuilders = 
resultTsBlockBuilder.getValueColumnBuilders();
-
     Map<IDeviceID, List<String>> activeTimeSeries =
         ((RegionScanForActiveTimeSeriesUtil) 
regionScanUtil).getActiveTimeSeries();
 
     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;
@@ -114,26 +127,49 @@ public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSo
       Map<String, TimeseriesContext> timeSeriesInfo = 
timeSeriesToSchemasInfo.get(deviceID);
       for (String timeSeries : timeSeriesList) {
         TimeseriesContext schemaInfo = timeSeriesInfo.get(timeSeries);
-        timeColumnBuilder.writeLong(-1);
-        columnBuilders[0].writeBinary(
-            new Binary(contactDeviceAndMeasurement(deviceStr, timeSeries)));
-
-        checkAndAppend(schemaInfo.getAlias(), columnBuilders[1]); // 
Measurement
-        columnBuilders[2].writeBinary(dataBaseName); // Database
-        checkAndAppend(schemaInfo.getDataType(), columnBuilders[3]); // 
DataType
-        checkAndAppend(schemaInfo.getEncoding(), columnBuilders[4]); // 
Encoding
-        checkAndAppend(schemaInfo.getCompression(), columnBuilders[5]); // 
Compression
-        checkAndAppend(schemaInfo.getTags(), columnBuilders[6]); // Tags
-        checkAndAppend(schemaInfo.getAttributes(), columnBuilders[7]); // 
Attributes
-        checkAndAppend(schemaInfo.getDeadband(), columnBuilders[8]); // 
Description
-        checkAndAppend(schemaInfo.getDeadbandParameters(), columnBuilders[9]); 
// DeadbandParameters
-        columnBuilders[10].writeBinary(VIEW_TYPE); // ViewType
-        resultTsBlockBuilder.declarePosition();
+        if (schemaInfo.getActiveCountMultiplier() > 0) {
+          appendTimeseries(
+              contactDeviceAndMeasurement(deviceStr, timeSeries), schemaInfo, 
BASE_VIEW_TYPE);
+        }
+        for (Map.Entry<String, TimeseriesContext> logicalViewEntry :
+            schemaInfo.getActiveLogicalViewContextMap().entrySet()) {
+          if (countedLogicalViews.add(logicalViewEntry.getKey())) {
+            appendTimeseries(
+                
logicalViewEntry.getKey().getBytes(TSFileConfig.STRING_CHARSET),
+                logicalViewEntry.getValue(),
+                LOGICAL_VIEW_TYPE);
+          }
+        }
       }
       removeTimeseriesListFromDevice(deviceID, timeSeriesList);
     }
   }
 
+  private void appendTimeseries(
+      byte[] timeseriesPath, TimeseriesContext schemaInfo, Binary viewType) {
+    TimeColumnBuilder timeColumnBuilder = 
resultTsBlockBuilder.getTimeColumnBuilder();
+    ColumnBuilder[] columnBuilders = 
resultTsBlockBuilder.getValueColumnBuilders();
+
+    timeColumnBuilder.writeLong(-1);
+    columnBuilders[0].writeBinary(new Binary(timeseriesPath));
+
+    checkAndAppend(schemaInfo.getAlias(), columnBuilders[1]); // Measurement
+    if (schemaInfo.getDatabase() == null || 
dataBaseNameString.equals(schemaInfo.getDatabase())) {
+      columnBuilders[2].writeBinary(dataBaseName); // Database
+    } else {
+      checkAndAppend(schemaInfo.getDatabase(), columnBuilders[2]); // Database
+    }
+    checkAndAppend(schemaInfo.getDataType(), columnBuilders[3]); // DataType
+    checkAndAppend(schemaInfo.getEncoding(), columnBuilders[4]); // Encoding
+    checkAndAppend(schemaInfo.getCompression(), columnBuilders[5]); // 
Compression
+    checkAndAppend(schemaInfo.getTags(), columnBuilders[6]); // Tags
+    checkAndAppend(schemaInfo.getAttributes(), columnBuilders[7]); // 
Attributes
+    checkAndAppend(schemaInfo.getDeadband(), columnBuilders[8]); // Description
+    checkAndAppend(schemaInfo.getDeadbandParameters(), columnBuilders[9]); // 
DeadbandParameters
+    columnBuilders[10].writeBinary(viewType); // ViewType
+    resultTsBlockBuilder.declarePosition();
+  }
+
   private void removeTimeseriesListFromDevice(IDeviceID deviceID, List<String> 
timeSeriesList) {
     Map<String, TimeseriesContext> timeSeriesInfo = 
timeSeriesToSchemasInfo.get(deviceID);
     for (String timeSeries : timeSeriesList) {
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..22d5b0518ac 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
@@ -35,8 +35,11 @@ import org.apache.iotdb.commons.path.AlignedPath;
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.path.PathPatternTree;
+import org.apache.iotdb.commons.queryengine.common.NodeRef;
+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.table.Audit;
 import org.apache.iotdb.commons.schema.template.Template;
 import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
 import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression;
@@ -71,6 +74,7 @@ import 
org.apache.iotdb.db.queryengine.plan.expression.binary.CompareBinaryExpre
 import org.apache.iotdb.db.queryengine.plan.expression.leaf.ConstantOperand;
 import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
 import 
org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
+import 
org.apache.iotdb.db.queryengine.plan.expression.visitor.CompleteMeasurementSchemaVisitor;
 import 
org.apache.iotdb.db.queryengine.plan.expression.visitor.ExistUnknownTypeInExpression;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.write.MeasurementGroup;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.DeviceViewIntoPathDescriptor;
@@ -142,6 +146,7 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.sys.ExplainStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.sys.ShowDiskUsageStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowQueriesStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.sys.ShowVersionStatement;
+import 
org.apache.iotdb.db.schemaengine.schemaregion.view.visitor.TransformToExpressionVisitor;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
@@ -2931,7 +2936,9 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       Analysis analysis,
       MPPQueryContext context,
       PathPatternTree authorityScope,
-      boolean canSeeAuditDB)
+      boolean canSeeAuditDB,
+      boolean canSeeSystemDB,
+      boolean includeLogicalView)
       throws IllegalPathException {
     analyzeGlobalTimeConditionInShowMetaData(timeCondition, analysis);
     context.generateGlobalTimeFilter(analysis);
@@ -2944,7 +2951,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 +2967,60 @@ 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 (shouldSkipInternalDatabaseForActiveCount(
+          devicePath, schemaTree, canSeeAuditDB, canSeeSystemDB)) {
+        continue;
+      }
       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 +3032,116 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     return true;
   }
 
+  private boolean shouldSkipInternalDatabaseForActiveCount(
+      PartialPath devicePath,
+      ISchemaTree schemaTree,
+      boolean canSeeAuditDB,
+      boolean canSeeSystemDB) {
+    String database = schemaTree.getBelongedDatabase(devicePath);
+    if (SchemaConstant.SYSTEM_DATABASE.equals(database)) {
+      return !canSeeSystemDB;
+    }
+    if (SchemaConstant.AUDIT_DATABASE.equals(database)
+        || Audit.TABLE_MODEL_AUDIT_DATABASE.equals(database)) {
+      return !canSeeAuditDB;
+    }
+    return false;
+  }
+
+  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();
+    String viewDataType = getLogicalViewDataType(logicalViewSchema, 
schemaTree);
+    String viewDatabase = schemaTree.getBelongedDatabase(viewDevicePath);
+    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;
+      }
+
+      Map<String, TimeseriesContext> activeLogicalViewContextMap =
+          Collections.singletonMap(
+              viewPath,
+              new TimeseriesContext(
+                  viewSchemaInfo, viewDataType, viewDatabase, 1, 
Collections.emptyMap()));
+      addPhysicalTimeseriesForActiveCount(
+          sourceDevicePath,
+          sourceSchemaInfo,
+          sourceDeviceSchemaInfo.isAligned(),
+          new TimeseriesContext(sourceSchemaInfo, 0, 
activeLogicalViewContextMap),
+          deviceToTimeseriesContext,
+          deviceSet);
+    }
+  }
+
+  private String getLogicalViewDataType(
+      LogicalViewSchema logicalViewSchema, ISchemaTree schemaTree) {
+    if (logicalViewSchema.getType() != TSDataType.UNKNOWN) {
+      return logicalViewSchema.getType().toString();
+    }
+    try {
+      Expression expression =
+          new 
TransformToExpressionVisitor().process(logicalViewSchema.getExpression(), null);
+      expression = new CompleteMeasurementSchemaVisitor().process(expression, 
schemaTree);
+      Map<NodeRef<Expression>, TSDataType> expressionTypes = new HashMap<>();
+      analyzeExpression(expressionTypes, expression);
+      TSDataType dataType = expressionTypes.get(NodeRef.of(expression));
+      return dataType == null ? TSDataType.UNKNOWN.toString() : 
dataType.toString();
+    } catch (Exception e) {
+      return TSDataType.UNKNOWN.toString();
+    }
+  }
+
+  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 +3167,9 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
                 analysis,
                 context,
                 showTimeSeriesStatement.getAuthorityScope(),
-                showTimeSeriesStatement.isCanSeeAuditDB());
+                showTimeSeriesStatement.isCanSeeAuditDB(),
+                true,
+                true);
         if (!hasSchema) {
           
analysis.setRespDatasetHeader(DatasetHeaderFactory.getShowTimeSeriesHeader());
           return analysis;
@@ -3271,7 +3420,9 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
                 analysis,
                 context,
                 countTimeSeriesStatement.getAuthorityScope(),
-                countTimeSeriesStatement.isCanSeeAuditDB());
+                countTimeSeriesStatement.isCanSeeAuditDB(),
+                countTimeSeriesStatement.isCanSeeSystemDB(),
+                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/LogicalPlanBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java
index fff2aa07b49..26d361c1f21 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java
@@ -1176,7 +1176,9 @@ public class LogicalPlanBuilder {
       boolean prefixPath,
       SchemaFilter schemaFilter,
       Map<Integer, Template> templateMap,
-      PathPatternTree scope) {
+      PathPatternTree scope,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase) {
     this.root =
         new TimeSeriesCountNode(
             context.getQueryId().genPlanNodeId(),
@@ -1184,7 +1186,9 @@ public class LogicalPlanBuilder {
             prefixPath,
             schemaFilter,
             templateMap,
-            scope);
+            scope,
+            includeSystemDatabase,
+            includeAuditDatabase);
     return this;
   }
 
@@ -1194,7 +1198,9 @@ public class LogicalPlanBuilder {
       int level,
       SchemaFilter schemaFilter,
       Map<Integer, Template> templateMap,
-      PathPatternTree scope) {
+      PathPatternTree scope,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase) {
     this.root =
         new LevelTimeSeriesCountNode(
             context.getQueryId().genPlanNodeId(),
@@ -1203,7 +1209,9 @@ public class LogicalPlanBuilder {
             level,
             schemaFilter,
             templateMap,
-            scope);
+            scope,
+            includeSystemDatabase,
+            includeAuditDatabase);
     return this;
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
index a9b0b9d83f4..2c9304ce0b9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanVisitor.java
@@ -733,7 +733,9 @@ public class LogicalPlanVisitor extends 
StatementVisitor<PlanNode, MPPQueryConte
             countTimeSeriesStatement.isPrefixPath(),
             countTimeSeriesStatement.getSchemaFilter(),
             analysis.getRelatedTemplateInfo(),
-            countTimeSeriesStatement.getAuthorityScope())
+            countTimeSeriesStatement.getAuthorityScope(),
+            countTimeSeriesStatement.isCanSeeSystemDB(),
+            countTimeSeriesStatement.isCanSeeAuditDB())
         .planCountMerge()
         .getRoot();
   }
@@ -749,7 +751,9 @@ public class LogicalPlanVisitor extends 
StatementVisitor<PlanNode, MPPQueryConte
             countLevelTimeSeriesStatement.getLevel(),
             countLevelTimeSeriesStatement.getSchemaFilter(),
             analysis.getRelatedTemplateInfo(),
-            countLevelTimeSeriesStatement.getAuthorityScope())
+            countLevelTimeSeriesStatement.getAuthorityScope(),
+            countLevelTimeSeriesStatement.isCanSeeSystemDB(),
+            countLevelTimeSeriesStatement.isCanSeeAuditDB())
         .planCountMerge()
         .getRoot();
   }
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..63cb0d861ad 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
@@ -984,7 +984,9 @@ public class OperatorTreeGenerator implements 
PlanVisitor<Operator, LocalExecuti
             node.isPrefixPath(),
             node.getSchemaFilter(),
             node.getTemplateMap(),
-            node.getScope()));
+            node.getScope(),
+            node.isIncludeSystemDatabase(),
+            node.isIncludeAuditDatabase()));
   }
 
   @Override
@@ -1006,7 +1008,9 @@ public class OperatorTreeGenerator implements 
PlanVisitor<Operator, LocalExecuti
             node.isPrefixPath(),
             node.getSchemaFilter(),
             node.getTemplateMap(),
-            node.getScope()));
+            node.getScope(),
+            node.isIncludeSystemDatabase(),
+            node.isIncludeAuditDatabase()));
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/SourceRewriter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/SourceRewriter.java
index 6582f0a4a68..d326a6de30a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/SourceRewriter.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/SourceRewriter.java
@@ -858,7 +858,10 @@ public class SourceRewriter extends 
BaseSourceRewriter<DistributionPlanContext>
       return planNodeList;
     }
 
-    boolean outputCountInScanNode = node.isOutputCount() && 
!context.isOneSeriesInMultiRegion();
+    boolean outputCountInScanNode =
+        node.isOutputCount()
+            && !context.isOneSeriesInMultiRegion()
+            && !hasActiveLogicalViewContext(node);
     ActiveRegionScanMergeNode regionMergeNode =
         new ActiveRegionScanMergeNode(
             context.queryContext.getQueryId().genPlanNodeId(),
@@ -872,6 +875,11 @@ public class SourceRewriter extends 
BaseSourceRewriter<DistributionPlanContext>
     return Collections.singletonList(regionMergeNode);
   }
 
+  private boolean hasActiveLogicalViewContext(RegionScanNode node) {
+    return node instanceof TimeseriesRegionScanNode
+        && ((TimeseriesRegionScanNode) node).hasActiveLogicalViewContext();
+  }
+
   @Override
   public List<PlanNode> visitDeviceRegionScan(
       DeviceRegionScanNode node, DistributionPlanContext context) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/LevelTimeSeriesCountNode.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/LevelTimeSeriesCountNode.java
index 336ae40f85d..902a2dd69db 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/LevelTimeSeriesCountNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/LevelTimeSeriesCountNode.java
@@ -48,6 +48,8 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
   private final int level;
   private final SchemaFilter schemaFilter;
   private final Map<Integer, Template> templateMap;
+  private final boolean includeSystemDatabase;
+  private final boolean includeAuditDatabase;
 
   public LevelTimeSeriesCountNode(
       PlanNodeId id,
@@ -56,11 +58,15 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
       int level,
       SchemaFilter schemaFilter,
       @NotNull Map<Integer, Template> templateMap,
-      @NotNull PathPatternTree scope) {
+      @NotNull PathPatternTree scope,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase) {
     super(id, partialPath, isPrefixPath, scope);
     this.level = level;
     this.schemaFilter = schemaFilter;
     this.templateMap = templateMap;
+    this.includeSystemDatabase = includeSystemDatabase;
+    this.includeAuditDatabase = includeAuditDatabase;
   }
 
   public SchemaFilter getSchemaFilter() {
@@ -75,6 +81,14 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
     return templateMap;
   }
 
+  public boolean isIncludeSystemDatabase() {
+    return includeSystemDatabase;
+  }
+
+  public boolean isIncludeAuditDatabase() {
+    return includeAuditDatabase;
+  }
+
   @Override
   public PlanNodeType getType() {
     return PlanNodeType.LEVEL_TIME_SERIES_COUNT;
@@ -83,7 +97,15 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
   @Override
   public PlanNode clone() {
     return new LevelTimeSeriesCountNode(
-        getPlanNodeId(), path, isPrefixPath, level, schemaFilter, templateMap, 
scope);
+        getPlanNodeId(),
+        path,
+        isPrefixPath,
+        level,
+        schemaFilter,
+        templateMap,
+        scope,
+        includeSystemDatabase,
+        includeAuditDatabase);
   }
 
   @Override
@@ -101,6 +123,8 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
     ReadWriteIOUtils.write(isPrefixPath, byteBuffer);
     ReadWriteIOUtils.write(level, byteBuffer);
     SchemaFilter.serialize(schemaFilter, byteBuffer);
+    ReadWriteIOUtils.write(includeSystemDatabase, byteBuffer);
+    ReadWriteIOUtils.write(includeAuditDatabase, byteBuffer);
     ReadWriteIOUtils.write(templateMap.size(), byteBuffer);
     for (Template template : templateMap.values()) {
       template.serialize(byteBuffer);
@@ -115,6 +139,8 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
     ReadWriteIOUtils.write(isPrefixPath, stream);
     ReadWriteIOUtils.write(level, stream);
     SchemaFilter.serialize(schemaFilter, stream);
+    ReadWriteIOUtils.write(includeSystemDatabase, stream);
+    ReadWriteIOUtils.write(includeAuditDatabase, stream);
     ReadWriteIOUtils.write(templateMap.size(), stream);
     for (Template template : templateMap.values()) {
       template.serialize(stream);
@@ -134,6 +160,8 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
     boolean isPrefixPath = ReadWriteIOUtils.readBool(buffer);
     int level = ReadWriteIOUtils.readInt(buffer);
     SchemaFilter schemaFilter = SchemaFilter.deserialize(buffer);
+    boolean includeSystemDatabase = ReadWriteIOUtils.readBool(buffer);
+    boolean includeAuditDatabase = ReadWriteIOUtils.readBool(buffer);
     int templateNum = ReadWriteIOUtils.readInt(buffer);
     Map<Integer, Template> templateMap = new HashMap<>();
     Template template;
@@ -144,7 +172,15 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
     }
     PlanNodeId planNodeId = PlanNodeId.deserialize(buffer);
     return new LevelTimeSeriesCountNode(
-        planNodeId, path, isPrefixPath, level, schemaFilter, templateMap, 
scope);
+        planNodeId,
+        path,
+        isPrefixPath,
+        level,
+        schemaFilter,
+        templateMap,
+        scope,
+        includeSystemDatabase,
+        includeAuditDatabase);
   }
 
   @Override
@@ -159,12 +195,14 @@ public class LevelTimeSeriesCountNode extends 
SchemaQueryScanNode {
       return false;
     }
     LevelTimeSeriesCountNode that = (LevelTimeSeriesCountNode) o;
-    return level == that.level;
+    return level == that.level
+        && includeSystemDatabase == that.includeSystemDatabase
+        && includeAuditDatabase == that.includeAuditDatabase;
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(super.hashCode(), level);
+    return Objects.hash(super.hashCode(), level, includeSystemDatabase, 
includeAuditDatabase);
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TimeSeriesCountNode.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TimeSeriesCountNode.java
index 6326a38a703..8bcc9e70f5d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TimeSeriesCountNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/metadata/read/TimeSeriesCountNode.java
@@ -51,16 +51,24 @@ public class TimeSeriesCountNode extends 
SchemaQueryScanNode {
 
   private final Map<Integer, Template> templateMap;
 
+  private final boolean includeSystemDatabase;
+
+  private final boolean includeAuditDatabase;
+
   public TimeSeriesCountNode(
       PlanNodeId id,
       PartialPath partialPath,
       boolean isPrefixPath,
       SchemaFilter schemaFilter,
       @NotNull Map<Integer, Template> templateMap,
-      @NotNull PathPatternTree scope) {
+      @NotNull PathPatternTree scope,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase) {
     super(id, partialPath, isPrefixPath, scope);
     this.schemaFilter = schemaFilter;
     this.templateMap = templateMap;
+    this.includeSystemDatabase = includeSystemDatabase;
+    this.includeAuditDatabase = includeAuditDatabase;
   }
 
   public SchemaFilter getSchemaFilter() {
@@ -71,6 +79,14 @@ public class TimeSeriesCountNode extends SchemaQueryScanNode 
{
     return templateMap;
   }
 
+  public boolean isIncludeSystemDatabase() {
+    return includeSystemDatabase;
+  }
+
+  public boolean isIncludeAuditDatabase() {
+    return includeAuditDatabase;
+  }
+
   @Override
   public PlanNodeType getType() {
     return PlanNodeType.TIME_SERIES_COUNT;
@@ -79,7 +95,14 @@ public class TimeSeriesCountNode extends SchemaQueryScanNode 
{
   @Override
   public PlanNode clone() {
     return new TimeSeriesCountNode(
-        getPlanNodeId(), path, isPrefixPath, schemaFilter, templateMap, scope);
+        getPlanNodeId(),
+        path,
+        isPrefixPath,
+        schemaFilter,
+        templateMap,
+        scope,
+        includeSystemDatabase,
+        includeAuditDatabase);
   }
 
   @Override
@@ -96,6 +119,8 @@ public class TimeSeriesCountNode extends SchemaQueryScanNode 
{
     scope.serialize(byteBuffer);
     ReadWriteIOUtils.write(isPrefixPath, byteBuffer);
     SchemaFilter.serialize(schemaFilter, byteBuffer);
+    ReadWriteIOUtils.write(includeSystemDatabase, byteBuffer);
+    ReadWriteIOUtils.write(includeAuditDatabase, byteBuffer);
     ReadWriteIOUtils.write(templateMap.size(), byteBuffer);
     for (Template template : templateMap.values()) {
       template.serialize(byteBuffer);
@@ -109,6 +134,8 @@ public class TimeSeriesCountNode extends 
SchemaQueryScanNode {
     scope.serialize(stream);
     ReadWriteIOUtils.write(isPrefixPath, stream);
     SchemaFilter.serialize(schemaFilter, stream);
+    ReadWriteIOUtils.write(includeSystemDatabase, stream);
+    ReadWriteIOUtils.write(includeAuditDatabase, stream);
     ReadWriteIOUtils.write(templateMap.size(), stream);
     for (Template template : templateMap.values()) {
       template.serialize(stream);
@@ -127,6 +154,8 @@ public class TimeSeriesCountNode extends 
SchemaQueryScanNode {
     PathPatternTree scope = PathPatternTree.deserialize(buffer);
     boolean isPrefixPath = ReadWriteIOUtils.readBool(buffer);
     SchemaFilter schemaFilter = SchemaFilter.deserialize(buffer);
+    boolean includeSystemDatabase = ReadWriteIOUtils.readBool(buffer);
+    boolean includeAuditDatabase = ReadWriteIOUtils.readBool(buffer);
 
     int templateNum = ReadWriteIOUtils.readInt(buffer);
     Map<Integer, Template> templateMap = new HashMap<>();
@@ -139,7 +168,14 @@ public class TimeSeriesCountNode extends 
SchemaQueryScanNode {
 
     PlanNodeId planNodeId = PlanNodeId.deserialize(buffer);
     return new TimeSeriesCountNode(
-        planNodeId, path, isPrefixPath, schemaFilter, templateMap, scope);
+        planNodeId,
+        path,
+        isPrefixPath,
+        schemaFilter,
+        templateMap,
+        scope,
+        includeSystemDatabase,
+        includeAuditDatabase);
   }
 
   @Override
@@ -156,11 +192,14 @@ public class TimeSeriesCountNode extends 
SchemaQueryScanNode {
     if (!super.equals(o)) return false;
     TimeSeriesCountNode that = (TimeSeriesCountNode) o;
     return Objects.equals(schemaFilter, that.schemaFilter)
-        && Objects.equals(templateMap, that.templateMap);
+        && Objects.equals(templateMap, that.templateMap)
+        && includeSystemDatabase == that.includeSystemDatabase
+        && includeAuditDatabase == that.includeAuditDatabase;
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(super.hashCode(), schemaFilter, templateMap);
+    return Objects.hash(
+        super.hashCode(), schemaFilter, templateMap, includeSystemDatabase, 
includeAuditDatabase);
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/TimeseriesRegionScanNode.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/TimeseriesRegionScanNode.java
index b960aa5b507..24bcf288403 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/TimeseriesRegionScanNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/source/TimeseriesRegionScanNode.java
@@ -86,6 +86,13 @@ public class TimeseriesRegionScanNode extends RegionScanNode 
{
     return deviceToTimeseriesSchemaInfo;
   }
 
+  public boolean hasActiveLogicalViewContext() {
+    return deviceToTimeseriesSchemaInfo.values().stream()
+        .flatMap(timeseriesContextMap -> 
timeseriesContextMap.values().stream())
+        .flatMap(List::stream)
+        .anyMatch(context -> 
!context.getActiveLogicalViewContextMap().isEmpty());
+  }
+
   @Override
   public List<PlanNode> getChildren() {
     return ImmutableList.of();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
index 68658529e71..fd9757c5f89 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
@@ -30,6 +30,7 @@ import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.path.PathPatternTreeUtils;
+import org.apache.iotdb.commons.schema.SchemaConstant;
 import org.apache.iotdb.commons.schema.table.Audit;
 import org.apache.iotdb.commons.utils.StatusUtils;
 import org.apache.iotdb.db.audit.DNAuditLogger;
@@ -54,6 +55,7 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountDatabaseStat
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountDevicesStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountLevelTimeSeriesStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountNodesStatement;
+import org.apache.iotdb.db.queryengine.plan.statement.metadata.CountStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountTimeSeriesStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountTimeSlotListStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
@@ -1393,13 +1395,19 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
         .setAuditLogOperation(AuditLogOperation.QUERY)
         .setPrivilegeType(PrivilegeType.READ_SCHEMA);
     if (AuthorityChecker.SUPER_USER.equals(context.getUsername())) {
+      statement.setCanSeeSystemDB(true);
       statement.setCanSeeAuditDB(true);
       AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
           context.setResult(true),
           () -> 
statement.getPaths().stream().distinct().collect(Collectors.toList()).toString());
       return SUCCEED;
     }
+    TSStatus internalDatabaseStatus = 
checkExplicitInternalDatabaseCount(statement, context);
+    if (internalDatabaseStatus != null) {
+      return internalDatabaseStatus;
+    }
     setCanSeeAuditDB(statement, context);
+    setCanSeeSystemDB(statement, context);
     if (statement.hasTimeCondition()) {
       try {
         statement.setAuthorityScope(
@@ -1408,6 +1416,7 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
                     context.getUsername(), PrivilegeType.READ_SCHEMA),
                 AuthorityChecker.getAuthorizedPathTree(
                     context.getUsername(), PrivilegeType.READ_DATA)));
+        appendInternalDatabaseAuthorityScope(statement);
       } catch (AuthException e) {
         AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
             context.setResult(false),
@@ -1419,14 +1428,22 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
           () -> 
statement.getPaths().stream().distinct().collect(Collectors.toList()).toString());
       return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
     } else {
-      return visitAuthorityInformation(statement, context);
+      TSStatus status = visitAuthorityInformation(statement, context);
+      if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        appendInternalDatabaseAuthorityScope(statement);
+      }
+      return status;
     }
   }
 
   @Override
   public TSStatus visitCountLevelTimeSeries(
       CountLevelTimeSeriesStatement countStatement, TreeAccessCheckContext 
context) {
+    context
+        .setAuditLogOperation(AuditLogOperation.QUERY)
+        .setPrivilegeType(PrivilegeType.READ_SCHEMA);
     if (AuthorityChecker.SUPER_USER.equals(context.getUsername())) {
+      countStatement.setCanSeeSystemDB(true);
       countStatement.setCanSeeAuditDB(true);
       AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
           context.setResult(true),
@@ -1437,8 +1454,86 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
                   .toString());
       return SUCCEED;
     }
+    TSStatus internalDatabaseStatus = 
checkExplicitInternalDatabaseCount(countStatement, context);
+    if (internalDatabaseStatus != null) {
+      return internalDatabaseStatus;
+    }
     setCanSeeAuditDB(countStatement, context);
-    return visitAuthorityInformation(countStatement, context);
+    setCanSeeSystemDB(countStatement, context);
+    TSStatus status = visitAuthorityInformation(countStatement, context);
+    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      appendInternalDatabaseAuthorityScope(countStatement);
+    }
+    return status;
+  }
+
+  private void setCanSeeSystemDB(CountStatement statement, IAuditEntity 
auditEntity) {
+    statement.setCanSeeSystemDB(
+        checkHasGlobalAuth(
+            auditEntity, PrivilegeType.SYSTEM, () -> 
SchemaConstant.SYSTEM_DATABASE));
+  }
+
+  private void appendInternalDatabaseAuthorityScope(CountStatement statement) {
+    PathPatternTree authorityScope = statement.getAuthorityScope();
+    if (SchemaConstant.ALL_MATCH_SCOPE.equals(authorityScope)) {
+      return;
+    }
+    if (statement.isCanSeeSystemDB()) {
+      authorityScope.appendPathPattern(
+          createInternalDatabasePathPattern(SchemaConstant.SYSTEM_DATABASE), 
true);
+    }
+    if (statement.isCanSeeAuditDB()) {
+      
authorityScope.appendPathPattern(Audit.TREE_MODEL_AUDIT_DATABASE_PATH_PATTERN, 
true);
+    }
+    authorityScope.constructTree();
+  }
+
+  private PartialPath createInternalDatabasePathPattern(String 
internalDatabase) {
+    String[] databaseNodes = internalDatabase.split("\\.");
+    String[] pathPatternNodes = Arrays.copyOf(databaseNodes, 
databaseNodes.length + 1);
+    pathPatternNodes[databaseNodes.length] = 
IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
+    return new PartialPath(pathPatternNodes);
+  }
+
+  private TSStatus checkExplicitInternalDatabaseCount(
+      CountStatement statement, TreeAccessCheckContext context) {
+    String internalDatabase = 
getExplicitInternalDatabase(statement.getPathPattern());
+    if (internalDatabase == null) {
+      return null;
+    }
+
+    PrivilegeType requiredPrivilege =
+        SchemaConstant.SYSTEM_DATABASE.equals(internalDatabase)
+            ? PrivilegeType.SYSTEM
+            : PrivilegeType.AUDIT;
+    TSStatus status = checkGlobalAuth(context, requiredPrivilege, () -> 
internalDatabase);
+    if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      return status;
+    }
+    
statement.setCanSeeSystemDB(SchemaConstant.SYSTEM_DATABASE.equals(internalDatabase));
+    
statement.setCanSeeAuditDB(SchemaConstant.AUDIT_DATABASE.equals(internalDatabase));
+    
statement.setAuthorityScope(createAuthorityScope(statement.getPathPattern()));
+    return SUCCEED;
+  }
+
+  private String getExplicitInternalDatabase(PartialPath pathPattern) {
+    String[] nodes = pathPattern.getNodes();
+    if (nodes.length < 2 || !SchemaConstant.ROOT.equals(nodes[0])) {
+      return null;
+    }
+    String database = SchemaConstant.ROOT + "." + nodes[1];
+    if (SchemaConstant.SYSTEM_DATABASE.equals(database)
+        || SchemaConstant.AUDIT_DATABASE.equals(database)) {
+      return database;
+    }
+    return null;
+  }
+
+  private PathPatternTree createAuthorityScope(PartialPath pathPattern) {
+    PathPatternTree authorityScope = new PathPatternTree();
+    authorityScope.appendPathPattern(pathPattern);
+    authorityScope.constructTree();
+    return authorityScope;
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/CountStatement.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/CountStatement.java
index 529a8660dfb..a74390b7bed 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/CountStatement.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/CountStatement.java
@@ -34,6 +34,7 @@ import java.util.List;
  */
 public class CountStatement extends ShowStatement {
   protected PartialPath pathPattern;
+  private boolean canSeeSystemDB = true;
 
   public CountStatement(PartialPath pathPattern) {
     this.pathPattern = pathPattern;
@@ -52,4 +53,12 @@ public class CountStatement extends ShowStatement {
   public List<PartialPath> getPaths() {
     return Collections.singletonList(pathPattern);
   }
+
+  public boolean isCanSeeSystemDB() {
+    return canSeeSystemDB;
+  }
+
+  public void setCanSeeSystemDB(boolean canSeeSystemDB) {
+    this.canSeeSystemDB = canSeeSystemDB;
+  }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/TreeAccessTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/TreeAccessTest.java
index af8746fae3e..dd1826982c9 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/TreeAccessTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/TreeAccessTest.java
@@ -21,9 +21,12 @@ package org.apache.iotdb.db.auth;
 
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.auth.entity.User;
+import org.apache.iotdb.commons.path.PartialPath;
 import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckVisitor;
 import org.apache.iotdb.db.queryengine.plan.statement.AuthorType;
+import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountLevelTimeSeriesStatement;
+import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.CountTimeSeriesStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement;
 import org.apache.iotdb.rpc.TSStatusCode;
 
@@ -33,6 +36,8 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
 
+import java.util.Collections;
+
 public class TreeAccessTest {
 
   @Before
@@ -81,4 +86,132 @@ public class TreeAccessTest {
             .visitAuthor(authorStatement, new TreeAccessCheckContext(10000L, 
"user1", ""))
             .getCode());
   }
+
+  @Test
+  public void testCountTimeSeriesInternalDatabasePermission() throws Exception 
{
+    User user = new User("user1", "password");
+    
AuthorityChecker.getAuthorityFetcher().getAuthorCache().putUserCache(user.getName(),
 user);
+    TreeAccessCheckVisitor treeAccessCheckVisitor = new 
TreeAccessCheckVisitor();
+
+    CountTimeSeriesStatement systemStatement =
+        new CountTimeSeriesStatement(new PartialPath("root.__system.**"));
+    Assert.assertEquals(
+        TSStatusCode.NO_PERMISSION.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(systemStatement, new 
TreeAccessCheckContext(10000L, "user1", ""))
+            .getCode());
+
+    user.grantSysPrivilege(PrivilegeType.SYSTEM, false);
+    systemStatement = new CountTimeSeriesStatement(new 
PartialPath("root.__system.**"));
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(systemStatement, new 
TreeAccessCheckContext(10000L, "user1", ""))
+            .getCode());
+    Assert.assertEquals(
+        Collections.singletonList(new PartialPath("root.__system.**")),
+        systemStatement.getAuthorityScope().getAllPathPatterns());
+    Assert.assertTrue(systemStatement.isCanSeeSystemDB());
+    Assert.assertFalse(systemStatement.isCanSeeAuditDB());
+
+    CountLevelTimeSeriesStatement systemLevelStatement =
+        new CountLevelTimeSeriesStatement(new PartialPath("root.__system.**"), 
1);
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountLevelTimeSeries(
+                systemLevelStatement, new TreeAccessCheckContext(10000L, 
"user1", ""))
+            .getCode());
+    Assert.assertEquals(
+        Collections.singletonList(new PartialPath("root.__system.**")),
+        systemLevelStatement.getAuthorityScope().getAllPathPatterns());
+    Assert.assertTrue(systemLevelStatement.isCanSeeSystemDB());
+    Assert.assertFalse(systemLevelStatement.isCanSeeAuditDB());
+
+    CountTimeSeriesStatement auditStatement =
+        new CountTimeSeriesStatement(new PartialPath("root.__audit.**"));
+    Assert.assertEquals(
+        TSStatusCode.NO_PERMISSION.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(auditStatement, new 
TreeAccessCheckContext(10000L, "user1", ""))
+            .getCode());
+
+    user.grantSysPrivilege(PrivilegeType.AUDIT, false);
+    auditStatement = new CountTimeSeriesStatement(new 
PartialPath("root.__audit.**"));
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(auditStatement, new 
TreeAccessCheckContext(10000L, "user1", ""))
+            .getCode());
+    Assert.assertTrue(auditStatement.isCanSeeAuditDB());
+    Assert.assertFalse(auditStatement.isCanSeeSystemDB());
+    Assert.assertEquals(
+        Collections.singletonList(new PartialPath("root.__audit.**")),
+        auditStatement.getAuthorityScope().getAllPathPatterns());
+
+    CountLevelTimeSeriesStatement auditLevelStatement =
+        new CountLevelTimeSeriesStatement(new PartialPath("root.__audit.**"), 
1);
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountLevelTimeSeries(
+                auditLevelStatement, new TreeAccessCheckContext(10000L, 
"user1", ""))
+            .getCode());
+    Assert.assertTrue(auditLevelStatement.isCanSeeAuditDB());
+    Assert.assertFalse(auditLevelStatement.isCanSeeSystemDB());
+    Assert.assertEquals(
+        Collections.singletonList(new PartialPath("root.__audit.**")),
+        auditLevelStatement.getAuthorityScope().getAllPathPatterns());
+  }
+
+  @Test
+  public void testCountTimeSeriesImplicitInternalDatabasePermission() throws 
Exception {
+    User user = new User("user2", "password");
+    
AuthorityChecker.getAuthorityFetcher().getAuthorCache().putUserCache(user.getName(),
 user);
+    TreeAccessCheckVisitor treeAccessCheckVisitor = new 
TreeAccessCheckVisitor();
+
+    CountTimeSeriesStatement statement = new CountTimeSeriesStatement(new 
PartialPath("root.**"));
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(statement, new 
TreeAccessCheckContext(10000L, "user2", ""))
+            .getCode());
+    Assert.assertFalse(statement.isCanSeeSystemDB());
+    Assert.assertFalse(statement.isCanSeeAuditDB());
+
+    user.grantSysPrivilege(PrivilegeType.SYSTEM, false);
+    statement = new CountTimeSeriesStatement(new PartialPath("root.**"));
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(statement, new 
TreeAccessCheckContext(10000L, "user2", ""))
+            .getCode());
+    Assert.assertTrue(statement.isCanSeeSystemDB());
+    Assert.assertFalse(statement.isCanSeeAuditDB());
+    Assert.assertTrue(
+        statement
+            .getAuthorityScope()
+            .getAllPathPatterns()
+            .contains(new PartialPath("root.__system.**")));
+
+    user.grantSysPrivilege(PrivilegeType.AUDIT, false);
+    statement = new CountTimeSeriesStatement(new PartialPath("root.**"));
+    Assert.assertEquals(
+        TSStatusCode.SUCCESS_STATUS.getStatusCode(),
+        treeAccessCheckVisitor
+            .visitCountTimeSeries(statement, new 
TreeAccessCheckContext(10000L, "user2", ""))
+            .getCode());
+    Assert.assertTrue(statement.isCanSeeSystemDB());
+    Assert.assertTrue(statement.isCanSeeAuditDB());
+    Assert.assertTrue(
+        statement
+            .getAuthorityScope()
+            .getAllPathPatterns()
+            .contains(new PartialPath("root.__system.**")));
+    Assert.assertTrue(
+        statement
+            .getAuthorityScope()
+            .getAllPathPatterns()
+            .contains(new PartialPath("root.__audit.**")));
+  }
 }
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..307e69a179e
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/TimeSeriesSchemaSourceTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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 testCountSourceSkipsUnauthorizedInternalDatabases() throws 
Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            false);
+
+    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 testCountSourceKeepsAuthorizedInternalDatabases() throws 
Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> systemCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE,
+            true,
+            false);
+    assertFalse(
+        
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+    assertTrue(
+        
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+
+    final ISchemaSource<ITimeSeriesSchemaInfo> auditCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            true);
+    assertFalse(
+        
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+    assertTrue(
+        
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+  }
+
+  @Test
+  public void 
testCountSourceSkipsUnauthorizedInternalDatabasesWithWildcardSecondNode()
+      throws Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.*.**"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            false);
+
+    assertTrue(
+        
countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
+    
assertTrue(countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
+    
assertFalse(countSource.shouldSkipSchemaRegion(mockSchemaRegion("root.sg")));
+  }
+
+  @Test
+  public void testCountSourceKeepsExactInternalDatabaseQueriesWithPrivilege() 
throws Exception {
+    final ISchemaSource<ITimeSeriesSchemaInfo> systemCountSource =
+        SchemaSourceFactory.getTimeSeriesSchemaCountSource(
+            new PartialPath("root.__system"),
+            false,
+            null,
+            Collections.emptyMap(),
+            SchemaConstant.ALL_MATCH_SCOPE,
+            true,
+            false);
+    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,
+            false,
+            true);
+    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,
+            false,
+            false);
+    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;
+  }
+}
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/RegionScanPlanningTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/RegionScanPlanningTest.java
index 205758304e0..892fc4ee3dd 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/RegionScanPlanningTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/RegionScanPlanningTest.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.QueryId;
+import org.apache.iotdb.db.queryengine.common.TimeseriesContext;
 import org.apache.iotdb.db.queryengine.plan.analyze.Analysis;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.DistributedQueryPlan;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan;
@@ -36,10 +37,15 @@ import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.TimeseriesR
 
 import org.junit.Test;
 
+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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 public class RegionScanPlanningTest {
@@ -145,4 +151,79 @@ public class RegionScanPlanningTest {
     assertEquals(devicePaths, targetDevicePaths);
     assertEquals(path, targetMeasurementPaths);
   }
+
+  @Test
+  public void testCountTimeseriesWithLogicalViewUsesMergeBeforeCount() throws 
IllegalPathException {
+    QueryId queryId = new QueryId("test");
+    MPPQueryContext context =
+        new MPPQueryContext("", queryId, null, new TEndPoint(), new 
TEndPoint());
+
+    Map<String, TimeseriesContext> logicalViewContextMap =
+        Collections.singletonMap(
+            "root.sg.view.v1",
+            new TimeseriesContext(
+                "INT32",
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                1,
+                true,
+                "root.sg",
+                Collections.emptyMap()));
+    Map<PartialPath, Map<PartialPath, List<TimeseriesContext>>> 
deviceToTimeseriesSchemaInfo =
+        new HashMap<>();
+    deviceToTimeseriesSchemaInfo.put(
+        new PartialPath("root.sg.d22"),
+        Collections.singletonMap(
+            new MeasurementPath("root.sg.d22.s1"),
+            Collections.singletonList(
+                new TimeseriesContext(
+                    "INT32",
+                    null,
+                    "PLAIN",
+                    "LZ4",
+                    null,
+                    null,
+                    null,
+                    null,
+                    0,
+                    logicalViewContextMap))));
+    deviceToTimeseriesSchemaInfo.put(
+        new PartialPath("root.sg.d55555"),
+        Collections.singletonMap(
+            new MeasurementPath("root.sg.d55555.s1"),
+            Collections.singletonList(
+                new TimeseriesContext(
+                    "INT32",
+                    null,
+                    "PLAIN",
+                    "LZ4",
+                    null,
+                    null,
+                    null,
+                    null,
+                    0,
+                    logicalViewContextMap))));
+
+    TimeseriesRegionScanNode regionScanNode =
+        new TimeseriesRegionScanNode(
+            queryId.genPlanNodeId(), deviceToTimeseriesSchemaInfo, true, null);
+    PlanNode rewrittenRoot =
+        new DistributionPlanner(Util.ANALYSIS, new LogicalQueryPlan(context, 
regionScanNode))
+            .rewriteSource();
+
+    assertTrue(rewrittenRoot instanceof ActiveRegionScanMergeNode);
+    ActiveRegionScanMergeNode mergeNode = (ActiveRegionScanMergeNode) 
rewrittenRoot;
+    assertTrue(mergeNode.isOutputCount());
+    assertTrue(mergeNode.isNeedMerge());
+    assertEquals(2, mergeNode.getChildren().size());
+    for (PlanNode child : mergeNode.getChildren()) {
+      assertTrue(child instanceof TimeseriesRegionScanNode);
+      assertFalse(((TimeseriesRegionScanNode) child).isOutputCount());
+    }
+  }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/RegionScanLogicalPlannerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/RegionScanLogicalPlannerTest.java
index dd3b8b6281e..6975d845c03 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/RegionScanLogicalPlannerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/logical/RegionScanLogicalPlannerTest.java
@@ -276,4 +276,51 @@ public class RegionScanLogicalPlannerTest {
     buffer.flip();
     Assert.assertEquals(timeseriesRegionScanNode, 
PlanNodeType.deserialize(buffer));
   }
+
+  @Test
+  public void serializeDeserializeLogicalViewContextTest() throws 
IllegalPathException {
+    Map<String, TimeseriesContext> logicalViewContextMap =
+        Collections.singletonMap(
+            "root.sg.view.v1",
+            new TimeseriesContext(
+                "INT32",
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                1,
+                true,
+                "root.sg",
+                new HashMap<>()));
+    Map<PartialPath, List<TimeseriesContext>> timeseriesSchemaInfoMap = new 
HashMap<>();
+    timeseriesSchemaInfoMap.put(
+        new MeasurementPath("root.sg.d3.s1", TSDataType.INT32),
+        Collections.singletonList(
+            new TimeseriesContext(
+                "INT32",
+                null,
+                config.getDefaultInt32Encoding().toString(),
+                "LZ4",
+                null,
+                null,
+                null,
+                null,
+                0,
+                logicalViewContextMap)));
+    Map<PartialPath, Map<PartialPath, List<TimeseriesContext>>> 
deviceToTimeseriesSchemaInfo =
+        new HashMap<>();
+    deviceToTimeseriesSchemaInfo.put(new PartialPath("root.sg.d3"), 
timeseriesSchemaInfoMap);
+
+    TimeseriesRegionScanNode timeseriesRegionScanNode =
+        new TimeseriesRegionScanNode(
+            new PlanNodeId("timeseries_test_id"), 
deviceToTimeseriesSchemaInfo, false, null);
+
+    ByteBuffer buffer = ByteBuffer.allocate(10240);
+    timeseriesRegionScanNode.serialize(buffer);
+    buffer.flip();
+    Assert.assertEquals(timeseriesRegionScanNode, 
PlanNodeType.deserialize(buffer));
+  }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/metadata/read/SchemaCountNodeSerdeTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/metadata/read/SchemaCountNodeSerdeTest.java
index b5dca437289..6be0ad7fae5 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/metadata/read/SchemaCountNodeSerdeTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/planner/node/metadata/read/SchemaCountNodeSerdeTest.java
@@ -87,7 +87,9 @@ public class SchemaCountNodeSerdeTest {
             10,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            true,
+            true);
     IdentitySinkNode sinkNode =
         new IdentitySinkNode(
             new PlanNodeId("sink"),
@@ -122,7 +124,9 @@ public class SchemaCountNodeSerdeTest {
             true,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            true,
+            true);
     IdentitySinkNode sinkNode =
         new IdentitySinkNode(
             new PlanNodeId("sink"),

Reply via email to