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 ********************