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

zyk 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 e4ead169cee Support Show View (#9951)
e4ead169cee is described below

commit e4ead169cee45c55a20f280ededc0b7cb6f13f1e
Author: Marcos_Zyk <[email protected]>
AuthorDate: Fri May 26 14:42:41 2023 +0800

    Support Show View (#9951)
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |   6 +-
 .../reader/SchemaReaderLimitOffsetWrapper.java     |  86 ++++++++++
 .../db/mpp/common/header/ColumnHeaderConstant.java |  11 ++
 .../db/mpp/common/header/DatasetHeaderFactory.java |   4 +
 .../schema/source/LogicalViewSchemaSource.java     | 175 +++++++++++++++++++++
 .../schema/source/SchemaSourceFactory.java         |   5 +
 .../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java  |  17 ++
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |  27 ++++
 .../db/mpp/plan/planner/LogicalPlanBuilder.java    |   9 ++
 .../db/mpp/plan/planner/LogicalPlanVisitor.java    |  37 +++++
 .../db/mpp/plan/planner/OperatorTreeGenerator.java |  20 +++
 .../mpp/plan/planner/plan/node/PlanNodeType.java   |   6 +-
 .../metedata/read/LogicalViewSchemaScanNode.java   | 126 +++++++++++++++
 .../db/mpp/plan/statement/StatementVisitor.java    |   5 +
 .../metadata/view/ShowLogicalViewStatement.java    |  62 ++++++++
 15 files changed, 594 insertions(+), 2 deletions(-)

diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 98a866e5fdb..93ffd7a1c5a 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -64,7 +64,7 @@ ddlStatement
     // Quota
     | setSpaceQuota | showSpaceQuota | setThrottleQuota | showThrottleQuota
     // View
-    | createLogicalView | dropLogicalView
+    | createLogicalView | dropLogicalView | showLogicalView
     ;
 
 dmlStatement
@@ -563,6 +563,10 @@ createLogicalView
     : CREATE VIEW viewTargetPaths AS viewSourcePaths
     ;
 
+showLogicalView
+    : SHOW VIEW prefixPath? timeseriesWhereClause? rowPaginationClause?
+    ;
+
 dropLogicalView
     : (DELETE | DROP) VIEW prefixPath (COMMA prefixPath)*
     ;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/query/reader/SchemaReaderLimitOffsetWrapper.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/query/reader/SchemaReaderLimitOffsetWrapper.java
new file mode 100644
index 00000000000..4c3ed2cb89b
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/query/reader/SchemaReaderLimitOffsetWrapper.java
@@ -0,0 +1,86 @@
+/*
+ * 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.metadata.query.reader;
+
+import org.apache.iotdb.db.metadata.query.info.ISchemaInfo;
+
+import java.util.NoSuchElementException;
+
+public class SchemaReaderLimitOffsetWrapper<T extends ISchemaInfo> implements 
ISchemaReader<T> {
+
+  private final ISchemaReader<T> schemaReader;
+
+  private final long limit;
+  private final long offset;
+  private final boolean hasLimit;
+
+  private int count = 0;
+  int curOffset = 0;
+
+  public SchemaReaderLimitOffsetWrapper(ISchemaReader<T> schemaReader, long 
limit, long offset) {
+    this.schemaReader = schemaReader;
+    this.limit = limit;
+    this.offset = offset;
+    this.hasLimit = limit > 0 || offset > 0;
+
+    if (hasLimit) {
+      while (curOffset < offset && schemaReader.hasNext()) {
+        schemaReader.next();
+        curOffset++;
+      }
+    }
+  }
+
+  @Override
+  public boolean isSuccess() {
+    return schemaReader.isSuccess();
+  }
+
+  @Override
+  public Throwable getFailure() {
+    return schemaReader.getFailure();
+  }
+
+  @Override
+  public void close() throws Exception {
+    schemaReader.close();
+  }
+
+  @Override
+  public boolean hasNext() {
+    if (hasLimit) {
+      return count < limit && schemaReader.hasNext();
+    } else {
+      return schemaReader.hasNext();
+    }
+  }
+
+  @Override
+  public T next() {
+    if (!hasNext()) {
+      throw new NoSuchElementException();
+    }
+    T result = schemaReader.next();
+    if (hasLimit) {
+      count++;
+    }
+    return result;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
index b5d6e60bb27..a5ab5165c8c 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/ColumnHeaderConstant.java
@@ -186,6 +186,7 @@ public class ColumnHeaderConstant {
 
   // column names for views (eg. logical view)
   public static final String VIEW_TYPE = "ViewType";
+  public static final String SOURCE = "Source";
 
   public static final List<ColumnHeader> lastQueryColumnHeaders =
       ImmutableList.of(
@@ -458,4 +459,14 @@ public class ColumnHeaderConstant {
           new ColumnHeader(TRAIL_ID, TSDataType.TEXT),
           new ColumnHeader(MODEL_PATH, TSDataType.TEXT),
           new ColumnHeader(HYPERPARAMETER, TSDataType.TEXT));
+
+  public static final List<ColumnHeader> showLogicalViewColumnHeaders =
+      ImmutableList.of(
+          new ColumnHeader(TIMESERIES, TSDataType.TEXT),
+          new ColumnHeader(DATABASE, TSDataType.TEXT),
+          new ColumnHeader(DATATYPE, TSDataType.TEXT),
+          new ColumnHeader(TAGS, TSDataType.TEXT),
+          new ColumnHeader(ATTRIBUTES, TSDataType.TEXT),
+          new ColumnHeader(VIEW_TYPE, TSDataType.TEXT),
+          new ColumnHeader(SOURCE, TSDataType.TEXT));
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/DatasetHeaderFactory.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/DatasetHeaderFactory.java
index 6652bcfa2f1..430839e0d6d 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/common/header/DatasetHeaderFactory.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/common/header/DatasetHeaderFactory.java
@@ -188,4 +188,8 @@ public class DatasetHeaderFactory {
   public static DatasetHeader getShowTrailsHeader() {
     return new DatasetHeader(ColumnHeaderConstant.showTrailsColumnHeaders, 
true);
   }
+
+  public static DatasetHeader getShowLogicalViewHeader() {
+    return new 
DatasetHeader(ColumnHeaderConstant.showLogicalViewColumnHeaders, true);
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/LogicalViewSchemaSource.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/LogicalViewSchemaSource.java
new file mode 100644
index 00000000000..1841d64a8da
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/LogicalViewSchemaSource.java
@@ -0,0 +1,175 @@
+/*
+ * 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.mpp.execution.operator.schema.source;
+
+import org.apache.iotdb.commons.exception.MetadataException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
+import 
org.apache.iotdb.db.metadata.plan.schemaregion.impl.read.SchemaRegionReadPlanFactory;
+import org.apache.iotdb.db.metadata.query.info.ITimeSeriesSchemaInfo;
+import org.apache.iotdb.db.metadata.query.reader.ISchemaReader;
+import 
org.apache.iotdb.db.metadata.query.reader.SchemaReaderLimitOffsetWrapper;
+import org.apache.iotdb.db.metadata.schemaregion.ISchemaRegion;
+import org.apache.iotdb.db.mpp.common.header.ColumnHeader;
+import org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.tsfile.read.common.block.TsBlockBuilder;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.stream.Collectors;
+
+import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_MATCH_PATTERN;
+
+public class LogicalViewSchemaSource implements 
ISchemaSource<ITimeSeriesSchemaInfo> {
+
+  private final PartialPath pathPattern;
+
+  private final long limit;
+  private final long offset;
+
+  private final SchemaFilter schemaFilter;
+
+  LogicalViewSchemaSource(
+      PartialPath pathPattern, long limit, long offset, SchemaFilter 
schemaFilter) {
+    this.pathPattern = pathPattern;
+
+    this.limit = limit;
+    this.offset = offset;
+
+    this.schemaFilter = schemaFilter;
+  }
+
+  @Override
+  public ISchemaReader<ITimeSeriesSchemaInfo> getSchemaReader(ISchemaRegion 
schemaRegion) {
+    try {
+      return new SchemaReaderLimitOffsetWrapper<ITimeSeriesSchemaInfo>(
+          new LogicalViewSchemaReader(
+              schemaRegion.getTimeSeriesReader(
+                  SchemaRegionReadPlanFactory.getShowTimeSeriesPlan(
+                      pathPattern, Collections.emptyMap(), 0, 0, false, 
schemaFilter))),
+          limit,
+          offset);
+    } catch (MetadataException e) {
+      throw new RuntimeException(e.getMessage(), e);
+    }
+  }
+
+  @Override
+  public List<ColumnHeader> getInfoQueryColumnHeaders() {
+    return ColumnHeaderConstant.showLogicalViewColumnHeaders;
+  }
+
+  @Override
+  public void transformToTsBlockColumns(
+      ITimeSeriesSchemaInfo series, TsBlockBuilder builder, String database) {
+    builder.getTimeColumnBuilder().writeLong(0);
+    builder.writeNullableText(0, series.getFullPath());
+    builder.writeNullableText(1, database);
+
+    builder.writeNullableText(2, "");
+
+    builder.writeNullableText(3, mapToString(series.getTags()));
+    builder.writeNullableText(4, mapToString(series.getAttributes()));
+
+    builder.writeNullableText(5, "logical");
+    builder.writeNullableText(
+        6, ((LogicalViewSchema) 
series.getSchema()).getExpression().toString());
+    builder.declarePosition();
+  }
+
+  @Override
+  public boolean hasSchemaStatistic(ISchemaRegion schemaRegion) {
+    return pathPattern.equals(ALL_MATCH_PATTERN) && (schemaFilter == null);
+  }
+
+  @Override
+  public long getSchemaStatistic(ISchemaRegion schemaRegion) {
+    return schemaRegion.getSchemaRegionStatistics().getSeriesNumber();
+  }
+
+  private String mapToString(Map<String, String> map) {
+    if (map == null || map.isEmpty()) {
+      return null;
+    }
+    String content =
+        map.entrySet().stream()
+            .map(e -> "\"" + e.getKey() + "\"" + ":" + "\"" + e.getValue() + 
"\"")
+            .collect(Collectors.joining(","));
+    return "{" + content + "}";
+  }
+
+  private static class LogicalViewSchemaReader implements 
ISchemaReader<ITimeSeriesSchemaInfo> {
+
+    private final ISchemaReader<ITimeSeriesSchemaInfo> timeSeriesReader;
+
+    private ITimeSeriesSchemaInfo nextResult;
+
+    LogicalViewSchemaReader(ISchemaReader<ITimeSeriesSchemaInfo> 
timeSeriesReader) {
+      this.timeSeriesReader = timeSeriesReader;
+    }
+
+    @Override
+    public boolean isSuccess() {
+      return timeSeriesReader.isSuccess();
+    }
+
+    @Override
+    public Throwable getFailure() {
+      return timeSeriesReader.getFailure();
+    }
+
+    @Override
+    public void close() throws Exception {
+      timeSeriesReader.close();
+    }
+
+    @Override
+    public boolean hasNext() {
+      if (nextResult == null) {
+        getNext();
+      }
+      return nextResult != null;
+    }
+
+    @Override
+    public ITimeSeriesSchemaInfo next() {
+      if (!hasNext()) {
+        throw new NoSuchElementException();
+      }
+      ITimeSeriesSchemaInfo result = nextResult;
+      nextResult = null;
+      return result;
+    }
+
+    private void getNext() {
+      ITimeSeriesSchemaInfo timeSeriesSchemaInfo;
+      while (timeSeriesReader.hasNext()) {
+        timeSeriesSchemaInfo = timeSeriesReader.next();
+        if (timeSeriesSchemaInfo.isLogicalView()) {
+          nextResult = timeSeriesSchemaInfo;
+          return;
+        }
+      }
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/SchemaSourceFactory.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/SchemaSourceFactory.java
index 6c7cc9e6efa..ccfb31ccef8 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/SchemaSourceFactory.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/schema/source/SchemaSourceFactory.java
@@ -81,4 +81,9 @@ public class SchemaSourceFactory {
       List<PartialPath> pathPatternList, int templateId) {
     return new PathsUsingTemplateSource(pathPatternList, templateId);
   }
+
+  public static ISchemaSource<ITimeSeriesSchemaInfo> 
getLogicalViewSchemaSource(
+      PartialPath pathPattern, long limit, long offset, SchemaFilter 
schemaFilter) {
+    return new LogicalViewSchemaSource(pathPattern, limit, offset, 
schemaFilter);
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index a4983f060d3..6e32b1d658d 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -136,6 +136,7 @@ import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowPathSetTempl
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.CreateLogicalViewStatement;
+import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.ShowLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ShowQueriesStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ShowVersionStatement;
@@ -3326,4 +3327,20 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
 
     return analysis;
   }
+
+  @Override
+  public Analysis visitShowLogicalView(
+      ShowLogicalViewStatement showLogicalViewStatement, MPPQueryContext 
context) {
+    context.setQueryType(QueryType.READ);
+    Analysis analysis = new Analysis();
+    analysis.setStatement(showLogicalViewStatement);
+
+    PathPatternTree patternTree = new PathPatternTree();
+    patternTree.appendPathPattern(showLogicalViewStatement.getPathPattern());
+    SchemaPartition schemaPartitionInfo = 
partitionFetcher.getSchemaPartition(patternTree);
+    analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+
+    
analysis.setRespDatasetHeader(DatasetHeaderFactory.getShowLogicalViewHeader());
+    return analysis;
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index 8f965050939..2bd2080cff0 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -165,6 +165,7 @@ import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTempla
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.UnsetSchemaTemplateStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.CreateLogicalViewStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.DeleteLogicalViewStatement;
+import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.ShowLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.AuthorStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ClearCacheStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
@@ -1016,6 +1017,32 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     return deleteLogicalViewStatement;
   }
 
+  @Override
+  public Statement visitShowLogicalView(IoTDBSqlParser.ShowLogicalViewContext 
ctx) {
+    ShowLogicalViewStatement showLogicalViewStatement;
+    if (ctx.prefixPath() != null) {
+      showLogicalViewStatement = new 
ShowLogicalViewStatement(parsePrefixPath(ctx.prefixPath()));
+    } else {
+      showLogicalViewStatement =
+          new ShowLogicalViewStatement(new 
PartialPath(SqlConstant.getSingleRootArray()));
+    }
+    if (ctx.timeseriesWhereClause() != null) {
+      SchemaFilter schemaFilter = 
parseTimeseriesWhereClause(ctx.timeseriesWhereClause());
+      showLogicalViewStatement.setSchemaFilter(schemaFilter);
+    }
+    if (ctx.rowPaginationClause() != null) {
+      if (ctx.rowPaginationClause().limitClause() != null) {
+        showLogicalViewStatement.setLimit(
+            parseLimitClause(ctx.rowPaginationClause().limitClause()));
+      }
+      if (ctx.rowPaginationClause().offsetClause() != null) {
+        showLogicalViewStatement.setOffset(
+            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
+      }
+    }
+    return showLogicalViewStatement;
+  }
+
   // parse suffix paths in logical view
   private PartialPath 
parseViewSuffixPath(IoTDBSqlParser.ViewSuffixPathsContext ctx) {
     List<IoTDBSqlParser.NodeNameWithoutWildcardContext> nodeNamesWithoutStar =
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java
index b191f3f2a1c..3bc06b12940 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java
@@ -43,6 +43,7 @@ import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.CountSchemaM
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.DevicesCountNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.DevicesSchemaScanNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.LevelTimeSeriesCountNode;
+import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.LogicalViewSchemaScanNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodeManagementMemoryMergeNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodePathsConvertNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodePathsCountNode;
@@ -1148,6 +1149,14 @@ public class LogicalPlanBuilder {
     return this;
   }
 
+  public LogicalPlanBuilder planLogicalViewSchemaSource(
+      PartialPath pathPattern, SchemaFilter schemaFilter, long limit, long 
offset) {
+    this.root =
+        new LogicalViewSchemaScanNode(
+            context.getQueryId().genPlanNodeId(), pathPattern, schemaFilter, 
limit, offset);
+    return this;
+  }
+
   private LogicalPlanBuilder planSort(OrderByParameter orderByParameter) {
     if (orderByParameter.isEmpty()) {
       return this;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
index 01eaf88aecc..b3397e563b6 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
@@ -80,6 +80,7 @@ import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ActivateTemplate
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.BatchActivateTemplateStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowPathsUsingTemplateStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.CreateLogicalViewStatement;
+import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.ShowLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ShowQueriesStatement;
 import org.apache.iotdb.tsfile.utils.Pair;
 
@@ -844,4 +845,40 @@ public class LogicalPlanVisitor extends 
StatementVisitor<PlanNode, MPPQueryConte
         createLogicalViewStatement.getTargetPathList(),
         viewExpressionList);
   }
+
+  @Override
+  public PlanNode visitShowLogicalView(
+      ShowLogicalViewStatement showTimeSeriesStatement, MPPQueryContext 
context) {
+    LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(analysis, context);
+
+    // If there is only one region, we can push down the offset and limit 
operation to
+    // source operator.
+    boolean canPushDownOffsetLimit =
+        analysis.getSchemaPartitionInfo() != null
+            && analysis.getSchemaPartitionInfo().getDistributionInfo().size() 
== 1;
+
+    long limit = showTimeSeriesStatement.getLimit();
+    long offset = showTimeSeriesStatement.getOffset();
+    if (!canPushDownOffsetLimit) {
+      limit = showTimeSeriesStatement.getLimit() + 
showTimeSeriesStatement.getOffset();
+      offset = 0;
+    }
+    planBuilder =
+        planBuilder
+            .planLogicalViewSchemaSource(
+                showTimeSeriesStatement.getPathPattern(),
+                showTimeSeriesStatement.getSchemaFilter(),
+                limit,
+                offset)
+            .planSchemaQueryMerge(false);
+
+    if (canPushDownOffsetLimit) {
+      return planBuilder.getRoot();
+    }
+
+    return planBuilder
+        .planOffset(showTimeSeriesStatement.getOffset())
+        .planLimit(showTimeSeriesStatement.getLimit())
+        .getRoot();
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
index 13c033c8a29..e98855927e4 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
@@ -142,6 +142,7 @@ import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.CountSchemaM
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.DevicesCountNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.DevicesSchemaScanNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.LevelTimeSeriesCountNode;
+import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.LogicalViewSchemaScanNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodeManagementMemoryMergeNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodePathsConvertNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodePathsCountNode;
@@ -531,6 +532,8 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
       return visitNodePathsSchemaScan((NodePathsSchemaScanNode) node, context);
     } else if (node instanceof PathsUsingTemplateScanNode) {
       return visitPathsUsingTemplateScan((PathsUsingTemplateScanNode) node, 
context);
+    } else if (node instanceof LogicalViewSchemaScanNode) {
+      return visitLogicalViewSchemaScan((LogicalViewSchemaScanNode) node, 
context);
     }
     return visitPlan(node, context);
   }
@@ -2380,6 +2383,23 @@ public class OperatorTreeGenerator extends 
PlanVisitor<Operator, LocalExecutionP
             node.getPathPatternList(), node.getTemplateId()));
   }
 
+  public Operator visitLogicalViewSchemaScan(
+      LogicalViewSchemaScanNode node, LocalExecutionPlanContext context) {
+    OperatorContext operatorContext =
+        context
+            .getDriverContext()
+            .addOperatorContext(
+                context.getNextOperatorId(),
+                node.getPlanNodeId(),
+                SchemaQueryScanOperator.class.getSimpleName());
+    context.getTimeSliceAllocator().recordExecutionWeight(operatorContext, 1);
+    return new SchemaQueryScanOperator<>(
+        node.getPlanNodeId(),
+        operatorContext,
+        SchemaSourceFactory.getLogicalViewSchemaSource(
+            node.getPath(), node.getLimit(), node.getOffset(), 
node.getSchemaFilter()));
+  }
+
   public List<Operator> dealWithConsumeAllChildrenPipelineBreaker(
       PlanNode node, LocalExecutionPlanContext context) {
     // children after pipelining
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
index 9d0bc8a148d..f0ff085eded 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/PlanNodeType.java
@@ -23,6 +23,7 @@ import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.CountSchemaM
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.DevicesCountNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.DevicesSchemaScanNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.LevelTimeSeriesCountNode;
+import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.LogicalViewSchemaScanNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodeManagementMemoryMergeNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodePathsConvertNode;
 import 
org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.NodePathsCountNode;
@@ -175,7 +176,8 @@ public enum PlanNodeType {
   CREATE_LOGICAL_VIEW((short) 73),
   CONSTRUCT_LOGICAL_VIEW_BLACK_LIST((short) 74),
   ROLLBACK_LOGICAL_VIEW_BLACK_LIST((short) 75),
-  DELETE_LOGICAL_VIEW((short) 76);
+  DELETE_LOGICAL_VIEW((short) 76),
+  LOGICAL_VIEW_SCHEMA_SCAN((short) 77);
 
   public static final int BYTES = Short.BYTES;
 
@@ -376,6 +378,8 @@ public enum PlanNodeType {
         return RollbackLogicalViewBlackListNode.deserialize(buffer);
       case 76:
         return DeleteLogicalViewNode.deserialize(buffer);
+      case 77:
+        return LogicalViewSchemaScanNode.deserialize(buffer);
       default:
         throw new IllegalArgumentException("Invalid node type: " + nodeType);
     }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/metedata/read/LogicalViewSchemaScanNode.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/metedata/read/LogicalViewSchemaScanNode.java
new file mode 100644
index 00000000000..060d0ef23dd
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/plan/node/metedata/read/LogicalViewSchemaScanNode.java
@@ -0,0 +1,126 @@
+/*
+ * 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.mpp.plan.planner.plan.node.metedata.read;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.db.mpp.common.header.ColumnHeader;
+import org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNodeId;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNodeType;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class LogicalViewSchemaScanNode extends SchemaQueryScanNode {
+
+  private final SchemaFilter schemaFilter;
+
+  public LogicalViewSchemaScanNode(
+      PlanNodeId id, PartialPath partialPath, SchemaFilter schemaFilter, long 
limit, long offset) {
+    super(id, partialPath, limit, offset, false);
+    this.schemaFilter = schemaFilter;
+  }
+
+  public SchemaFilter getSchemaFilter() {
+    return schemaFilter;
+  }
+
+  @Override
+  protected void serializeAttributes(ByteBuffer byteBuffer) {
+    PlanNodeType.LOGICAL_VIEW_SCHEMA_SCAN.serialize(byteBuffer);
+    ReadWriteIOUtils.write(path.getFullPath(), byteBuffer);
+    SchemaFilter.serialize(schemaFilter, byteBuffer);
+    ReadWriteIOUtils.write(limit, byteBuffer);
+    ReadWriteIOUtils.write(offset, byteBuffer);
+  }
+
+  @Override
+  protected void serializeAttributes(DataOutputStream stream) throws 
IOException {
+    PlanNodeType.LOGICAL_VIEW_SCHEMA_SCAN.serialize(stream);
+    ReadWriteIOUtils.write(path.getFullPath(), stream);
+    SchemaFilter.serialize(schemaFilter, stream);
+    ReadWriteIOUtils.write(limit, stream);
+    ReadWriteIOUtils.write(offset, stream);
+  }
+
+  public static LogicalViewSchemaScanNode deserialize(ByteBuffer byteBuffer) {
+    String fullPath = ReadWriteIOUtils.readString(byteBuffer);
+    PartialPath path;
+    try {
+      path = new PartialPath(fullPath);
+    } catch (IllegalPathException e) {
+      throw new IllegalArgumentException("Cannot deserialize 
TimeSeriesSchemaScanNode", e);
+    }
+    SchemaFilter schemaFilter = SchemaFilter.deserialize(byteBuffer);
+    long limit = ReadWriteIOUtils.readLong(byteBuffer);
+    long offset = ReadWriteIOUtils.readLong(byteBuffer);
+
+    PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer);
+
+    return new LogicalViewSchemaScanNode(planNodeId, path, schemaFilter, 
limit, offset);
+  }
+
+  @Override
+  public PlanNode clone() {
+    return new LogicalViewSchemaScanNode(getPlanNodeId(), path, schemaFilter, 
limit, offset);
+  }
+
+  @Override
+  public List<String> getOutputColumnNames() {
+    return ColumnHeaderConstant.showLogicalViewColumnHeaders.stream()
+        .map(ColumnHeader::getColumnName)
+        .collect(Collectors.toList());
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    if (!super.equals(o)) {
+      return false;
+    }
+    LogicalViewSchemaScanNode that = (LogicalViewSchemaScanNode) o;
+    return Objects.equals(schemaFilter, that.schemaFilter);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(super.hashCode(), schemaFilter);
+  }
+
+  @Override
+  public String toString() {
+    return String.format(
+        "LogicalViewSchemaScanNode-%s:[DataRegion: %s]",
+        this.getPlanNodeId(), this.getRegionReplicaSet());
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
index 03c18855434..8a70c0cf927 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/StatementVisitor.java
@@ -92,6 +92,7 @@ import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTempla
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.template.UnsetSchemaTemplateStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.CreateLogicalViewStatement;
 import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.DeleteLogicalViewStatement;
+import 
org.apache.iotdb.db.mpp.plan.statement.metadata.view.ShowLogicalViewStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.AuthorStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ClearCacheStatement;
 import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
@@ -253,6 +254,10 @@ public abstract class StatementVisitor<R, C> {
     return visitStatement(deleteLogicalViewStatement, context);
   }
 
+  public R visitShowLogicalView(ShowLogicalViewStatement 
showLogicalViewStatement, C context) {
+    return visitStatement(showLogicalViewStatement, context);
+  }
+
   // ML Model
   public R visitCreateModel(CreateModelStatement createModelStatement, C 
context) {
     return visitStatement(createModelStatement, context);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/view/ShowLogicalViewStatement.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/view/ShowLogicalViewStatement.java
new file mode 100644
index 00000000000..e98d02ab6f6
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/view/ShowLogicalViewStatement.java
@@ -0,0 +1,62 @@
+/*
+ * 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.mpp.plan.statement.metadata.view;
+
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStatement;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ShowLogicalViewStatement extends ShowStatement {
+
+  private final PartialPath pathPattern;
+
+  private SchemaFilter schemaFilter;
+
+  public ShowLogicalViewStatement(PartialPath pathPattern) {
+    super();
+    this.pathPattern = pathPattern;
+  }
+
+  public PartialPath getPathPattern() {
+    return pathPattern;
+  }
+
+  public SchemaFilter getSchemaFilter() {
+    return schemaFilter;
+  }
+
+  public void setSchemaFilter(SchemaFilter schemaFilter) {
+    this.schemaFilter = schemaFilter;
+  }
+
+  @Override
+  public List<PartialPath> getPaths() {
+    return Collections.singletonList(pathPattern);
+  }
+
+  @Override
+  public <R, C> R accept(StatementVisitor<R, C> visitor, C context) {
+    return visitor.visitShowLogicalView(this, context);
+  }
+}


Reply via email to