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

jt2594838 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new f44d9b7bf3b Fix count and show timeseries follow-up (#17804)
f44d9b7bf3b is described below

commit f44d9b7bf3bd31856c23f253af1810d03491b64e
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       |  13 ++
 .../impl/DataNodeInternalRPCServiceImpl.java       |   6 +-
 .../db/queryengine/common/TimeseriesContext.java   | 234 ++++++++++++++++++---
 .../schema/source/SchemaSourceFactory.java         |  19 +-
 .../schema/source/TimeSeriesSchemaSource.java      |  29 ++-
 .../source/ActiveTimeSeriesRegionScanOperator.java |  77 ++++---
 .../queryengine/plan/analyze/AnalyzeVisitor.java   |  57 ++++-
 .../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  |  41 ++--
 .../distribution/RegionScanPlanningTest.java       |  81 +++++++
 .../logical/RegionScanLogicalPlannerTest.java      |  47 +++++
 .../metadata/read/SchemaCountNodeSerdeTest.java    |   8 +-
 21 files changed, 887 insertions(+), 112 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 dc706140fd3..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
@@ -260,10 +260,23 @@ public class IoTDBActiveSchemaQueryIT extends 
AbstractSchemaIT {
           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());
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 aaf8b51787d..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
@@ -29,7 +29,8 @@ import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -45,20 +46,70 @@ public class TimeseriesContext {
 
   private final String deadband;
   private final String deadbandParameters;
+  private final String database;
   private final int activeCountMultiplier;
-  private final Set<String> activeLogicalViewCountSet;
+  private final boolean logicalView;
+  private final Map<String, TimeseriesContext> activeLogicalViewContextMap;
 
   public TimeseriesContext(IMeasurementSchemaInfo schemaInfo) {
-    this(schemaInfo, 1, Collections.emptySet());
+    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());
@@ -66,8 +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.activeLogicalViewCountSet = new HashSet<>(activeLogicalViewCountSet);
+    this.activeLogicalViewContextMap = new 
HashMap<>(activeLogicalViewContextMap);
   }
 
   public String getDataType() {
@@ -102,12 +154,24 @@ public class TimeseriesContext {
     return deadband;
   }
 
+  public String getDatabase() {
+    return database;
+  }
+
   public int getActiveCountMultiplier() {
     return activeCountMultiplier;
   }
 
   public Set<String> getActiveLogicalViewCountSet() {
-    return activeLogicalViewCountSet;
+    return activeLogicalViewContextMap.keySet();
+  }
+
+  public Map<String, TimeseriesContext> getActiveLogicalViewContextMap() {
+    return activeLogicalViewContextMap;
+  }
+
+  public boolean isLogicalView() {
+    return logicalView;
   }
 
   public TimeseriesContext(
@@ -129,7 +193,9 @@ public class TimeseriesContext {
         deadband,
         deadbandParameters,
         1,
-        Collections.emptySet());
+        false,
+        null,
+        Collections.emptyMap());
   }
 
   public TimeseriesContext(
@@ -143,6 +209,87 @@ public class TimeseriesContext {
       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;
@@ -151,13 +298,31 @@ public class TimeseriesContext {
     this.attributes = attributes;
     this.deadband = deadband;
     this.deadbandParameters = deadbandParameters;
+    this.database = database;
     this.activeCountMultiplier = activeCountMultiplier;
-    this.activeLogicalViewCountSet = new HashSet<>(activeLogicalViewCountSet);
+    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) {
-    Set<String> mergedActiveLogicalViewCountSet = new 
HashSet<>(activeLogicalViewCountSet);
-    mergedActiveLogicalViewCountSet.addAll(that.activeLogicalViewCountSet);
+    Map<String, TimeseriesContext> mergedActiveLogicalViewContextMap =
+        new HashMap<>(activeLogicalViewContextMap);
+    mergedActiveLogicalViewContextMap.putAll(that.activeLogicalViewContextMap);
     return new TimeseriesContext(
         dataType,
         alias,
@@ -168,7 +333,9 @@ public class TimeseriesContext {
         deadband,
         deadbandParameters,
         activeCountMultiplier + that.activeCountMultiplier,
-        mergedActiveLogicalViewCountSet);
+        logicalView,
+        database,
+        mergedActiveLogicalViewContextMap);
   }
 
   public void serializeAttributes(ByteBuffer byteBuffer) {
@@ -180,10 +347,13 @@ 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(activeLogicalViewCountSet.size(), byteBuffer);
-    for (String logicalView : activeLogicalViewCountSet) {
-      ReadWriteIOUtils.write(logicalView, 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);
     }
   }
 
@@ -196,10 +366,13 @@ 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(activeLogicalViewCountSet.size(), stream);
-    for (String logicalView : activeLogicalViewCountSet) {
-      ReadWriteIOUtils.write(logicalView, 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);
     }
   }
 
@@ -212,11 +385,14 @@ 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);
-    int activeLogicalViewCountSetSize = ReadWriteIOUtils.readInt(buffer);
-    Set<String> activeLogicalViewCountSet = new HashSet<>();
-    for (int i = 0; i < activeLogicalViewCountSetSize; i++) {
-      activeLogicalViewCountSet.add(ReadWriteIOUtils.readString(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,
@@ -228,7 +404,9 @@ public class TimeseriesContext {
         deadband,
         deadbandParameters,
         activeCountMultiplier,
-        activeLogicalViewCountSet);
+        logicalView,
+        database,
+        activeLogicalViewContextMap);
   }
 
   @Override
@@ -243,14 +421,16 @@ 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(database, that.database)
             && activeCountMultiplier == that.activeCountMultiplier
-            && Objects.equals(activeLogicalViewCountSet, 
that.activeLogicalViewCountSet);
+            && logicalView == that.logicalView
+            && Objects.equals(activeLogicalViewContextMap, 
that.activeLogicalViewContextMap);
     return res;
   }
 
@@ -265,7 +445,9 @@ public class TimeseriesContext {
         attributes,
         deadband,
         deadbandParameters,
+        database,
         activeCountMultiplier,
-        activeLogicalViewCountSet);
+        logicalView,
+        activeLogicalViewContextMap);
   }
 }
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 f45dc6a9b06..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, 
true, scope, null);
+        pathPattern,
+        isPrefixMatch,
+        0,
+        0,
+        schemaFilter,
+        templateMap,
+        false,
+        includeSystemDatabase,
+        includeAuditDatabase,
+        scope,
+        null);
   }
 
   // show time series
