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

ycycse pushed a commit to branch ycy/supportEA
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/ycy/supportEA by this push:
     new 1e89595b948 support EXPLAIN ANALYZE in table model
1e89595b948 is described below

commit 1e89595b94842a6a06c216252c2a3e0189c250ee
Author: ycycse <[email protected]>
AuthorDate: Sun Nov 24 00:31:31 2024 +0800

    support EXPLAIN ANALYZE in table model
---
 .../plan/planner/TableOperatorGenerator.java       | 16 +++++++
 .../plan/planner/plan/node/ExplainAnalyzeNode.java | 11 +++++
 .../relational/analyzer/StatementAnalyzer.java     | 13 +++++-
 .../relational/planner/TableLogicalPlanner.java    | 53 ++++++++++++++++------
 .../plan/relational/planner/TableModelPlanner.java |  2 +-
 .../planner/distribute/AddExchangeNodes.java       | 34 ++++++++++----
 .../distribute/TableDistributedPlanGenerator.java  |  9 ++++
 .../distribute/TableDistributedPlanner.java        |  7 ++-
 .../distribute/TableModelQueryFragmentPlanner.java |  4 +-
 .../optimizations/UnaliasSymbolReferences.java     | 10 ++++
 .../plan/relational/sql/parser/AstBuilder.java     |  4 +-
 11 files changed, 136 insertions(+), 27 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
index d5d3327dbf9..24f7f424380 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
@@ -34,6 +34,7 @@ import 
org.apache.iotdb.db.queryengine.execution.exchange.sink.DownStreamChannel
 import org.apache.iotdb.db.queryengine.execution.exchange.sink.ISinkHandle;
 import 
org.apache.iotdb.db.queryengine.execution.exchange.sink.ShuffleSinkHandle;
 import org.apache.iotdb.db.queryengine.execution.exchange.source.ISourceHandle;
+import 
org.apache.iotdb.db.queryengine.execution.operator.ExplainAnalyzeOperator;
 import org.apache.iotdb.db.queryengine.execution.operator.Operator;
 import org.apache.iotdb.db.queryengine.execution.operator.OperatorContext;
 import 
org.apache.iotdb.db.queryengine.execution.operator.process.CollectOperator;
@@ -82,6 +83,7 @@ import 
org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggr
 import 
org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.StreamingHashAggregationOperator;
 import 
org.apache.iotdb.db.queryengine.execution.relational.ColumnTransformerBuilder;
 import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
+import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
@@ -1755,6 +1757,20 @@ public class TableOperatorGenerator extends 
PlanVisitor<Operator, LocalExecution
     return aggTableScanOperator;
   }
 
