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

caogaofei pushed a commit to branch beyyes/TableModelGrammar_DistributePlan
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to 
refs/heads/beyyes/TableModelGrammar_DistributePlan by this push:
     new 16d07feb15d add explain support
16d07feb15d is described below

commit 16d07feb15d1751ddf5e0292765bbd5dd45019f0
Author: Beyyes <[email protected]>
AuthorDate: Thu Jun 13 21:06:08 2024 +0800

    add explain support
---
 .../memory/StatementMemorySourceVisitor.java       |  4 +
 .../TableModelStatementMemorySourceContext.java    | 41 ++++++++++
 .../TableModelStatementMemorySourceVisitor.java    | 90 ++++++++++++++++++++++
 .../plan/planner/plan/node/PlanGraphPrinter.java   | 54 +++++++++++++
 .../plan/relational/analyzer/Analysis.java         | 20 +++--
 .../relational/analyzer/StatementAnalyzer.java     |  3 +-
 .../plan/relational/planner/LogicalPlanner.java    | 16 ++--
 .../relational/planner/RelationalModelPlanner.java | 19 ++---
 .../plan/relational/sql/parser/AstBuilder.java     |  4 +-
 9 files changed, 223 insertions(+), 28 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/StatementMemorySourceVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/StatementMemorySourceVisitor.java
index 7a37902dbb9..20bce13a41b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/StatementMemorySourceVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/StatementMemorySourceVisitor.java
@@ -100,6 +100,10 @@ public class StatementMemorySourceVisitor
             new PlanGraphPrinter.GraphContext(
                 
context.getQueryContext().getTypeProvider().getTemplatedInfo()));
 