@@ -69,7 +81,8 @@ public class SchemaSourceFactory {
         schemaFilter,
         templateMap,
         true,
-        false,
+        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 5ac6d59b089..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
@@ -56,7 +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 excludeInternalDatabase;
+  private final boolean includeSystemDatabase;
+  private final boolean includeAuditDatabase;
   private final Ordering timeseriesOrdering;
 
   TimeSeriesSchemaSource(
@@ -67,7 +68,8 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
       SchemaFilter schemaFilter,
       Map<Integer, Template> templateMap,
       boolean needViewDetail,
-      boolean excludeInternalDatabase,
+      boolean includeSystemDatabase,
+      boolean includeAuditDatabase,
       PathPatternTree scope,
       Ordering timeseriesOrdering) {
     this.pathPattern = pathPattern;
@@ -77,7 +79,8 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
     this.schemaFilter = schemaFilter;
     this.templateMap = templateMap;
     this.needViewDetail = needViewDetail;
-    this.excludeInternalDatabase = excludeInternalDatabase;
+    this.includeSystemDatabase = includeSystemDatabase;
+    this.includeAuditDatabase = includeAuditDatabase;
     this.scope = scope;
     this.timeseriesOrdering = timeseriesOrdering;
   }
@@ -147,21 +150,15 @@ public class TimeSeriesSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaIn
 
   @Override
   public boolean shouldSkipSchemaRegion(final ISchemaRegion schemaRegion) {
-    if (!excludeInternalDatabase) {
-      return false;
-    }
-
     final String database = schemaRegion.getDatabaseFullPath();
-    if (!SchemaConstant.SYSTEM_DATABASE.equals(database)
-        && !SchemaConstant.AUDIT_DATABASE.equals(database)
-        && !Audit.TABLE_MODEL_AUDIT_DATABASE.equals(database)) {
-      return false;
+    if (SchemaConstant.SYSTEM_DATABASE.equals(database)) {
+      return !includeSystemDatabase;
     }
-
-    final String[] nodes = pathPattern.getNodes();
-    return nodes.length < 2
-        || !SchemaConstant.ROOT.equals(nodes[0])
-        || !database.endsWith("." + nodes[1]);
+    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) {
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 2dd1272f473..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
@@ -45,8 +45,12 @@ public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSo
   // Timeseries which need to be checked.
   private final Map<IDeviceID, Map<String, TimeseriesContext>> 
timeSeriesToSchemasInfo;
   private final Set<String> countedLogicalViews;
-  private static final Binary VIEW_TYPE = new Binary("BASE".getBytes());
+  private 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)
@@ -65,14 +69,13 @@ public class ActiveTimeSeriesRegionScanOperator extends 
AbstractRegionScanDataSo
     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
@@ -96,9 +99,6 @@ 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();
 
@@ -127,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 9d91a29d78b..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;
 
@@ -2932,6 +2937,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       MPPQueryContext context,
       PathPatternTree authorityScope,
       boolean canSeeAuditDB,
+      boolean canSeeSystemDB,
       boolean includeLogicalView)
       throws IllegalPathException {
     analyzeGlobalTimeConditionInShowMetaData(timeCondition, analysis);
@@ -2965,6 +2971,10 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     for (DeviceSchemaInfo deviceSchemaInfo : deviceSchemaInfoList) {
       boolean isAligned = deviceSchemaInfo.isAligned();
       PartialPath devicePath = deviceSchemaInfo.getDevicePath();
+      if (shouldSkipInternalDatabaseForActiveCount(
+          devicePath, schemaTree, canSeeAuditDB, canSeeSystemDB)) {
+        continue;
+      }
       if (isAligned) {
         List<String> measurementList = new ArrayList<>();
         List<IMeasurementSchema> schemaList = new ArrayList<>();
@@ -3022,6 +3032,22 @@ 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,
@@ -3034,6 +3060,8 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     }
 
     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;
@@ -3054,16 +3082,39 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
         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, 
Collections.singleton(viewPath)),
+          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,
@@ -3117,7 +3168,8 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
                 context,
                 showTimeSeriesStatement.getAuthorityScope(),
                 showTimeSeriesStatement.isCanSeeAuditDB(),
-                false);
+                true,
+                true);
         if (!hasSchema) {
           
analysis.setRespDatasetHeader(DatasetHeaderFactory.getShowTimeSeriesHeader());
           return analysis;
@@ -3369,6 +3421,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
                 context,
                 countTimeSeriesStatement.getAuthorityScope(),
                 countTimeSeriesStatement.isCanSeeAuditDB(),
+                countTimeSeriesStatement.isCanSeeSystemDB(),
                 true);
         if (!hasSchema) {
           
analysis.setRespDatasetHeader(DatasetHeaderFactory.getCountTimeSeriesHeader());
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 7ed81c7e842..327dbecdda2 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
index 3769018ed46..307e69a179e 100644
--- 
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
@@ -38,14 +38,16 @@ import static org.junit.Assert.assertTrue;
 public class TimeSeriesSchemaSourceTest {
 
   @Test
-  public void testCountSourceSkipsImplicitInternalDatabases() throws Exception 
{
+  public void testCountSourceSkipsUnauthorizedInternalDatabases() throws 
Exception {
     final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
         SchemaSourceFactory.getTimeSeriesSchemaCountSource(
             new PartialPath("root.**"),
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            false);
 
     assertTrue(
         
countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
@@ -56,14 +58,16 @@ public class TimeSeriesSchemaSourceTest {
   }
 
   @Test
-  public void testCountSourceKeepsExplicitInternalDatabaseQueries() throws 
Exception {
+  public void testCountSourceKeepsAuthorizedInternalDatabases() throws 
Exception {
     final ISchemaSource<ITimeSeriesSchemaInfo> systemCountSource =
         SchemaSourceFactory.getTimeSeriesSchemaCountSource(
-            new PartialPath("root.__system.**"),
+            new PartialPath("root.**"),
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            true,
+            false);
     assertFalse(
         
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
     assertTrue(
@@ -71,11 +75,13 @@ public class TimeSeriesSchemaSourceTest {
 
     final ISchemaSource<ITimeSeriesSchemaInfo> auditCountSource =
         SchemaSourceFactory.getTimeSeriesSchemaCountSource(
-            new PartialPath("root.__audit.**"),
+            new PartialPath("root.**"),
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            true);
     assertFalse(
         
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
     assertTrue(
@@ -83,14 +89,17 @@ public class TimeSeriesSchemaSourceTest {
   }
 
   @Test
-  public void testCountSourceSkipsWildcardSecondNodeForInternalDatabases() 
throws Exception {
+  public void 
testCountSourceSkipsUnauthorizedInternalDatabasesWithWildcardSecondNode()
+      throws Exception {
     final ISchemaSource<ITimeSeriesSchemaInfo> countSource =
         SchemaSourceFactory.getTimeSeriesSchemaCountSource(
             new PartialPath("root.*.**"),
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            false);
 
     assertTrue(
         
countSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
@@ -99,14 +108,16 @@ public class TimeSeriesSchemaSourceTest {
   }
 
   @Test
-  public void testCountSourceKeepsExactInternalDatabaseQueries() throws 
Exception {
+  public void testCountSourceKeepsExactInternalDatabaseQueriesWithPrivilege() 
throws Exception {
     final ISchemaSource<ITimeSeriesSchemaInfo> systemCountSource =
         SchemaSourceFactory.getTimeSeriesSchemaCountSource(
             new PartialPath("root.__system"),
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            true,
+            false);
     assertFalse(
         
systemCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.SYSTEM_DATABASE)));
 
@@ -116,7 +127,9 @@ public class TimeSeriesSchemaSourceTest {
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            true);
     assertFalse(
         
auditCountSource.shouldSkipSchemaRegion(mockSchemaRegion(SchemaConstant.AUDIT_DATABASE)));
   }
@@ -147,7 +160,9 @@ public class TimeSeriesSchemaSourceTest {
             false,
             null,
             Collections.emptyMap(),
-            SchemaConstant.ALL_MATCH_SCOPE);
+            SchemaConstant.ALL_MATCH_SCOPE,
+            false,
+            false);
     final ISchemaRegion schemaRegion = mockSchemaRegion("root.sg");
     final ISchemaRegionStatistics schemaRegionStatistics =
         Mockito.mock(ISchemaRegionStatistics.class);
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