+  @Override
+  public Operator visitExplainAnalyze(ExplainAnalyzeNode node, 
LocalExecutionPlanContext context) {
+    Operator operator = node.getChild().accept(this, context);
+    OperatorContext operatorContext =
+        context
+            .getDriverContext()
+            .addOperatorContext(
+                context.getNextOperatorId(),
+                node.getPlanNodeId(),
+                ExplainAnalyzeOperator.class.getSimpleName());
+    return new ExplainAnalyzeOperator(
+        operatorContext, operator, node.getQueryId(), node.isVerbose(), 
node.getTimeout());
+  }
+
   private boolean[] checkStatisticAndScanOrder(AggregationTableScanNode node) {
     boolean canUseStatistic = true;
     int ascendingCount = 0, descendingCount = 0;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/ExplainAnalyzeNode.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/ExplainAnalyzeNode.java
index c831e41c1f9..c9e9709eccc 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/ExplainAnalyzeNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/ExplainAnalyzeNode.java
@@ -21,6 +21,7 @@ package 
org.apache.iotdb.db.queryengine.plan.planner.plan.node;
 
 import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
+import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
 
 import org.apache.tsfile.utils.ReadWriteIOUtils;
 
@@ -59,6 +60,16 @@ public class ExplainAnalyzeNode extends 
SingleChildProcessNode {
     return Collections.singletonList(ColumnHeaderConstant.EXPLAIN_ANALYZE);
   }
 
+  @Override
+  public List<Symbol> getOutputSymbols() {
+    return 
Collections.singletonList(Symbol.of(ColumnHeaderConstant.EXPLAIN_ANALYZE));
+  }
+
+  @Override
+  public PlanNode replaceChildren(List<PlanNode> newChildren) {
+    return new ExplainAnalyzeNode(getPlanNodeId(), newChildren.get(0), 
verbose, queryId, timeout);
+  }
+
   @Override
   protected void serializeAttributes(ByteBuffer byteBuffer) {
     PlanNodeType.EXPLAIN_ANALYZE.serialize(byteBuffer);
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 e7438a8c82c..387a9b9feb7 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
@@ -25,6 +25,9 @@ import 
org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
 import org.apache.iotdb.db.exception.sql.SemanticException;
 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;
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
 import org.apache.iotdb.db.queryengine.execution.warnings.IoTDBWarning;
 import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
 import org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeUtils;
@@ -152,11 +155,13 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Streams;
+import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.read.common.type.RowType;
 import org.apache.tsfile.read.common.type.Type;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -585,7 +590,13 @@ public class StatementAnalyzer {
 
     @Override
     protected Scope visitExplainAnalyze(ExplainAnalyze node, Optional<Scope> 
context) {
-      throw new SemanticException("Explain Analyze statement is not supported 
yet.");
+      queryContext.setExplainAnalyze(true);
+      analysis.setRespDatasetHeader(
+          new DatasetHeader(
+              Collections.singletonList(
+                  new ColumnHeader(ColumnHeaderConstant.EXPLAIN_ANALYZE, 
TSDataType.TEXT, null)),
+              true));
+      return visitQuery((Query) node.getStatement(), context);
     }
 
     @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java
index 5eb25278a67..c659ca3a3bc 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java
@@ -20,10 +20,12 @@ import 
org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.QueryId;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
 import org.apache.iotdb.db.queryengine.common.header.ColumnHeader;
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
 import org.apache.iotdb.db.queryengine.common.header.DatasetHeader;
 import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
 import org.apache.iotdb.db.queryengine.metric.QueryPlanCostMetricSet;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan;
+import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.WritePlanNode;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.CountSchemaMergeNode;
@@ -48,6 +50,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AbstractTraverseD
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateOrUpdateDevice;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ExplainAnalyze;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FetchDevice;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LoadTsFile;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.PipeEnriched;
@@ -61,6 +64,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import org.apache.tsfile.enums.TSDataType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -140,7 +144,7 @@ public class TableLogicalPlanner {
     final Statement statement = analysis.getStatement();
     PlanNode planNode = planStatement(analysis, statement);
 
-    if (statement instanceof Query) {
+    if (statement instanceof Query || statement instanceof ExplainAnalyze) {
       QueryPlanCostMetricSet.getInstance()
           .recordPlanCost(TABLE_TYPE, LOGICAL_PLANNER, System.nanoTime() - 
startTime);
       startTime = System.nanoTime();
@@ -202,6 +206,9 @@ public class TableLogicalPlanner {
     if (statement instanceof PipeEnriched) {
       return createRelationPlan(analysis, (PipeEnriched) statement);
     }
+    if (statement instanceof ExplainAnalyze) {
+      return planExplainAnalyze((ExplainAnalyze) statement, analysis);
+    }
     throw new IllegalStateException(
         "Unsupported statement type: " + statement.getClass().getSimpleName());
   }
@@ -216,18 +223,24 @@ public class TableLogicalPlanner {
 
     int columnNumber = 0;
     // TODO perfect the logic of outputDescriptor
-    RelationType outputDescriptor = analysis.getOutputDescriptor();
-    for (Field field : outputDescriptor.getVisibleFields()) {
-      String name = field.getName().orElse("_col" + columnNumber);
-
-      names.add(name);
-      int fieldIndex = outputDescriptor.indexOf(field);
-      Symbol symbol = plan.getSymbol(fieldIndex);
-      outputs.add(symbol);
-
-      columnHeaders.add(new ColumnHeader(name, 
getTSDataType(field.getType())));
-
-      columnNumber++;
+    if (queryContext.isExplainAnalyze()) {
+      outputs.add(new Symbol(ColumnHeaderConstant.EXPLAIN_ANALYZE));
+      names.add("Explain Analyze");
+      columnHeaders.add(new ColumnHeader("Explain Analyze", TSDataType.TEXT));
+    } else {
+      RelationType outputDescriptor = analysis.getOutputDescriptor();
+      for (Field field : outputDescriptor.getVisibleFields()) {
+        String name = field.getName().orElse("_col" + columnNumber);
+
+        names.add(name);
+        int fieldIndex = outputDescriptor.indexOf(field);
+        Symbol symbol = plan.getSymbol(fieldIndex);
+        outputs.add(symbol);
+
+        columnHeaders.add(new ColumnHeader(name, 
getTSDataType(field.getType())));
+
+        columnNumber++;
+      }
     }
 
     OutputNode outputNode =
@@ -417,6 +430,20 @@ public class TableLogicalPlanner {
     }
   }
 
+  private RelationPlan planExplainAnalyze(final ExplainAnalyze statement, 
final Analysis analysis) {
+    RelationPlan originalQueryPlan =
+        createRelationPlan(analysis, (Query) (statement.getStatement()));
+    PlanNode newRoot =
+        new ExplainAnalyzeNode(
+            queryContext.getQueryId().genPlanNodeId(),
+            originalQueryPlan.getRoot(),
+            statement.isVerbose(),
+            queryContext.getLocalQueryId(),
+            queryContext.getTimeOut());
+    return new RelationPlan(
+        newRoot, originalQueryPlan.getScope(), 
originalQueryPlan.getFieldMappings());
+  }
+
   private enum Stage {
     CREATED,
     OPTIMIZED,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableModelPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableModelPlanner.java
index 1b891dead32..2f471990b58 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableModelPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableModelPlanner.java
@@ -168,7 +168,7 @@ public class TableModelPlanner implements IPlanner {
 
   @Override
   public ScheduledExecutorService getScheduledExecutorService() {
-    return null;
+    return scheduledExecutor;
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/AddExchangeNodes.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/AddExchangeNodes.java
index 622c93d74bd..03e84d69982 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/AddExchangeNodes.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/AddExchangeNodes.java
@@ -22,6 +22,7 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.planner.distribute;
 import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import 
org.apache.iotdb.db.queryengine.plan.planner.distribution.NodeDistribution;
+import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.WritePlanNode;
@@ -58,14 +59,14 @@ public class AddExchangeNodes
     PlanNode newNode = node.clone();
     if (node.getChildren().size() == 1) {
       newNode.addChild(node.getChildren().get(0).accept(this, context));
-      context.nodeDistributionMap.put(
-          node.getPlanNodeId(),
-          new NodeDistribution(
-              SAME_WITH_ALL_CHILDREN,
-              context
-                  .nodeDistributionMap
-                  .get(node.getChildren().get(0).getPlanNodeId())
-                  .getRegion()));
+      // Explain Analyze doesn't have region info, this may be solved by a 
local RegionReplicaSet
+      NodeDistribution childRegion =
+          
context.nodeDistributionMap.get(node.getChildren().get(0).getPlanNodeId());
+      if (childRegion != null) {
+        context.nodeDistributionMap.put(
+            node.getPlanNodeId(),
+            new NodeDistribution(SAME_WITH_ALL_CHILDREN, 
childRegion.getRegion()));
+      }
       return newNode;
     }
 
@@ -120,6 +121,23 @@ public class AddExchangeNodes
     return processTableDeviceSourceNode(node, context);
   }
 
+  @Override
+  public PlanNode visitExplainAnalyze(
+      ExplainAnalyzeNode node, TableDistributedPlanGenerator.PlanContext 
context) {
+    ExplainAnalyzeNode newNode = (ExplainAnalyzeNode) node.clone();
+
+    PlanNode child = newNode.getChild();
+    child = child.accept(this, context);
+
+    ExchangeNode exchangeNode = new 
ExchangeNode(queryContext.getQueryId().genPlanNodeId());
+    exchangeNode.setChild(child);
+    exchangeNode.setOutputSymbols(child.getOutputSymbols());
+    newNode.setChild(exchangeNode);
+
+    context.hasExchangeNode = true;
+    return newNode;
+  }
+
   private PlanNode processTableDeviceSourceNode(
       final TableDeviceSourceNode node, final 
TableDistributedPlanGenerator.PlanContext context) {
     context.nodeDistributionMap.put(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
index 6c1becfcc9c..ca4e7765480 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanGenerator.java
@@ -21,7 +21,9 @@ import 
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
 import org.apache.iotdb.commons.utils.PathUtils;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.QueryId;
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
 import 
org.apache.iotdb.db.queryengine.plan.planner.distribution.NodeDistribution;
+import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
@@ -60,6 +62,7 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
 import com.google.common.collect.ImmutableSet;
 import org.apache.tsfile.common.conf.TSFileConfig;
 import org.apache.tsfile.file.metadata.IDeviceID;
+import org.apache.tsfile.read.common.type.StringType;
 import org.apache.tsfile.utils.Pair;
 
 import javax.annotation.Nonnull;
@@ -156,6 +159,12 @@ public class TableDistributedPlanGenerator
     return Collections.singletonList(node);
   }
 
+  @Override
+  public List<PlanNode> visitExplainAnalyze(ExplainAnalyzeNode node, 
PlanContext context) {
+    symbolAllocator.newSymbol(ColumnHeaderConstant.EXPLAIN_ANALYZE, 
StringType.getInstance());
+    return visitPlan(node, context);
+  }
+
   @Override
   public List<PlanNode> visitFill(FillNode node, PlanContext context) {
     if (!(node instanceof ValueFillNode)) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanner.java
index 14c50cb3937..7e2acc85165 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableDistributedPlanner.java
@@ -35,6 +35,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.planner.SymbolAllocator;
 import org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode;
 import 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.DistributedOptimizeFactory;
 import 
org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.PlanOptimizer;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ExplainAnalyze;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Query;
 import 
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager;
 
@@ -85,7 +86,8 @@ public class TableDistributedPlanner {
         new TableDistributedPlanGenerator.PlanContext();
     PlanNode outputNodeWithExchange = 
generateDistributedPlanWithOptimize(planContext);
 
-    if (analysis.getStatement() instanceof Query) {
+    if (analysis.getStatement() instanceof Query
+        || analysis.getStatement() instanceof ExplainAnalyze) {
       analysis
           .getRespDatasetHeader()
           .setTableColumnToTsBlockIndexMap((OutputNode) 
outputNodeWithExchange);
@@ -113,7 +115,8 @@ public class TableDistributedPlanner {
     // distribute plan optimize rule
     PlanNode distributedPlan = distributedPlanResult.get(0);
 
-    if (analysis.getStatement() instanceof Query) {
+    if (analysis.getStatement() instanceof Query
+        || analysis.getStatement() instanceof ExplainAnalyze) {
       for (PlanOptimizer optimizer : optimizers) {
         distributedPlan =
             optimizer.optimize(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
index b2f8334b4f8..aaa3fe8f5fb 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/TableModelQueryFragmentPlanner.java
@@ -33,6 +33,7 @@ import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.ExchangeNo
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.sink.MultiChildrenSinkNode;
 import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ExplainAnalyze;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Query;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDevice;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Statement;
@@ -104,7 +105,7 @@ public class TableModelQueryFragmentPlanner {
             QueryType.READ,
             queryContext.getTimeOut(),
             queryContext.getSession(),
-            false,
+            queryContext.isExplainAnalyze(),
             fragment.isRoot());
 
     // Get the target region for origin PlanFragment, then its instance will 
be distributed one
@@ -143,6 +144,7 @@ public class TableModelQueryFragmentPlanner {
 
     final Statement statement = analysis.getStatement();
     if (statement instanceof Query
+        || statement instanceof ExplainAnalyze
         || statement instanceof ShowDevice
         || statement instanceof CountDevice) {
       
fragmentInstance.getFragment().generateTableModelTypeProvider(queryContext.getTypeProvider());
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/UnaliasSymbolReferences.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/UnaliasSymbolReferences.java
index cbf6bbf90e7..a325f9a974f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/UnaliasSymbolReferences.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/UnaliasSymbolReferences.java
@@ -13,6 +13,7 @@
  */
 package org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations;
 
+import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema;
@@ -265,6 +266,15 @@ public class UnaliasSymbolReferences implements 
PlanOptimizer {
           rewrittenSource.getMappings());
     }
 
+    @Override
+    public PlanAndMappings visitExplainAnalyze(ExplainAnalyzeNode node, 
UnaliasContext context) {
+      PlanAndMappings rewrittenSource = node.getChild().accept(this, context);
+
+      return new PlanAndMappings(
+          node.replaceChildren(ImmutableList.of(rewrittenSource.getRoot())),
+          rewrittenSource.getMappings());
+    }
+
     @Override
     public PlanAndMappings visitLimit(LimitNode node, UnaliasContext context) {
       PlanAndMappings rewrittenSource = node.getChild().accept(this, context);
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 d7f5abb27c9..6e83e9d2399 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
@@ -68,6 +68,7 @@ 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.ExplainAnalyze;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Fill;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Flush;
@@ -1066,7 +1067,8 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
 
   @Override
   public Node visitExplainAnalyze(RelationalSqlParser.ExplainAnalyzeContext 
ctx) {
-    return super.visitExplainAnalyze(ctx);
+    return new ExplainAnalyze(
+        getLocation(ctx), ctx.VERBOSE() != null, (Statement) 
visit(ctx.query()));
   }
 
   // ********************** query expressions ********************

Reply via email to