+    return getStatementMemorySource(header, lines);
+  }
+
+  static StatementMemorySource getStatementMemorySource(DatasetHeader header, 
List<String> lines) {
     TsBlockBuilder builder = new 
TsBlockBuilder(Collections.singletonList(TSDataType.TEXT));
     lines.forEach(
         line -> {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceContext.java
new file mode 100644
index 00000000000..a4b849fb385
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceContext.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.execution.memory;
+
+import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
+import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
+
+public class TableModelStatementMemorySourceContext {
+  private final MPPQueryContext queryContext;
+  private final Analysis analysis;
+
+  public TableModelStatementMemorySourceContext(MPPQueryContext queryContext, 
Analysis analysis) {
+    this.queryContext = queryContext;
+    this.analysis = analysis;
+  }
+
+  public MPPQueryContext getQueryContext() {
+    return queryContext;
+  }
+
+  public Analysis getAnalysis() {
+    return analysis;
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
new file mode 100644
index 00000000000..43cca971e2e
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.queryengine.plan.execution.memory;
+
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
+import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
+import org.apache.iotdb.db.queryengine.plan.analyze.ClusterPartitionFetcher;
+import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanGraphPrinter;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
+import 
org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.ExchangeNodeGenerator;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.block.TsBlock;
+
+import java.util.Collections;
+import java.util.List;
+
+import static 
org.apache.iotdb.db.queryengine.common.header.DatasetHeader.EMPTY_HEADER;
+import static 
org.apache.iotdb.db.queryengine.plan.execution.memory.StatementMemorySourceVisitor.getStatementMemorySource;
+
+public class TableModelStatementMemorySourceVisitor
+    extends AstVisitor<StatementMemorySource, 
TableModelStatementMemorySourceContext> {
+
+  @Override
+  public StatementMemorySource visitNode(
+      Node node, TableModelStatementMemorySourceContext context) {
+    DatasetHeader datasetHeader = context.getAnalysis().getRespDatasetHeader();
+    return new StatementMemorySource(
+        new TsBlock(0), datasetHeader == null ? EMPTY_HEADER : datasetHeader);
+  }
+
+  @Override
+  public StatementMemorySource visitExplain(
+      Explain node, TableModelStatementMemorySourceContext context) {
+    context.getAnalysis().setStatement(node.getStatement());
+    DatasetHeader header =
+        new DatasetHeader(
+            Collections.singletonList(
+                new ColumnHeader(IoTDBConstant.COLUMN_DISTRIBUTION_PLAN, 
TSDataType.TEXT)),
+            true);
+    LogicalQueryPlan logicalPlan =
+        new 
org.apache.iotdb.db.queryengine.plan.relational.planner.LogicalPlanner(
+                context.getQueryContext(),
+                LocalExecutionPlanner.getInstance().metadata,
+                context.getQueryContext().getSession(),
+                ClusterPartitionFetcher.getInstance(),
+                WarningCollector.NOOP)
+            .plan(context.getAnalysis());
+
+    // TODO(beyyes) adapt this logic after optimize ExchangeNodeAdder
+    ExchangeNodeGenerator.PlanContext exchangeContext =
+        new ExchangeNodeGenerator.PlanContext(context.getQueryContext());
+    List<PlanNode> distributedPlanNodeResult =
+        new ExchangeNodeGenerator().visitPlan(logicalPlan.getRootNode(), 
exchangeContext);
+
+    List<String> lines =
+        distributedPlanNodeResult
+            .get(0)
+            .accept(
+                new PlanGraphPrinter(),
+                new PlanGraphPrinter.GraphContext(
+                    
context.getQueryContext().getTypeProvider().getTemplatedInfo()));
+
+    return getStatementMemorySource(header, lines);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
index 308e2afd22f..232c12ba34f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java
@@ -66,6 +66,7 @@ import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.AggregationDe
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.CrossSeriesAggregationDescriptor;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.DeviceViewIntoPathDescriptor;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.IntoPathDescriptor;
+import 
org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode;
 
 import org.apache.commons.lang3.Validate;
 import org.apache.tsfile.utils.Pair;
@@ -598,6 +599,59 @@ public class PlanGraphPrinter extends 
PlanVisitor<List<String>, PlanGraphPrinter
     return render(node, boxValue, context);
   }
 
+  // =============== Methods below are used for table model ================
+  @Override
+  public List<String> visitTableScan(TableScanNode node, GraphContext context) 
{
+    List<String> boxValue = new ArrayList<>();
+    boxValue.add(String.format("TableScan-%s", node.getPlanNodeId().getId()));
+    boxValue.add(String.format("QualifiedTableName: %s", 
node.getQualifiedTableName()));
+    boxValue.add(String.format("OutputSymbols: %s", node.getOutputSymbols()));
+    boxValue.add(String.format("DeviceEntriesSize: %s", 
node.getDeviceEntries().size()));
+    boxValue.add(String.format("ScanOrder: %s", node.getScanOrder()));
+    if (node.getPushDownPredicate() != null) {
+      boxValue.add(String.format("PushDownPredicate: %s", 
node.getOutputSymbols()));
+    }
+    if (node.getPushDownOffset() > 0) {
+      boxValue.add(String.format("PushDownOffset: %s", 
node.getPushDownOffset()));
+    }
+    if (node.getPushDownLimit() > 0) {
+      boxValue.add(String.format("PushDownLimit: %s", 
node.getPushDownLimit()));
+    }
+    boxValue.add(String.format("RegionId: %s", 
node.getRegionReplicaSet().getRegionId().getId()));
+    return render(node, boxValue, context);
+  }
+
+  @Override
+  public List<String> visitFilter(
+      org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode 
node,
+      GraphContext context) {
+    List<String> boxValue = new ArrayList<>();
+    boxValue.add(String.format("Filter-%s", node.getPlanNodeId().getId()));
+    boxValue.add(String.format("Predicate: %s", node.getPredicate()));
+    return render(node, boxValue, context);
+  }
+
+  @Override
+  public List<String> visitProject(
+      org.apache.iotdb.db.queryengine.plan.relational.planner.node.ProjectNode 
node,
+      GraphContext context) {
+    List<String> boxValue = new ArrayList<>();
+    boxValue.add(String.format("Project-%s", node.getPlanNodeId().getId()));
+    boxValue.add(String.format("OutputSymbols: %s", node.getOutputSymbols()));
+    boxValue.add(String.format("Expressions: %s", 
node.getAssignments().getMap().values()));
+    return render(node, boxValue, context);
+  }
+
+  @Override
+  public List<String> visitOutput(
+      org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode 
node,
+      GraphContext context) {
+    List<String> boxValue = new ArrayList<>();
+    boxValue.add(String.format("Output-%s", node.getPlanNodeId().getId()));
+    boxValue.add(String.format("OutputSymbols: %s", node.getOutputSymbols()));
+    return render(node, boxValue, context);
+  }
+
   private String printRegion(TRegionReplicaSet regionReplicaSet) {
     return String.format(
         "Partition: %s",
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
index c4708ad1960..4d019248d86 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java
@@ -27,6 +27,8 @@ import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
 import org.apache.iotdb.db.queryengine.plan.analyze.IAnalysis;
 import 
org.apache.iotdb.db.queryengine.plan.execution.memory.StatementMemorySource;
+import 
org.apache.iotdb.db.queryengine.plan.execution.memory.TableModelStatementMemorySourceContext;
+import 
org.apache.iotdb.db.queryengine.plan.execution.memory.TableModelStatementMemorySourceVisitor;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.TimePredicate;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableSchema;
@@ -86,11 +88,10 @@ import static java.util.Collections.unmodifiableList;
 import static java.util.Collections.unmodifiableMap;
 import static java.util.Collections.unmodifiableSet;
 import static java.util.Objects.requireNonNull;
-import static 
org.apache.iotdb.db.queryengine.common.header.DatasetHeader.EMPTY_HEADER;
 
 public class Analysis implements IAnalysis {
 
-  @Nullable private final Statement root;
+  @Nullable private Statement root;
 
   private final Map<NodeRef<Parameter>, Expression> parameters;
 
@@ -269,6 +270,10 @@ public class Analysis implements IAnalysis {
     return getScope(root);
   }
 
+  public void setStatement(Statement statement) {
+    this.root = statement;
+  }
+
   public void setScope(Node node, Scope scope) {
     scopes.put(NodeRef.of(node), scope);
   }
@@ -614,11 +619,12 @@ public class Analysis implements IAnalysis {
 
   @Override
   public TsBlock constructResultForMemorySource(MPPQueryContext context) {
-    StatementMemorySource source =
-        new StatementMemorySource(
-            new TsBlock(0), respDatasetHeader == null ? EMPTY_HEADER : 
respDatasetHeader);
-    setRespDatasetHeader(source.getDatasetHeader());
-    return source.getTsBlock();
+    requireNonNull(getStatement(), "root statement is analysis is null");
+    StatementMemorySource memorySource =
+        new TableModelStatementMemorySourceVisitor()
+            .process(getStatement(), new 
TableModelStatementMemorySourceContext(context, this));
+    setRespDatasetHeader(memorySource.getDatasetHeader());
+    return memorySource.getTsBlock();
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index a15ed482daa..1fcc4e89024 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -359,7 +359,8 @@ public class StatementAnalyzer {
 
     @Override
     protected Scope visitExplain(Explain node, Optional<Scope> context) {
-      throw new SemanticException("Explain statement is not supported yet.");
+      analysis.setFinishQueryAfterAnalyze();
+      return visitQuery((Query) node.getStatement(), context);
     }
 
     @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
index 719ede30231..a7537c4e680 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LogicalPlanner.java
@@ -14,7 +14,6 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.planner;
 
-import org.apache.iotdb.commons.exception.IoTDBException;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
 import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
@@ -34,6 +33,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.Pru
 import 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.RelationalPlanOptimizer;
 import 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.RemoveRedundantIdentityProjections;
 import 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.SimplifyExpressions;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Query;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Statement;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Table;
@@ -84,7 +84,7 @@ public class LogicalPlanner {
             new IndexScan());
   }
 
-  public LogicalQueryPlan plan(Analysis analysis) throws IoTDBException {
+  public LogicalQueryPlan plan(Analysis analysis) {
     PlanNode planNode = planStatement(analysis, analysis.getStatement());
 
     relationalPlanOptimizers.forEach(
@@ -95,17 +95,19 @@ public class LogicalPlanner {
     return new LogicalQueryPlan(context, planNode);
   }
 
-  private PlanNode planStatement(Analysis analysis, Statement statement) 
throws IoTDBException {
+  private PlanNode planStatement(Analysis analysis, Statement statement) {
     return createOutputPlan(planStatementWithoutOutput(analysis, statement), 
analysis);
   }
 
-  private RelationPlan planStatementWithoutOutput(Analysis analysis, Statement 
statement)
-      throws IoTDBException {
+  private RelationPlan planStatementWithoutOutput(Analysis analysis, Statement 
statement) {
     if (statement instanceof Query) {
       return createRelationPlan(analysis, (Query) statement);
     }
-    throw new IoTDBException(
-        "Unsupported statement type " + statement.getClass().getSimpleName(), 
-1);
+    if (statement instanceof Explain) {
+      return createRelationPlan(analysis, (Query) ((Explain) 
statement).getStatement());
+    }
+    throw new IllegalStateException(
+        "Unsupported statement type: " + statement.getClass().getSimpleName());
   }
 
   private PlanNode createOutputPlan(RelationPlan plan, Analysis analysis) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationalModelPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationalModelPlanner.java
index b936555d401..60189c42f63 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationalModelPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/RelationalModelPlanner.java
@@ -24,7 +24,6 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.client.IClientManager;
 import 
org.apache.iotdb.commons.client.async.AsyncDataNodeInternalServiceClient;
 import org.apache.iotdb.commons.client.sync.SyncDataNodeInternalServiceClient;
-import org.apache.iotdb.commons.exception.IoTDBException;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.execution.QueryStateMachine;
 import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
@@ -108,17 +107,13 @@ public class RelationalModelPlanner implements IPlanner {
 
   @Override
   public LogicalQueryPlan doLogicalPlan(IAnalysis analysis, MPPQueryContext 
context) {
-    try {
-      return new LogicalPlanner(
-              context,
-              metadata,
-              context.getSession(),
-              ClusterPartitionFetcher.getInstance(),
-              warningCollector)
-          .plan((Analysis) analysis);
-    } catch (IoTDBException e) {
-      throw new RuntimeException(e);
-    }
+    return new LogicalPlanner(
+            context,
+            metadata,
+            context.getSession(),
+            ClusterPartitionFetcher.getInstance(),
+            warningCollector)
+        .plan((Analysis) analysis);
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index 02d98c5fac7..41e7fd6d33e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -50,6 +50,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropIndex;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropTable;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Except;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ExistsPredicate;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericDataType;
@@ -103,6 +104,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SimpleCaseExpress
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SimpleGroupBy;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SingleColumn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SortItem;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Statement;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SubqueryExpression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Table;
@@ -502,7 +504,7 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
 
   @Override
   public Node visitExplain(RelationalSqlParser.ExplainContext ctx) {
-    return super.visitExplain(ctx);
+    return new Explain(getLocation(ctx), (Statement) visit(ctx.query()));
   }
 
   @Override

Reply via email to