You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by er...@apache.org on 2022/07/11 08:54:29 UTC
[iotdb] 01/01: Refine Analyzer and LogicalPlanner
This is an automated email from the ASF dual-hosted git repository.
ericpai pushed a commit to branch improve/code-refine
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 42769b8f40c5de09e082efca0a950c653f03adad
Author: ericpai <er...@hotmail.com>
AuthorDate: Mon Jul 11 16:54:11 2022 +0800
Refine Analyzer and LogicalPlanner
---
.../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java | 1464 ++++++++++++++++++++
.../apache/iotdb/db/mpp/plan/analyze/Analyzer.java | 1450 +------------------
.../db/mpp/plan/planner/LogicalPlanVisitor.java | 679 +++++++++
.../iotdb/db/mpp/plan/planner/LogicalPlanner.java | 655 ---------
4 files changed, 2145 insertions(+), 2103 deletions(-)
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
new file mode 100644
index 0000000000..83554d8ccb
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -0,0 +1,1464 @@
+/*
+ * 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.analyze;
+
+import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
+import org.apache.iotdb.common.rpc.thrift.TSeriesPartitionSlot;
+import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.partition.DataPartition;
+import org.apache.iotdb.commons.partition.DataPartitionQueryParam;
+import org.apache.iotdb.commons.partition.SchemaNodeManagementPartition;
+import org.apache.iotdb.commons.partition.SchemaPartition;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.sql.MeasurementNotExistException;
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.exception.sql.StatementAnalyzeException;
+import org.apache.iotdb.db.metadata.path.MeasurementPath;
+import org.apache.iotdb.db.mpp.common.MPPQueryContext;
+import org.apache.iotdb.db.mpp.common.header.ColumnHeader;
+import org.apache.iotdb.db.mpp.common.header.DatasetHeader;
+import org.apache.iotdb.db.mpp.common.header.HeaderConstant;
+import org.apache.iotdb.db.mpp.common.schematree.DeviceSchemaInfo;
+import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
+import org.apache.iotdb.db.mpp.common.schematree.SchemaTree;
+import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
+import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
+import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.FillDescriptor;
+import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.FilterNullParameter;
+import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.GroupByTimeParameter;
+import org.apache.iotdb.db.mpp.plan.statement.Statement;
+import org.apache.iotdb.db.mpp.plan.statement.StatementNode;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.db.mpp.plan.statement.component.FillComponent;
+import org.apache.iotdb.db.mpp.plan.statement.component.GroupByTimeComponent;
+import org.apache.iotdb.db.mpp.plan.statement.component.OrderBy;
+import org.apache.iotdb.db.mpp.plan.statement.component.ResultColumn;
+import org.apache.iotdb.db.mpp.plan.statement.crud.DeleteDataStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertMultiTabletsStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsOfOneDeviceStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertTabletStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
+import org.apache.iotdb.db.mpp.plan.statement.internal.InternalCreateTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.internal.LastPointFetchStatement;
+import org.apache.iotdb.db.mpp.plan.statement.internal.SchemaFetchStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.AlterTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountDevicesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountStorageGroupStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildNodesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildPathsStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowClusterStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDevicesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
+import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
+import org.apache.iotdb.db.mpp.plan.statement.sys.ShowVersionStatement;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.filter.GroupByFilter;
+import org.apache.iotdb.tsfile.read.filter.GroupByMonthFilter;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
+import org.apache.iotdb.tsfile.read.filter.factory.FilterFactory;
+import org.apache.iotdb.tsfile.utils.Pair;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.stream.Collectors;
+
+import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_RESULT_NODES;
+
+/** This visitor is used to analyze each type of Statement and returns the {@link Analysis}. */
+public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> {
+
+ private static final Logger logger = LoggerFactory.getLogger(Analyzer.class);
+
+ private final IPartitionFetcher partitionFetcher;
+ private final ISchemaFetcher schemaFetcher;
+ private final TypeProvider typeProvider;
+ private final MPPQueryContext context;
+
+ public AnalyzeVisitor(
+ IPartitionFetcher partitionFetcher,
+ ISchemaFetcher schemaFetcher,
+ TypeProvider typeProvider,
+ MPPQueryContext context) {
+ this.context = context;
+ this.partitionFetcher = partitionFetcher;
+ this.schemaFetcher = schemaFetcher;
+ this.typeProvider = typeProvider;
+ }
+
+ private String getLogHeader() {
+ return String.format("Query[%s]:", context.getQueryId());
+ }
+
+ @Override
+ public Analysis visitNode(StatementNode node, MPPQueryContext context) {
+ throw new UnsupportedOperationException(
+ "Unsupported statement type: " + node.getClass().getName());
+ }
+
+ @Override
+ public Analysis visitExplain(ExplainStatement explainStatement, MPPQueryContext context) {
+ Analysis analysis = visitQuery(explainStatement.getQueryStatement(), context);
+ analysis.setStatement(explainStatement);
+ analysis.setFinishQueryAfterAnalyze(true);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitQuery(QueryStatement queryStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ try {
+ // check for semantic errors
+ queryStatement.semanticCheck();
+
+ // concat path and construct path pattern tree
+ PathPatternTree patternTree = new PathPatternTree();
+ queryStatement =
+ (QueryStatement) new ConcatPathRewriter().rewrite(queryStatement, patternTree);
+ analysis.setStatement(queryStatement);
+
+ // request schema fetch API
+ logger.info("{} fetch query schema...", getLogHeader());
+ SchemaTree schemaTree = schemaFetcher.fetchSchema(patternTree);
+ logger.info("{} fetch schema done", getLogHeader());
+ // If there is no leaf node in the schema tree, the query should be completed immediately
+ if (schemaTree.isEmpty()) {
+ analysis.setFinishQueryAfterAnalyze(true);
+ return analysis;
+ }
+
+ // extract global time filter from query filter and determine if there is a value filter
+ Pair<Filter, Boolean> resultPair = analyzeGlobalTimeFilter(queryStatement);
+ Filter globalTimeFilter = resultPair.left;
+ boolean hasValueFilter = resultPair.right;
+ analysis.setGlobalTimeFilter(globalTimeFilter);
+ analysis.setHasValueFilter(hasValueFilter);
+
+ if (queryStatement.isLastQuery()) {
+ if (hasValueFilter) {
+ throw new SemanticException("Only time filters are supported in LAST query");
+ }
+
+ return analyzeLast(analysis, schemaTree.getAllMeasurement(), schemaTree);
+ }
+
+ // Example 1: select s1, s1 + s2 as t, udf(udf(s1)) from root.sg.d1
+ // outputExpressions: [<root.sg.d1.s1,null>, <root.sg.d1.s1 + root.sg.d1.s2,t>,
+ // <udf(udf(root.sg.d1.s1)),null>]
+ // transformExpressions: [root.sg.d1.s1, root.sg.d1.s1 + root.sg.d1.s2,
+ // udf(udf(root.sg.d1.s1))]
+ // sourceExpressions: {root.sg.d1 -> [root.sg.d1.s1, root.sg.d1.s2]}
+ //
+ // Example 2: select s1, s2, s3 as t from root.sg.* align by device
+ // outputExpressions: [<s1,null>, <s2,null>, <s1,t>]
+ // transformExpressions: [root.sg.d1.s1, root.sg.d1.s2, root.sg.d1.s3,
+ // root.sg.d2.s1, root.sg.d2.s2]
+ // sourceExpressions: {root.sg.d1 -> [root.sg.d1.s1, root.sg.d1.s2, root.sg.d1.s2],
+ // root.sg.d2 -> [root.sg.d2.s1, root.sg.d2.s2]}
+ //
+ // Example 3: select sum(s1) + 1 as t, count(s2) from root.sg.d1
+ // outputExpressions: [<sum(root.sg.d1.s1) + 1,t>, <count(root.sg.d1.s2),t>]
+ // transformExpressions: [sum(root.sg.d1.s1) + 1, count(root.sg.d1.s2)]
+ // aggregationExpressions: {root.sg.d1 -> [sum(root.sg.d1.s1), count(root.sg.d1.s2)]}
+ // sourceExpressions: {root.sg.d1 -> [sum(root.sg.d1.s1), count(root.sg.d1.s2)]}
+ //
+ // Example 4: select sum(s1) + 1 as t, count(s2) from root.sg.d1 where s1 > 1
+ // outputExpressions: [<sum(root.sg.d1.s1) + 1,t>, <count(root.sg.d1.s2),t>]
+ // transformExpressions: [sum(root.sg.d1.s1) + 1, count(root.sg.d1.s2)]
+ // aggregationExpressions: {root.sg.d1 -> [sum(root.sg.d1.s1), count(root.sg.d1.s2)]}
+ // sourceExpressions: {root.sg.d1 -> [root.sg.d1.s1, root.sg.d1.s2]}
+ List<Pair<Expression, String>> outputExpressions;
+ if (queryStatement.isAlignByDevice()) {
+ Map<String, Set<Expression>> deviceToTransformExpressions = new HashMap<>();
+
+ // all selected device
+ Set<PartialPath> deviceList = analyzeFrom(queryStatement, schemaTree);
+
+ Map<String, Set<String>> deviceToMeasurementsMap = new HashMap<>();
+ outputExpressions =
+ analyzeSelect(
+ queryStatement,
+ schemaTree,
+ deviceList,
+ deviceToTransformExpressions,
+ deviceToMeasurementsMap);
+
+ Map<String, List<Integer>> deviceToMeasurementIndexesMap = new HashMap<>();
+ List<String> allMeasurements =
+ outputExpressions.stream()
+ .map(Pair::getLeft)
+ .map(Expression::getExpressionString)
+ .distinct()
+ .collect(Collectors.toList());
+ for (String deviceName : deviceToMeasurementsMap.keySet()) {
+ List<String> measurementsUnderDevice =
+ new ArrayList<>(deviceToMeasurementsMap.get(deviceName));
+ List<Integer> indexes = new ArrayList<>();
+ for (String measurement : measurementsUnderDevice) {
+ indexes.add(
+ allMeasurements.indexOf(measurement) + 1); // add 1 to skip the device column
+ }
+ deviceToMeasurementIndexesMap.put(deviceName, indexes);
+ }
+ analysis.setDeviceToMeasurementIndexesMap(deviceToMeasurementIndexesMap);
+
+ Map<String, Set<Expression>> deviceToSourceExpressions = new HashMap<>();
+ boolean isValueFilterAggregation = queryStatement.isAggregationQuery() && hasValueFilter;
+
+ Map<String, Boolean> deviceToIsRawDataSource = new HashMap<>();
+
+ Map<String, Set<Expression>> deviceToAggregationExpressions = new HashMap<>();
+ Map<String, Set<Expression>> deviceToAggregationTransformExpressions = new HashMap<>();
+ for (String deviceName : deviceToTransformExpressions.keySet()) {
+ Set<Expression> transformExpressions = deviceToTransformExpressions.get(deviceName);
+ Set<Expression> aggregationExpressions = new LinkedHashSet<>();
+ Set<Expression> aggregationTransformExpressions = new LinkedHashSet<>();
+
+ boolean isHasRawDataInputAggregation = false;
+ if (queryStatement.isAggregationQuery()) {
+ // true if nested expressions and UDFs exist in aggregation function
+ // i.e. select sum(s1 + 1) from root.sg.d1 align by device
+ isHasRawDataInputAggregation =
+ analyzeAggregation(
+ transformExpressions, aggregationExpressions, aggregationTransformExpressions);
+ deviceToAggregationExpressions.put(deviceName, aggregationExpressions);
+ deviceToAggregationTransformExpressions.put(
+ deviceName, aggregationTransformExpressions);
+ }
+
+ boolean isRawDataSource =
+ !queryStatement.isAggregationQuery()
+ || isValueFilterAggregation
+ || isHasRawDataInputAggregation;
+
+ for (Expression expression : transformExpressions) {
+ updateSource(
+ expression,
+ deviceToSourceExpressions.computeIfAbsent(deviceName, key -> new LinkedHashSet<>()),
+ isRawDataSource);
+ }
+ deviceToIsRawDataSource.put(deviceName, isRawDataSource);
+ }
+ analysis.setDeviceToAggregationExpressions(deviceToAggregationExpressions);
+ analysis.setDeviceToAggregationTransformExpressions(
+ deviceToAggregationTransformExpressions);
+ analysis.setDeviceToIsRawDataSource(deviceToIsRawDataSource);
+
+ if (queryStatement.getWhereCondition() != null) {
+ Map<String, Expression> deviceToQueryFilter = new HashMap<>();
+ Iterator<PartialPath> deviceIterator = deviceList.iterator();
+ while (deviceIterator.hasNext()) {
+ PartialPath devicePath = deviceIterator.next();
+ Expression queryFilter = null;
+ try {
+ queryFilter = analyzeWhereSplitByDevice(queryStatement, devicePath, schemaTree);
+ } catch (SemanticException e) {
+ if (e instanceof MeasurementNotExistException) {
+ logger.warn(e.getMessage());
+ deviceIterator.remove();
+ deviceToSourceExpressions.remove(devicePath.getFullPath());
+ continue;
+ }
+ throw e;
+ }
+ deviceToQueryFilter.put(devicePath.getFullPath(), queryFilter);
+ queryFilter.inferTypes(typeProvider);
+ updateSource(
+ queryFilter,
+ deviceToSourceExpressions.computeIfAbsent(
+ devicePath.getFullPath(), key -> new LinkedHashSet<>()),
+ true);
+ }
+ analysis.setDeviceToQueryFilter(deviceToQueryFilter);
+ }
+ analysis.setDeviceToSourceExpressions(deviceToSourceExpressions);
+ analysis.setDeviceToTransformExpressions(deviceToTransformExpressions);
+ } else {
+ outputExpressions = analyzeSelect(queryStatement, schemaTree);
+ Set<Expression> transformExpressions =
+ outputExpressions.stream()
+ .map(Pair::getLeft)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+
+ if (queryStatement.isGroupByLevel()) {
+ // map from grouped expression to set of input expressions
+ Map<Expression, Expression> rawPathToGroupedPathMap = new HashMap<>();
+ Map<Expression, Set<Expression>> groupByLevelExpressions =
+ analyzeGroupByLevel(
+ queryStatement, outputExpressions, transformExpressions, rawPathToGroupedPathMap);
+ analysis.setGroupByLevelExpressions(groupByLevelExpressions);
+ analysis.setRawPathToGroupedPathMap(rawPathToGroupedPathMap);
+ }
+
+ // true if nested expressions and UDFs exist in aggregation function
+ // i.e. select sum(s1 + 1) from root.sg.d1
+ boolean isHasRawDataInputAggregation = false;
+ if (queryStatement.isAggregationQuery()) {
+ Set<Expression> aggregationExpressions = new HashSet<>();
+ Set<Expression> aggregationTransformExpressions = new HashSet<>();
+ isHasRawDataInputAggregation =
+ analyzeAggregation(
+ transformExpressions, aggregationExpressions, aggregationTransformExpressions);
+ analysis.setAggregationExpressions(aggregationExpressions);
+ analysis.setAggregationTransformExpressions(aggregationTransformExpressions);
+ }
+
+ // generate sourceExpression according to transformExpressions
+ Set<Expression> sourceExpressions = new HashSet<>();
+ boolean isValueFilterAggregation = queryStatement.isAggregationQuery() && hasValueFilter;
+ boolean isRawDataSource =
+ !queryStatement.isAggregationQuery()
+ || isValueFilterAggregation
+ || isHasRawDataInputAggregation;
+ for (Expression expression : transformExpressions) {
+ updateSource(expression, sourceExpressions, isRawDataSource);
+ }
+
+ if (queryStatement.getWhereCondition() != null) {
+ Expression queryFilter = analyzeWhere(queryStatement, schemaTree);
+
+ // update sourceExpression according to queryFilter
+ queryFilter.inferTypes(typeProvider);
+ updateSource(queryFilter, sourceExpressions, isRawDataSource);
+ analysis.setQueryFilter(queryFilter);
+ }
+ analysis.setRawDataSource(isRawDataSource);
+ analysis.setSourceExpressions(sourceExpressions);
+ analysis.setTransformExpressions(transformExpressions);
+ }
+
+ if (queryStatement.isGroupByTime()) {
+ GroupByTimeComponent groupByTimeComponent = queryStatement.getGroupByTimeComponent();
+ if ((groupByTimeComponent.isIntervalByMonth()
+ || groupByTimeComponent.isSlidingStepByMonth())
+ && queryStatement.getResultOrder() == OrderBy.TIMESTAMP_DESC) {
+ throw new SemanticException("Group by month doesn't support order by time desc now.");
+ }
+ analysis.setGroupByTimeParameter(new GroupByTimeParameter(groupByTimeComponent));
+ }
+
+ if (queryStatement.getFilterNullComponent() != null) {
+ FilterNullParameter filterNullParameter = new FilterNullParameter();
+ filterNullParameter.setFilterNullPolicy(
+ queryStatement.getFilterNullComponent().getWithoutPolicyType());
+ List<Expression> resultFilterNullColumns;
+ if (queryStatement.isAlignByDevice()) {
+ resultFilterNullColumns =
+ analyzeWithoutNullAlignByDevice(
+ queryStatement,
+ outputExpressions.stream().map(Pair::getLeft).collect(Collectors.toSet()));
+ } else {
+ resultFilterNullColumns =
+ analyzeWithoutNull(queryStatement, schemaTree, analysis.getTransformExpressions());
+ }
+ filterNullParameter.setFilterNullColumns(resultFilterNullColumns);
+ analysis.setFilterNullParameter(filterNullParameter);
+ }
+
+ if (queryStatement.getFillComponent() != null) {
+ FillComponent fillComponent = queryStatement.getFillComponent();
+ List<Expression> fillColumnList =
+ outputExpressions.stream().map(Pair::getLeft).distinct().collect(Collectors.toList());
+ analysis.setFillDescriptor(
+ new FillDescriptor(fillComponent.getFillPolicy(), fillComponent.getFillValue()));
+ }
+
+ // generate result set header according to output expressions
+ DatasetHeader datasetHeader = analyzeOutput(queryStatement, outputExpressions);
+ analysis.setRespDatasetHeader(datasetHeader);
+ analysis.setTypeProvider(typeProvider);
+
+ // fetch partition information
+ Set<String> deviceSet = new HashSet<>();
+ if (queryStatement.isAlignByDevice()) {
+ deviceSet = analysis.getDeviceToSourceExpressions().keySet();
+ } else {
+ for (Expression expression : analysis.getSourceExpressions()) {
+ deviceSet.add(ExpressionAnalyzer.getDeviceNameInSourceExpression(expression));
+ }
+ }
+ DataPartition dataPartition = fetchDataPartitionByDevices(deviceSet, schemaTree);
+ analysis.setDataPartitionInfo(dataPartition);
+ } catch (StatementAnalyzeException e) {
+ logger.error("Meet error when analyzing the query statement: ", e);
+ throw new StatementAnalyzeException(
+ "Meet error when analyzing the query statement: " + e.getMessage());
+ }
+ return analysis;
+ }
+
+ private List<Pair<Expression, String>> analyzeSelect(
+ QueryStatement queryStatement, SchemaTree schemaTree) {
+ List<Pair<Expression, String>> outputExpressions = new ArrayList<>();
+ ColumnPaginationController paginationController =
+ new ColumnPaginationController(
+ queryStatement.getSeriesLimit(),
+ queryStatement.getSeriesOffset(),
+ queryStatement.isLastQuery() || queryStatement.isGroupByLevel());
+
+ for (ResultColumn resultColumn : queryStatement.getSelectComponent().getResultColumns()) {
+ boolean hasAlias = resultColumn.hasAlias();
+ List<Expression> resultExpressions =
+ ExpressionAnalyzer.removeWildcardInExpression(resultColumn.getExpression(), schemaTree);
+ if (hasAlias && !queryStatement.isGroupByLevel() && resultExpressions.size() > 1) {
+ throw new SemanticException(
+ String.format(
+ "alias '%s' can only be matched with one time series", resultColumn.getAlias()));
+ }
+ for (Expression expression : resultExpressions) {
+ if (paginationController.hasCurOffset()) {
+ paginationController.consumeOffset();
+ continue;
+ }
+ if (paginationController.hasCurLimit()) {
+ Expression expressionWithoutAlias =
+ ExpressionAnalyzer.removeAliasFromExpression(expression);
+ String alias =
+ !Objects.equals(expressionWithoutAlias, expression)
+ ? expression.getExpressionString()
+ : null;
+ alias = hasAlias ? resultColumn.getAlias() : alias;
+ outputExpressions.add(new Pair<>(expressionWithoutAlias, alias));
+ if (queryStatement.isGroupByLevel()
+ && resultColumn.getExpression() instanceof FunctionExpression) {
+ queryStatement
+ .getGroupByLevelComponent()
+ .updateIsCountStar((FunctionExpression) resultColumn.getExpression());
+ }
+ ExpressionAnalyzer.updateTypeProvider(expressionWithoutAlias, typeProvider);
+ expressionWithoutAlias.inferTypes(typeProvider);
+ paginationController.consumeLimit();
+ } else {
+ break;
+ }
+ }
+ }
+ return outputExpressions;
+ }
+
+ private Set<PartialPath> analyzeFrom(QueryStatement queryStatement, SchemaTree schemaTree) {
+ // device path patterns in FROM clause
+ List<PartialPath> devicePatternList = queryStatement.getFromComponent().getPrefixPaths();
+
+ Set<PartialPath> deviceList = new LinkedHashSet<>();
+ for (PartialPath devicePattern : devicePatternList) {
+ // get all matched devices
+ deviceList.addAll(
+ schemaTree.getMatchedDevices(devicePattern).stream()
+ .map(DeviceSchemaInfo::getDevicePath)
+ .collect(Collectors.toList()));
+ }
+ return deviceList;
+ }
+
+ private List<Pair<Expression, String>> analyzeSelect(
+ QueryStatement queryStatement,
+ SchemaTree schemaTree,
+ Set<PartialPath> deviceList,
+ Map<String, Set<Expression>> deviceToTransformExpressions,
+ Map<String, Set<String>> deviceToMeasurementsMap) {
+ List<Pair<Expression, String>> outputExpressions = new ArrayList<>();
+ ColumnPaginationController paginationController =
+ new ColumnPaginationController(
+ queryStatement.getSeriesLimit(), queryStatement.getSeriesOffset(), false);
+
+ for (ResultColumn resultColumn : queryStatement.getSelectComponent().getResultColumns()) {
+ Expression selectExpression = resultColumn.getExpression();
+ boolean hasAlias = resultColumn.hasAlias();
+
+ // measurement expression after removing wildcard
+ // use LinkedHashMap for order-preserving
+ Map<Expression, Map<String, Expression>> measurementToDeviceTransformExpressions =
+ new LinkedHashMap<>();
+ for (PartialPath device : deviceList) {
+ List<Expression> transformExpressions =
+ ExpressionAnalyzer.concatDeviceAndRemoveWildcard(
+ selectExpression, device, schemaTree, typeProvider);
+ for (Expression transformExpression : transformExpressions) {
+ measurementToDeviceTransformExpressions
+ .computeIfAbsent(
+ ExpressionAnalyzer.getMeasurementExpression(transformExpression),
+ key -> new LinkedHashMap<>())
+ .put(
+ device.getFullPath(),
+ ExpressionAnalyzer.removeAliasFromExpression(transformExpression));
+ }
+ }
+
+ if (hasAlias && measurementToDeviceTransformExpressions.keySet().size() > 1) {
+ throw new SemanticException(
+ String.format(
+ "alias '%s' can only be matched with one time series", resultColumn.getAlias()));
+ }
+
+ for (Expression measurementExpression : measurementToDeviceTransformExpressions.keySet()) {
+ if (paginationController.hasCurOffset()) {
+ paginationController.consumeOffset();
+ continue;
+ }
+ if (paginationController.hasCurLimit()) {
+ Map<String, Expression> deviceToTransformExpressionOfOneMeasurement =
+ measurementToDeviceTransformExpressions.get(measurementExpression);
+ deviceToTransformExpressionOfOneMeasurement
+ .values()
+ .forEach(expression -> expression.inferTypes(typeProvider));
+ // check whether the datatype of paths which has the same measurement name are
+ // consistent
+ // if not, throw a SemanticException
+ checkDataTypeConsistencyInAlignByDevice(
+ new ArrayList<>(deviceToTransformExpressionOfOneMeasurement.values()));
+
+ // add outputExpressions
+ Expression measurementExpressionWithoutAlias =
+ ExpressionAnalyzer.removeAliasFromExpression(measurementExpression);
+ String alias =
+ !Objects.equals(measurementExpressionWithoutAlias, measurementExpression)
+ ? measurementExpression.getExpressionString()
+ : null;
+ alias = hasAlias ? resultColumn.getAlias() : alias;
+ ExpressionAnalyzer.updateTypeProvider(measurementExpressionWithoutAlias, typeProvider);
+ measurementExpressionWithoutAlias.inferTypes(typeProvider);
+ outputExpressions.add(new Pair<>(measurementExpressionWithoutAlias, alias));
+
+ // add deviceToTransformExpressions
+ for (String deviceName : deviceToTransformExpressionOfOneMeasurement.keySet()) {
+ Expression transformExpression =
+ deviceToTransformExpressionOfOneMeasurement.get(deviceName);
+ ExpressionAnalyzer.updateTypeProvider(transformExpression, typeProvider);
+ transformExpression.inferTypes(typeProvider);
+ deviceToTransformExpressions
+ .computeIfAbsent(deviceName, key -> new LinkedHashSet<>())
+ .add(ExpressionAnalyzer.removeAliasFromExpression(transformExpression));
+ deviceToMeasurementsMap
+ .computeIfAbsent(deviceName, key -> new LinkedHashSet<>())
+ .add(measurementExpressionWithoutAlias.getExpressionString());
+ }
+ paginationController.consumeLimit();
+ } else {
+ break;
+ }
+ }
+ }
+
+ return outputExpressions;
+ }
+
+ private Pair<Filter, Boolean> analyzeGlobalTimeFilter(QueryStatement queryStatement) {
+ Filter globalTimeFilter = null;
+ boolean hasValueFilter = false;
+ if (queryStatement.getWhereCondition() != null) {
+ Pair<Filter, Boolean> resultPair =
+ ExpressionAnalyzer.transformToGlobalTimeFilter(
+ queryStatement.getWhereCondition().getPredicate());
+ globalTimeFilter = resultPair.left;
+ hasValueFilter = resultPair.right;
+ }
+ if (queryStatement.isGroupByTime()) {
+ GroupByTimeComponent groupByTimeComponent = queryStatement.getGroupByTimeComponent();
+ Filter groupByFilter = initGroupByFilter(groupByTimeComponent);
+ if (globalTimeFilter == null) {
+ globalTimeFilter = groupByFilter;
+ } else {
+ // TODO: optimize the filter
+ globalTimeFilter = FilterFactory.and(globalTimeFilter, groupByFilter);
+ }
+ }
+ return new Pair<>(globalTimeFilter, hasValueFilter);
+ }
+
+ private void updateSource(
+ Expression selectExpr, Set<Expression> sourceExpressions, boolean isRawDataSource) {
+ sourceExpressions.addAll(
+ ExpressionAnalyzer.searchSourceExpressions(selectExpr, isRawDataSource));
+ }
+
+ private boolean analyzeAggregation(
+ Set<Expression> transformExpressions,
+ Set<Expression> aggregationExpressions,
+ Set<Expression> aggregationTransformExpressions) {
+ // true if nested expressions and UDFs exist in aggregation function
+ // i.e. select sum(s1 + 1) from root.sg.d1 align by device
+ boolean isHasRawDataInputAggregation = false;
+ for (Expression expression : transformExpressions) {
+ for (Expression aggregationExpression :
+ ExpressionAnalyzer.searchAggregationExpressions(expression)) {
+ aggregationExpressions.add(aggregationExpression);
+ aggregationTransformExpressions.addAll(aggregationExpression.getExpressions());
+ }
+ }
+ for (Expression aggregationTransformExpression : aggregationTransformExpressions) {
+ if (ExpressionAnalyzer.checkIsNeedTransform(aggregationTransformExpression)) {
+ isHasRawDataInputAggregation = true;
+ break;
+ }
+ }
+ return isHasRawDataInputAggregation;
+ }
+
+ private Expression analyzeWhere(QueryStatement queryStatement, SchemaTree schemaTree) {
+ List<Expression> rewrittenPredicates =
+ ExpressionAnalyzer.removeWildcardInQueryFilter(
+ queryStatement.getWhereCondition().getPredicate(),
+ queryStatement.getFromComponent().getPrefixPaths(),
+ schemaTree,
+ typeProvider);
+ return ExpressionUtils.constructQueryFilter(
+ rewrittenPredicates.stream().distinct().collect(Collectors.toList()));
+ }
+
+ private Expression analyzeWhereSplitByDevice(
+ QueryStatement queryStatement, PartialPath devicePath, SchemaTree schemaTree) {
+ List<Expression> rewrittenPredicates =
+ ExpressionAnalyzer.removeWildcardInQueryFilterByDevice(
+ queryStatement.getWhereCondition().getPredicate(),
+ devicePath,
+ schemaTree,
+ typeProvider);
+ return ExpressionUtils.constructQueryFilter(
+ rewrittenPredicates.stream().distinct().collect(Collectors.toList()));
+ }
+
+ private Map<Expression, Set<Expression>> analyzeGroupByLevel(
+ QueryStatement queryStatement,
+ List<Pair<Expression, String>> outputExpressions,
+ Set<Expression> transformExpressions,
+ Map<Expression, Expression> rawPathToGroupedPathMap) {
+ GroupByLevelController groupByLevelController =
+ new GroupByLevelController(
+ queryStatement.getGroupByLevelComponent().getLevels(), typeProvider);
+ for (int i = 0; i < outputExpressions.size(); i++) {
+ Pair<Expression, String> measurementWithAlias = outputExpressions.get(i);
+ boolean isCountStar = queryStatement.getGroupByLevelComponent().isCountStar(i);
+ groupByLevelController.control(
+ isCountStar, measurementWithAlias.left, measurementWithAlias.right);
+ }
+ Map<Expression, Set<Expression>> rawGroupByLevelExpressions =
+ groupByLevelController.getGroupedPathMap();
+ rawPathToGroupedPathMap.putAll(groupByLevelController.getRawPathToGroupedPathMap());
+
+ Map<Expression, Set<Expression>> groupByLevelExpressions = new LinkedHashMap<>();
+ ColumnPaginationController paginationController =
+ new ColumnPaginationController(
+ queryStatement.getSeriesLimit(), queryStatement.getSeriesOffset(), false);
+ for (Expression groupedExpression : rawGroupByLevelExpressions.keySet()) {
+ if (paginationController.hasCurOffset()) {
+ paginationController.consumeOffset();
+ continue;
+ }
+ if (paginationController.hasCurLimit()) {
+ groupByLevelExpressions.put(
+ groupedExpression, rawGroupByLevelExpressions.get(groupedExpression));
+ paginationController.consumeLimit();
+ } else {
+ break;
+ }
+ }
+
+ // reset outputExpressions & transformExpressions after applying SLIMIT/SOFFSET
+ outputExpressions.clear();
+ for (Expression groupedExpression : groupByLevelExpressions.keySet()) {
+ TSDataType dataType =
+ typeProvider.getType(
+ new ArrayList<>(groupByLevelExpressions.get(groupedExpression))
+ .get(0)
+ .getExpressionString());
+ typeProvider.setType(groupedExpression.getExpressionString(), dataType);
+ outputExpressions.add(
+ new Pair<>(
+ groupedExpression,
+ groupByLevelController.getAlias(groupedExpression.getExpressionString())));
+ }
+ transformExpressions.clear();
+ transformExpressions.addAll(
+ groupByLevelExpressions.values().stream().flatMap(Set::stream).collect(Collectors.toSet()));
+ return groupByLevelExpressions;
+ }
+
+ private List<Expression> analyzeWithoutNullAlignByDevice(
+ QueryStatement queryStatement, Set<Expression> outputExpressions) {
+ List<Expression> resultFilterNullColumns = new ArrayList<>();
+ List<Expression> rawFilterNullColumns =
+ queryStatement.getFilterNullComponent().getWithoutNullColumns();
+
+ // don't specify columns, by default, it is effective for all columns
+ if (rawFilterNullColumns.isEmpty()) {
+ resultFilterNullColumns.addAll(outputExpressions);
+ return resultFilterNullColumns;
+ }
+
+ for (Expression filterNullColumn : rawFilterNullColumns) {
+ if (!outputExpressions.contains(filterNullColumn)) {
+ throw new SemanticException(
+ String.format(
+ "The without null column '%s' don't match the columns queried.", filterNullColumn));
+ }
+ resultFilterNullColumns.add(filterNullColumn);
+ }
+ return resultFilterNullColumns;
+ }
+
+ private List<Expression> analyzeWithoutNull(
+ QueryStatement queryStatement, SchemaTree schemaTree, Set<Expression> transformExpressions) {
+ List<Expression> resultFilterNullColumns = new ArrayList<>();
+ List<Expression> rawFilterNullColumns =
+ queryStatement.getFilterNullComponent().getWithoutNullColumns();
+
+ // don't specify columns, by default, it is effective for all columns
+ if (rawFilterNullColumns.isEmpty()) {
+ resultFilterNullColumns.addAll(transformExpressions);
+ return resultFilterNullColumns;
+ }
+
+ for (Expression filterNullColumn : rawFilterNullColumns) {
+ List<Expression> resultExpressions =
+ ExpressionAnalyzer.removeWildcardInExpression(filterNullColumn, schemaTree);
+ for (Expression expression : resultExpressions) {
+ Expression expressionWithoutAlias =
+ ExpressionAnalyzer.removeAliasFromExpression(expression);
+ if (!transformExpressions.contains(expressionWithoutAlias)) {
+ throw new SemanticException(
+ String.format(
+ "The without null column '%s' don't match the columns queried.",
+ filterNullColumn));
+ }
+ resultFilterNullColumns.add(expressionWithoutAlias);
+ }
+ }
+ return resultFilterNullColumns;
+ }
+
+ private DatasetHeader analyzeOutput(
+ QueryStatement queryStatement, List<Pair<Expression, String>> outputExpressions) {
+ boolean isIgnoreTimestamp =
+ queryStatement.isAggregationQuery() && !queryStatement.isGroupByTime();
+ List<ColumnHeader> columnHeaders = new ArrayList<>();
+ if (queryStatement.isAlignByDevice()) {
+ columnHeaders.add(new ColumnHeader(HeaderConstant.COLUMN_DEVICE, TSDataType.TEXT, null));
+ typeProvider.setType(HeaderConstant.COLUMN_DEVICE, TSDataType.TEXT);
+ }
+ columnHeaders.addAll(
+ outputExpressions.stream()
+ .map(
+ expressionWithAlias -> {
+ String columnName = expressionWithAlias.left.getExpressionString();
+ String alias = expressionWithAlias.right;
+ return new ColumnHeader(columnName, typeProvider.getType(columnName), alias);
+ })
+ .collect(Collectors.toList()));
+ return new DatasetHeader(columnHeaders, isIgnoreTimestamp);
+ }
+
+ private Analysis analyzeLast(
+ Analysis analysis, List<MeasurementPath> allSelectedPath, SchemaTree schemaTree) {
+ Set<Expression> sourceExpressions =
+ allSelectedPath.stream()
+ .map(TimeSeriesOperand::new)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ sourceExpressions.forEach(
+ expression -> ExpressionAnalyzer.updateTypeProvider(expression, typeProvider));
+ analysis.setSourceExpressions(sourceExpressions);
+
+ analysis.setRespDatasetHeader(HeaderConstant.LAST_QUERY_HEADER);
+ typeProvider.setType(HeaderConstant.COLUMN_TIMESERIES, TSDataType.TEXT);
+ typeProvider.setType(HeaderConstant.COLUMN_VALUE, TSDataType.TEXT);
+ typeProvider.setType(HeaderConstant.COLUMN_TIMESERIES_DATATYPE, TSDataType.TEXT);
+
+ Set<String> deviceSet =
+ allSelectedPath.stream().map(MeasurementPath::getDevice).collect(Collectors.toSet());
+ Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
+ for (String devicePath : deviceSet) {
+ DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
+ queryParam.setDevicePath(devicePath);
+ sgNameToQueryParamsMap
+ .computeIfAbsent(schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
+ .add(queryParam);
+ }
+ DataPartition dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
+ }
+
+ private DataPartition fetchDataPartitionByDevices(Set<String> deviceSet, SchemaTree schemaTree) {
+ Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
+ for (String devicePath : deviceSet) {
+ DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
+ queryParam.setDevicePath(devicePath);
+ sgNameToQueryParamsMap
+ .computeIfAbsent(schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
+ .add(queryParam);
+ }
+ return partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
+ }
+
+ /**
+ * Check datatype consistency in ALIGN BY DEVICE.
+ *
+ * <p>an inconsistent example: select s0 from root.sg1.d1, root.sg1.d2 align by device, return
+ * false while root.sg1.d1.s0 is INT32 and root.sg1.d2.s0 is FLOAT.
+ */
+ private void checkDataTypeConsistencyInAlignByDevice(List<Expression> expressions) {
+ TSDataType checkedDataType = typeProvider.getType(expressions.get(0).getExpressionString());
+ for (Expression expression : expressions) {
+ if (typeProvider.getType(expression.getExpressionString()) != checkedDataType) {
+ throw new SemanticException(
+ "ALIGN BY DEVICE: the data types of the same measurement column should be the same across devices.");
+ }
+ }
+ }
+
+ @Override
+ public Analysis visitLastPointFetch(LastPointFetchStatement statement, MPPQueryContext context) {
+ context.setQueryType(QueryType.READ);
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(statement);
+
+ SchemaTree schemaTree = new SchemaTree();
+ schemaTree.setStorageGroups(statement.getStorageGroups());
+
+ return analyzeLast(analysis, statement.getSelectedPaths(), schemaTree);
+ }
+
+ @Override
+ public Analysis visitInsert(InsertStatement insertStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+ insertStatement.semanticCheck();
+ long[] timeArray = insertStatement.getTimes();
+ PartialPath devicePath = insertStatement.getDevice();
+ String[] measurements = insertStatement.getMeasurementList();
+ if (timeArray.length == 1) {
+ // construct insert row statement
+ InsertRowStatement insertRowStatement = new InsertRowStatement();
+ insertRowStatement.setDevicePath(devicePath);
+ insertRowStatement.setTime(timeArray[0]);
+ insertRowStatement.setMeasurements(measurements);
+ insertRowStatement.setDataTypes(new TSDataType[insertStatement.getMeasurementList().length]);
+ Object[] values = new Object[insertStatement.getMeasurementList().length];
+ System.arraycopy(insertStatement.getValuesList().get(0), 0, values, 0, values.length);
+ insertRowStatement.setValues(values);
+ insertRowStatement.setNeedInferType(true);
+ insertRowStatement.setAligned(insertStatement.isAligned());
+ return insertRowStatement.accept(this, context);
+ } else {
+ // construct insert rows statement
+ // construct insert statement
+ InsertRowsStatement insertRowsStatement = new InsertRowsStatement();
+ List<InsertRowStatement> insertRowStatementList = new ArrayList<>();
+ for (int i = 0; i < timeArray.length; i++) {
+ InsertRowStatement statement = new InsertRowStatement();
+ statement.setDevicePath(devicePath);
+ statement.setMeasurements(measurements);
+ statement.setTime(timeArray[i]);
+ statement.setDataTypes(new TSDataType[insertStatement.getMeasurementList().length]);
+ Object[] values = new Object[insertStatement.getMeasurementList().length];
+ System.arraycopy(insertStatement.getValuesList().get(i), 0, values, 0, values.length);
+ statement.setValues(values);
+ statement.setAligned(insertStatement.isAligned());
+ statement.setNeedInferType(true);
+ insertRowStatementList.add(statement);
+ }
+ insertRowsStatement.setInsertRowStatementList(insertRowStatementList);
+ return insertRowsStatement.accept(this, context);
+ }
+ }
+
+ @Override
+ public Analysis visitCreateTimeseries(
+ CreateTimeSeriesStatement createTimeSeriesStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+ if (createTimeSeriesStatement.getTags() != null
+ && !createTimeSeriesStatement.getTags().isEmpty()
+ && createTimeSeriesStatement.getAttributes() != null
+ && !createTimeSeriesStatement.getAttributes().isEmpty()) {
+ for (String tagKey : createTimeSeriesStatement.getTags().keySet()) {
+ if (createTimeSeriesStatement.getAttributes().containsKey(tagKey)) {
+ throw new SemanticException(
+ String.format("Tag and attribute shouldn't have the same property key [%s]", tagKey));
+ }
+ }
+ }
+ Analysis analysis = new Analysis();
+ analysis.setStatement(createTimeSeriesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendFullPath(createTimeSeriesStatement.getPath());
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(patternTree);
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCreateAlignedTimeseries(
+ CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+ List<String> measurements = createAlignedTimeSeriesStatement.getMeasurements();
+ Set<String> measurementsSet = new HashSet<>(measurements);
+ if (measurementsSet.size() < measurements.size()) {
+ throw new SemanticException(
+ "Measurement under an aligned device is not allowed to have the same measurement name");
+ }
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(createAlignedTimeSeriesStatement);
+
+ PathPatternTree pathPatternTree = new PathPatternTree();
+ for (String measurement : createAlignedTimeSeriesStatement.getMeasurements()) {
+ pathPatternTree.appendFullPath(createAlignedTimeSeriesStatement.getDevicePath(), measurement);
+ }
+
+ SchemaPartition schemaPartitionInfo;
+ schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(pathPatternTree);
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitInternalCreateTimeseries(
+ InternalCreateTimeSeriesStatement internalCreateTimeSeriesStatement,
+ MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(internalCreateTimeSeriesStatement);
+
+ PathPatternTree pathPatternTree = new PathPatternTree();
+ for (String measurement : internalCreateTimeSeriesStatement.getMeasurements()) {
+ pathPatternTree.appendFullPath(
+ internalCreateTimeSeriesStatement.getDevicePath(), measurement);
+ }
+
+ SchemaPartition schemaPartitionInfo;
+ schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(pathPatternTree);
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCreateMultiTimeseries(
+ CreateMultiTimeSeriesStatement createMultiTimeSeriesStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+ Analysis analysis = new Analysis();
+ analysis.setStatement(createMultiTimeSeriesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ for (PartialPath path : createMultiTimeSeriesStatement.getPaths()) {
+ patternTree.appendFullPath(path);
+ }
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(patternTree);
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitAlterTimeseries(
+ AlterTimeSeriesStatement alterTimeSeriesStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+ Analysis analysis = new Analysis();
+ analysis.setStatement(alterTimeSeriesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendFullPath(alterTimeSeriesStatement.getPath());
+ SchemaPartition schemaPartitionInfo;
+ schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitInsertTablet(
+ InsertTabletStatement insertTabletStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+
+ DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
+ dataPartitionQueryParam.setDevicePath(insertTabletStatement.getDevicePath().getFullPath());
+ dataPartitionQueryParam.setTimePartitionSlotList(insertTabletStatement.getTimePartitionSlots());
+
+ DataPartition dataPartition =
+ partitionFetcher.getOrCreateDataPartition(
+ Collections.singletonList(dataPartitionQueryParam));
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(insertTabletStatement);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitInsertRow(InsertRowStatement insertRowStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+
+ DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
+ dataPartitionQueryParam.setDevicePath(insertRowStatement.getDevicePath().getFullPath());
+ dataPartitionQueryParam.setTimePartitionSlotList(insertRowStatement.getTimePartitionSlots());
+
+ DataPartition dataPartition =
+ partitionFetcher.getOrCreateDataPartition(
+ Collections.singletonList(dataPartitionQueryParam));
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(insertRowStatement);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitInsertRows(
+ InsertRowsStatement insertRowsStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+
+ List<DataPartitionQueryParam> dataPartitionQueryParams = new ArrayList<>();
+ for (InsertRowStatement insertRowStatement : insertRowsStatement.getInsertRowStatementList()) {
+ DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
+ dataPartitionQueryParam.setDevicePath(insertRowStatement.getDevicePath().getFullPath());
+ dataPartitionQueryParam.setTimePartitionSlotList(insertRowStatement.getTimePartitionSlots());
+ dataPartitionQueryParams.add(dataPartitionQueryParam);
+ }
+
+ DataPartition dataPartition =
+ partitionFetcher.getOrCreateDataPartition(dataPartitionQueryParams);
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(insertRowsStatement);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitInsertMultiTablets(
+ InsertMultiTabletsStatement insertMultiTabletsStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+
+ List<DataPartitionQueryParam> dataPartitionQueryParams = new ArrayList<>();
+ for (InsertTabletStatement insertTabletStatement :
+ insertMultiTabletsStatement.getInsertTabletStatementList()) {
+ DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
+ dataPartitionQueryParam.setDevicePath(insertTabletStatement.getDevicePath().getFullPath());
+ dataPartitionQueryParam.setTimePartitionSlotList(
+ insertTabletStatement.getTimePartitionSlots());
+ dataPartitionQueryParams.add(dataPartitionQueryParam);
+ }
+
+ DataPartition dataPartition =
+ partitionFetcher.getOrCreateDataPartition(dataPartitionQueryParams);
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(insertMultiTabletsStatement);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitInsertRowsOfOneDevice(
+ InsertRowsOfOneDeviceStatement insertRowsOfOneDeviceStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+
+ DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
+ dataPartitionQueryParam.setDevicePath(
+ insertRowsOfOneDeviceStatement.getDevicePath().getFullPath());
+ dataPartitionQueryParam.setTimePartitionSlotList(
+ insertRowsOfOneDeviceStatement.getTimePartitionSlots());
+
+ DataPartition dataPartition =
+ partitionFetcher.getOrCreateDataPartition(
+ Collections.singletonList(dataPartitionQueryParam));
+
+ Analysis analysis = new Analysis();
+ analysis.setStatement(insertRowsOfOneDeviceStatement);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowTimeSeries(
+ ShowTimeSeriesStatement showTimeSeriesStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showTimeSeriesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(showTimeSeriesStatement.getPathPattern());
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+
+ if (showTimeSeriesStatement.isOrderByHeat()) {
+ patternTree.constructTree();
+ // request schema fetch API
+ logger.info("{} fetch query schema...", getLogHeader());
+ SchemaTree schemaTree = schemaFetcher.fetchSchema(patternTree);
+ logger.info("{} fetch schema done", getLogHeader());
+ List<MeasurementPath> allSelectedPath = schemaTree.getAllMeasurement();
+
+ Set<Expression> sourceExpressions =
+ allSelectedPath.stream()
+ .map(TimeSeriesOperand::new)
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ analysis.setSourceExpressions(sourceExpressions);
+
+ Set<String> deviceSet =
+ allSelectedPath.stream().map(MeasurementPath::getDevice).collect(Collectors.toSet());
+ Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
+ for (String devicePath : deviceSet) {
+ DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
+ queryParam.setDevicePath(devicePath);
+ sgNameToQueryParamsMap
+ .computeIfAbsent(
+ schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
+ .add(queryParam);
+ }
+ DataPartition dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
+ analysis.setDataPartitionInfo(dataPartition);
+ }
+
+ analysis.setRespDatasetHeader(HeaderConstant.showTimeSeriesHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowStorageGroup(
+ ShowStorageGroupStatement showStorageGroupStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showStorageGroupStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showStorageGroupHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowTTL(ShowTTLStatement showTTLStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showTTLStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showTTLHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowDevices(
+ ShowDevicesStatement showDevicesStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showDevicesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(
+ showDevicesStatement.getPathPattern().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD));
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
+
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ analysis.setRespDatasetHeader(
+ showDevicesStatement.hasSgCol()
+ ? HeaderConstant.showDevicesWithSgHeader
+ : HeaderConstant.showDevicesHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowCluster(
+ ShowClusterStatement showClusterStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showClusterStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showClusterHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCountStorageGroup(
+ CountStorageGroupStatement countStorageGroupStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(countStorageGroupStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.countStorageGroupHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitSchemaFetch(
+ SchemaFetchStatement schemaFetchStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(schemaFetchStatement);
+ analysis.setSchemaPartitionInfo(schemaFetchStatement.getSchemaPartition());
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCountDevices(
+ CountDevicesStatement countDevicesStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(countDevicesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(
+ countDevicesStatement.getPartialPath().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD));
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
+
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ analysis.setRespDatasetHeader(HeaderConstant.countDevicesHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCountTimeSeries(
+ CountTimeSeriesStatement countTimeSeriesStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(countTimeSeriesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(countTimeSeriesStatement.getPartialPath());
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
+
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ analysis.setRespDatasetHeader(HeaderConstant.countTimeSeriesHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCountLevelTimeSeries(
+ CountLevelTimeSeriesStatement countLevelTimeSeriesStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(countLevelTimeSeriesStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(countLevelTimeSeriesStatement.getPartialPath());
+ SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
+
+ analysis.setSchemaPartitionInfo(schemaPartitionInfo);
+ analysis.setRespDatasetHeader(HeaderConstant.countLevelTimeSeriesHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCountNodes(CountNodesStatement countStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(countStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(countStatement.getPartialPath());
+ SchemaNodeManagementPartition schemaNodeManagementPartition =
+ partitionFetcher.getSchemaNodeManagementPartitionWithLevel(
+ patternTree, countStatement.getLevel());
+
+ if (schemaNodeManagementPartition == null) {
+ return analysis;
+ }
+ if (!schemaNodeManagementPartition.getMatchedNode().isEmpty()
+ && schemaNodeManagementPartition.getSchemaPartition().getSchemaPartitionMap().size() == 0) {
+ analysis.setFinishQueryAfterAnalyze(true);
+ }
+ analysis.setMatchedNodes(schemaNodeManagementPartition.getMatchedNode());
+ analysis.setSchemaPartitionInfo(schemaNodeManagementPartition.getSchemaPartition());
+ analysis.setRespDatasetHeader(HeaderConstant.countNodesHeader);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowChildPaths(
+ ShowChildPathsStatement showChildPathsStatement, MPPQueryContext context) {
+ return visitSchemaNodeManagementPartition(
+ showChildPathsStatement,
+ showChildPathsStatement.getPartialPath(),
+ HeaderConstant.showChildPathsHeader);
+ }
+
+ @Override
+ public Analysis visitShowChildNodes(
+ ShowChildNodesStatement showChildNodesStatement, MPPQueryContext context) {
+ return visitSchemaNodeManagementPartition(
+ showChildNodesStatement,
+ showChildNodesStatement.getPartialPath(),
+ HeaderConstant.showChildNodesHeader);
+ }
+
+ @Override
+ public Analysis visitShowVersion(
+ ShowVersionStatement showVersionStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showVersionStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showVersionHeader);
+ analysis.setFinishQueryAfterAnalyze(true);
+ return analysis;
+ }
+
+ private Analysis visitSchemaNodeManagementPartition(
+ Statement statement, PartialPath path, DatasetHeader header) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(statement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ patternTree.appendPathPattern(path);
+ SchemaNodeManagementPartition schemaNodeManagementPartition =
+ partitionFetcher.getSchemaNodeManagementPartition(patternTree);
+
+ if (schemaNodeManagementPartition == null) {
+ return analysis;
+ }
+ if (!schemaNodeManagementPartition.getMatchedNode().isEmpty()
+ && schemaNodeManagementPartition.getSchemaPartition().getSchemaPartitionMap().size() == 0) {
+ analysis.setFinishQueryAfterAnalyze(true);
+ }
+ analysis.setMatchedNodes(schemaNodeManagementPartition.getMatchedNode());
+ analysis.setSchemaPartitionInfo(schemaNodeManagementPartition.getSchemaPartition());
+ analysis.setRespDatasetHeader(header);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitDeleteData(
+ DeleteDataStatement deleteDataStatement, MPPQueryContext context) {
+ context.setQueryType(QueryType.WRITE);
+ Analysis analysis = new Analysis();
+ analysis.setStatement(deleteDataStatement);
+
+ PathPatternTree patternTree = new PathPatternTree();
+ for (PartialPath pathPattern : deleteDataStatement.getPathList()) {
+ patternTree.appendPathPattern(pathPattern);
+ }
+
+ SchemaPartition schemaPartition = partitionFetcher.getSchemaPartition(patternTree);
+
+ SchemaTree schemaTree = schemaFetcher.fetchSchema(patternTree, schemaPartition);
+ analysis.setSchemaTree(schemaTree);
+
+ Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
+
+ Map<String, Map<TSeriesPartitionSlot, TRegionReplicaSet>> schemaPartitionMap =
+ schemaPartition.getSchemaPartitionMap();
+
+ // todo keep the behaviour consistency of cluster and standalone,
+ // the behaviour of standalone fetcher and LocalConfigNode is not consistent with that of
+ // cluster mode's
+ if (IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
+ for (String storageGroup : schemaPartitionMap.keySet()) {
+ sgNameToQueryParamsMap.put(
+ storageGroup,
+ schemaPartitionMap.get(storageGroup).keySet().stream()
+ .map(DataPartitionQueryParam::new)
+ .collect(Collectors.toList()));
+ }
+ } else {
+ // the StandalonePartitionFetcher and LocalConfigNode now doesn't support partition fetch
+ // via slotId
+ schemaTree
+ .getMatchedDevices(new PartialPath(ALL_RESULT_NODES))
+ .forEach(
+ deviceSchemaInfo -> {
+ PartialPath devicePath = deviceSchemaInfo.getDevicePath();
+ DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
+ queryParam.setDevicePath(devicePath.getFullPath());
+ sgNameToQueryParamsMap
+ .computeIfAbsent(
+ schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
+ .add(queryParam);
+ });
+ }
+
+ DataPartition dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
+ analysis.setDataPartitionInfo(dataPartition);
+
+ if (dataPartition.isEmpty()) {
+ analysis.setFinishQueryAfterAnalyze(true);
+ }
+
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitCreateSchemaTemplate(
+ CreateSchemaTemplateStatement createTemplateStatement, MPPQueryContext context) {
+
+ context.setQueryType(QueryType.WRITE);
+ List<List<String>> measurementsList = createTemplateStatement.getMeasurements();
+ for (List measurements : measurementsList) {
+ Set<String> measurementsSet = new HashSet<>(measurements);
+ if (measurementsSet.size() < measurements.size()) {
+ throw new SemanticException(
+ "Measurement under an aligned device is not allowed to have the same measurement name");
+ }
+ }
+ Analysis analysis = new Analysis();
+ analysis.setStatement(createTemplateStatement);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowNodesInSchemaTemplate(
+ ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement,
+ MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showNodesInSchemaTemplateStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showNodesInSchemaTemplate);
+ return analysis;
+ }
+
+ @Override
+ public Analysis visitShowSchemaTemplate(
+ ShowSchemaTemplateStatement showSchemaTemplateStatement, MPPQueryContext context) {
+ Analysis analysis = new Analysis();
+ analysis.setStatement(showSchemaTemplateStatement);
+ analysis.setRespDatasetHeader(HeaderConstant.showSchemaTemplate);
+ return analysis;
+ }
+
+ private GroupByFilter initGroupByFilter(GroupByTimeComponent groupByTimeComponent) {
+ if (groupByTimeComponent.isIntervalByMonth() || groupByTimeComponent.isSlidingStepByMonth()) {
+ return new GroupByMonthFilter(
+ groupByTimeComponent.getInterval(),
+ groupByTimeComponent.getSlidingStep(),
+ groupByTimeComponent.getStartTime(),
+ groupByTimeComponent.getEndTime(),
+ groupByTimeComponent.isSlidingStepByMonth(),
+ groupByTimeComponent.isIntervalByMonth(),
+ TimeZone.getTimeZone("+00:00"));
+ } else {
+ return new GroupByFilter(
+ groupByTimeComponent.getInterval(),
+ groupByTimeComponent.getSlidingStep(),
+ groupByTimeComponent.getStartTime(),
+ groupByTimeComponent.getEndTime());
+ }
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
index ccbe7a1b11..6243a1cbb7 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
@@ -19,97 +19,12 @@
package org.apache.iotdb.db.mpp.plan.analyze;
-import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
-import org.apache.iotdb.common.rpc.thrift.TSeriesPartitionSlot;
-import org.apache.iotdb.commons.conf.IoTDBConstant;
-import org.apache.iotdb.commons.partition.DataPartition;
-import org.apache.iotdb.commons.partition.DataPartitionQueryParam;
-import org.apache.iotdb.commons.partition.SchemaNodeManagementPartition;
-import org.apache.iotdb.commons.partition.SchemaPartition;
-import org.apache.iotdb.commons.path.PartialPath;
-import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.exception.sql.MeasurementNotExistException;
-import org.apache.iotdb.db.exception.sql.SemanticException;
-import org.apache.iotdb.db.exception.sql.StatementAnalyzeException;
-import org.apache.iotdb.db.metadata.path.MeasurementPath;
import org.apache.iotdb.db.mpp.common.MPPQueryContext;
-import org.apache.iotdb.db.mpp.common.header.ColumnHeader;
-import org.apache.iotdb.db.mpp.common.header.DatasetHeader;
-import org.apache.iotdb.db.mpp.common.header.HeaderConstant;
-import org.apache.iotdb.db.mpp.common.schematree.DeviceSchemaInfo;
-import org.apache.iotdb.db.mpp.common.schematree.PathPatternTree;
-import org.apache.iotdb.db.mpp.common.schematree.SchemaTree;
-import org.apache.iotdb.db.mpp.plan.expression.Expression;
-import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
-import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
-import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.FillDescriptor;
-import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.FilterNullParameter;
-import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.GroupByTimeParameter;
import org.apache.iotdb.db.mpp.plan.statement.Statement;
-import org.apache.iotdb.db.mpp.plan.statement.StatementNode;
-import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
-import org.apache.iotdb.db.mpp.plan.statement.component.FillComponent;
-import org.apache.iotdb.db.mpp.plan.statement.component.GroupByTimeComponent;
-import org.apache.iotdb.db.mpp.plan.statement.component.OrderBy;
-import org.apache.iotdb.db.mpp.plan.statement.component.ResultColumn;
-import org.apache.iotdb.db.mpp.plan.statement.crud.DeleteDataStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertMultiTabletsStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsOfOneDeviceStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertTabletStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
-import org.apache.iotdb.db.mpp.plan.statement.internal.InternalCreateTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.internal.LastPointFetchStatement;
-import org.apache.iotdb.db.mpp.plan.statement.internal.SchemaFetchStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.AlterTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountDevicesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountStorageGroupStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildNodesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildPathsStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowClusterStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDevicesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowStorageGroupStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTTLStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowNodesInSchemaTemplateStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.template.ShowSchemaTemplateStatement;
-import org.apache.iotdb.db.mpp.plan.statement.sys.ExplainStatement;
-import org.apache.iotdb.db.mpp.plan.statement.sys.ShowVersionStatement;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.filter.GroupByFilter;
-import org.apache.iotdb.tsfile.read.filter.GroupByMonthFilter;
-import org.apache.iotdb.tsfile.read.filter.basic.Filter;
-import org.apache.iotdb.tsfile.read.filter.factory.FilterFactory;
-import org.apache.iotdb.tsfile.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.stream.Collectors;
-
-import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_RESULT_NODES;
-
/** Analyze the statement and generate Analysis. */
public class Analyzer {
private static final Logger logger = LoggerFactory.getLogger(Analyzer.class);
@@ -129,1368 +44,7 @@ public class Analyzer {
}
public Analysis analyze(Statement statement) {
- return new AnalyzeVisitor().process(statement, context);
- }
-
- private String getLogHeader() {
- return String.format("Query[%s]:", context.getQueryId());
- }
-
- /** This visitor is used to analyze each type of Statement and returns the {@link Analysis}. */
- private final class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> {
-
- @Override
- public Analysis visitNode(StatementNode node, MPPQueryContext context) {
- throw new UnsupportedOperationException(
- "Unsupported statement type: " + node.getClass().getName());
- }
-
- @Override
- public Analysis visitExplain(ExplainStatement explainStatement, MPPQueryContext context) {
- Analysis analysis = visitQuery(explainStatement.getQueryStatement(), context);
- analysis.setStatement(explainStatement);
- analysis.setFinishQueryAfterAnalyze(true);
- return analysis;
- }
-
- @Override
- public Analysis visitQuery(QueryStatement queryStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- try {
- // check for semantic errors
- queryStatement.semanticCheck();
-
- // concat path and construct path pattern tree
- PathPatternTree patternTree = new PathPatternTree();
- queryStatement =
- (QueryStatement) new ConcatPathRewriter().rewrite(queryStatement, patternTree);
- analysis.setStatement(queryStatement);
-
- // request schema fetch API
- logger.info("{} fetch query schema...", getLogHeader());
- SchemaTree schemaTree = schemaFetcher.fetchSchema(patternTree);
- logger.info("{} fetch schema done", getLogHeader());
- // If there is no leaf node in the schema tree, the query should be completed immediately
- if (schemaTree.isEmpty()) {
- analysis.setFinishQueryAfterAnalyze(true);
- return analysis;
- }
-
- // extract global time filter from query filter and determine if there is a value filter
- Pair<Filter, Boolean> resultPair = analyzeGlobalTimeFilter(queryStatement);
- Filter globalTimeFilter = resultPair.left;
- boolean hasValueFilter = resultPair.right;
- analysis.setGlobalTimeFilter(globalTimeFilter);
- analysis.setHasValueFilter(hasValueFilter);
-
- if (queryStatement.isLastQuery()) {
- if (hasValueFilter) {
- throw new SemanticException("Only time filters are supported in LAST query");
- }
-
- return analyzeLast(analysis, schemaTree.getAllMeasurement(), schemaTree);
- }
-
- // Example 1: select s1, s1 + s2 as t, udf(udf(s1)) from root.sg.d1
- // outputExpressions: [<root.sg.d1.s1,null>, <root.sg.d1.s1 + root.sg.d1.s2,t>,
- // <udf(udf(root.sg.d1.s1)),null>]
- // transformExpressions: [root.sg.d1.s1, root.sg.d1.s1 + root.sg.d1.s2,
- // udf(udf(root.sg.d1.s1))]
- // sourceExpressions: {root.sg.d1 -> [root.sg.d1.s1, root.sg.d1.s2]}
- //
- // Example 2: select s1, s2, s3 as t from root.sg.* align by device
- // outputExpressions: [<s1,null>, <s2,null>, <s1,t>]
- // transformExpressions: [root.sg.d1.s1, root.sg.d1.s2, root.sg.d1.s3,
- // root.sg.d2.s1, root.sg.d2.s2]
- // sourceExpressions: {root.sg.d1 -> [root.sg.d1.s1, root.sg.d1.s2, root.sg.d1.s2],
- // root.sg.d2 -> [root.sg.d2.s1, root.sg.d2.s2]}
- //
- // Example 3: select sum(s1) + 1 as t, count(s2) from root.sg.d1
- // outputExpressions: [<sum(root.sg.d1.s1) + 1,t>, <count(root.sg.d1.s2),t>]
- // transformExpressions: [sum(root.sg.d1.s1) + 1, count(root.sg.d1.s2)]
- // aggregationExpressions: {root.sg.d1 -> [sum(root.sg.d1.s1), count(root.sg.d1.s2)]}
- // sourceExpressions: {root.sg.d1 -> [sum(root.sg.d1.s1), count(root.sg.d1.s2)]}
- //
- // Example 4: select sum(s1) + 1 as t, count(s2) from root.sg.d1 where s1 > 1
- // outputExpressions: [<sum(root.sg.d1.s1) + 1,t>, <count(root.sg.d1.s2),t>]
- // transformExpressions: [sum(root.sg.d1.s1) + 1, count(root.sg.d1.s2)]
- // aggregationExpressions: {root.sg.d1 -> [sum(root.sg.d1.s1), count(root.sg.d1.s2)]}
- // sourceExpressions: {root.sg.d1 -> [root.sg.d1.s1, root.sg.d1.s2]}
- List<Pair<Expression, String>> outputExpressions;
- if (queryStatement.isAlignByDevice()) {
- Map<String, Set<Expression>> deviceToTransformExpressions = new HashMap<>();
-
- // all selected device
- Set<PartialPath> deviceList = analyzeFrom(queryStatement, schemaTree);
-
- Map<String, Set<String>> deviceToMeasurementsMap = new HashMap<>();
- outputExpressions =
- analyzeSelect(
- queryStatement,
- schemaTree,
- deviceList,
- deviceToTransformExpressions,
- deviceToMeasurementsMap);
-
- Map<String, List<Integer>> deviceToMeasurementIndexesMap = new HashMap<>();
- List<String> allMeasurements =
- outputExpressions.stream()
- .map(Pair::getLeft)
- .map(Expression::getExpressionString)
- .distinct()
- .collect(Collectors.toList());
- for (String deviceName : deviceToMeasurementsMap.keySet()) {
- List<String> measurementsUnderDevice =
- new ArrayList<>(deviceToMeasurementsMap.get(deviceName));
- List<Integer> indexes = new ArrayList<>();
- for (String measurement : measurementsUnderDevice) {
- indexes.add(
- allMeasurements.indexOf(measurement) + 1); // add 1 to skip the device column
- }
- deviceToMeasurementIndexesMap.put(deviceName, indexes);
- }
- analysis.setDeviceToMeasurementIndexesMap(deviceToMeasurementIndexesMap);
-
- Map<String, Set<Expression>> deviceToSourceExpressions = new HashMap<>();
- boolean isValueFilterAggregation = queryStatement.isAggregationQuery() && hasValueFilter;
-
- Map<String, Boolean> deviceToIsRawDataSource = new HashMap<>();
-
- Map<String, Set<Expression>> deviceToAggregationExpressions = new HashMap<>();
- Map<String, Set<Expression>> deviceToAggregationTransformExpressions = new HashMap<>();
- for (String deviceName : deviceToTransformExpressions.keySet()) {
- Set<Expression> transformExpressions = deviceToTransformExpressions.get(deviceName);
- Set<Expression> aggregationExpressions = new LinkedHashSet<>();
- Set<Expression> aggregationTransformExpressions = new LinkedHashSet<>();
-
- boolean isHasRawDataInputAggregation = false;
- if (queryStatement.isAggregationQuery()) {
- // true if nested expressions and UDFs exist in aggregation function
- // i.e. select sum(s1 + 1) from root.sg.d1 align by device
- isHasRawDataInputAggregation =
- analyzeAggregation(
- transformExpressions,
- aggregationExpressions,
- aggregationTransformExpressions);
- deviceToAggregationExpressions.put(deviceName, aggregationExpressions);
- deviceToAggregationTransformExpressions.put(
- deviceName, aggregationTransformExpressions);
- }
-
- boolean isRawDataSource =
- !queryStatement.isAggregationQuery()
- || isValueFilterAggregation
- || isHasRawDataInputAggregation;
-
- for (Expression expression : transformExpressions) {
- updateSource(
- expression,
- deviceToSourceExpressions.computeIfAbsent(
- deviceName, key -> new LinkedHashSet<>()),
- isRawDataSource);
- }
- deviceToIsRawDataSource.put(deviceName, isRawDataSource);
- }
- analysis.setDeviceToAggregationExpressions(deviceToAggregationExpressions);
- analysis.setDeviceToAggregationTransformExpressions(
- deviceToAggregationTransformExpressions);
- analysis.setDeviceToIsRawDataSource(deviceToIsRawDataSource);
-
- if (queryStatement.getWhereCondition() != null) {
- Map<String, Expression> deviceToQueryFilter = new HashMap<>();
- Iterator<PartialPath> deviceIterator = deviceList.iterator();
- while (deviceIterator.hasNext()) {
- PartialPath devicePath = deviceIterator.next();
- Expression queryFilter = null;
- try {
- queryFilter = analyzeWhereSplitByDevice(queryStatement, devicePath, schemaTree);
- } catch (SemanticException e) {
- if (e instanceof MeasurementNotExistException) {
- logger.warn(e.getMessage());
- deviceIterator.remove();
- deviceToSourceExpressions.remove(devicePath.getFullPath());
- continue;
- }
- throw e;
- }
- deviceToQueryFilter.put(devicePath.getFullPath(), queryFilter);
- queryFilter.inferTypes(typeProvider);
- updateSource(
- queryFilter,
- deviceToSourceExpressions.computeIfAbsent(
- devicePath.getFullPath(), key -> new LinkedHashSet<>()),
- true);
- }
- analysis.setDeviceToQueryFilter(deviceToQueryFilter);
- }
- analysis.setDeviceToSourceExpressions(deviceToSourceExpressions);
- analysis.setDeviceToTransformExpressions(deviceToTransformExpressions);
- } else {
- outputExpressions = analyzeSelect(queryStatement, schemaTree);
- Set<Expression> transformExpressions =
- outputExpressions.stream()
- .map(Pair::getLeft)
- .collect(Collectors.toCollection(LinkedHashSet::new));
-
- if (queryStatement.isGroupByLevel()) {
- // map from grouped expression to set of input expressions
- Map<Expression, Expression> rawPathToGroupedPathMap = new HashMap<>();
- Map<Expression, Set<Expression>> groupByLevelExpressions =
- analyzeGroupByLevel(
- queryStatement,
- outputExpressions,
- transformExpressions,
- rawPathToGroupedPathMap);
- analysis.setGroupByLevelExpressions(groupByLevelExpressions);
- analysis.setRawPathToGroupedPathMap(rawPathToGroupedPathMap);
- }
-
- // true if nested expressions and UDFs exist in aggregation function
- // i.e. select sum(s1 + 1) from root.sg.d1
- boolean isHasRawDataInputAggregation = false;
- if (queryStatement.isAggregationQuery()) {
- Set<Expression> aggregationExpressions = new HashSet<>();
- Set<Expression> aggregationTransformExpressions = new HashSet<>();
- isHasRawDataInputAggregation =
- analyzeAggregation(
- transformExpressions, aggregationExpressions, aggregationTransformExpressions);
- analysis.setAggregationExpressions(aggregationExpressions);
- analysis.setAggregationTransformExpressions(aggregationTransformExpressions);
- }
-
- // generate sourceExpression according to transformExpressions
- Set<Expression> sourceExpressions = new HashSet<>();
- boolean isValueFilterAggregation = queryStatement.isAggregationQuery() && hasValueFilter;
- boolean isRawDataSource =
- !queryStatement.isAggregationQuery()
- || isValueFilterAggregation
- || isHasRawDataInputAggregation;
- for (Expression expression : transformExpressions) {
- updateSource(expression, sourceExpressions, isRawDataSource);
- }
-
- if (queryStatement.getWhereCondition() != null) {
- Expression queryFilter = analyzeWhere(queryStatement, schemaTree);
-
- // update sourceExpression according to queryFilter
- queryFilter.inferTypes(typeProvider);
- updateSource(queryFilter, sourceExpressions, isRawDataSource);
- analysis.setQueryFilter(queryFilter);
- }
- analysis.setRawDataSource(isRawDataSource);
- analysis.setSourceExpressions(sourceExpressions);
- analysis.setTransformExpressions(transformExpressions);
- }
-
- if (queryStatement.isGroupByTime()) {
- GroupByTimeComponent groupByTimeComponent = queryStatement.getGroupByTimeComponent();
- if ((groupByTimeComponent.isIntervalByMonth()
- || groupByTimeComponent.isSlidingStepByMonth())
- && queryStatement.getResultOrder() == OrderBy.TIMESTAMP_DESC) {
- throw new SemanticException("Group by month doesn't support order by time desc now.");
- }
- analysis.setGroupByTimeParameter(new GroupByTimeParameter(groupByTimeComponent));
- }
-
- if (queryStatement.getFilterNullComponent() != null) {
- FilterNullParameter filterNullParameter = new FilterNullParameter();
- filterNullParameter.setFilterNullPolicy(
- queryStatement.getFilterNullComponent().getWithoutPolicyType());
- List<Expression> resultFilterNullColumns;
- if (queryStatement.isAlignByDevice()) {
- resultFilterNullColumns =
- analyzeWithoutNullAlignByDevice(
- queryStatement,
- outputExpressions.stream().map(Pair::getLeft).collect(Collectors.toSet()));
- } else {
- resultFilterNullColumns =
- analyzeWithoutNull(queryStatement, schemaTree, analysis.getTransformExpressions());
- }
- filterNullParameter.setFilterNullColumns(resultFilterNullColumns);
- analysis.setFilterNullParameter(filterNullParameter);
- }
-
- if (queryStatement.getFillComponent() != null) {
- FillComponent fillComponent = queryStatement.getFillComponent();
- List<Expression> fillColumnList =
- outputExpressions.stream().map(Pair::getLeft).distinct().collect(Collectors.toList());
- analysis.setFillDescriptor(
- new FillDescriptor(fillComponent.getFillPolicy(), fillComponent.getFillValue()));
- }
-
- // generate result set header according to output expressions
- DatasetHeader datasetHeader = analyzeOutput(queryStatement, outputExpressions);
- analysis.setRespDatasetHeader(datasetHeader);
- analysis.setTypeProvider(typeProvider);
-
- // fetch partition information
- Set<String> deviceSet = new HashSet<>();
- if (queryStatement.isAlignByDevice()) {
- deviceSet = analysis.getDeviceToSourceExpressions().keySet();
- } else {
- for (Expression expression : analysis.getSourceExpressions()) {
- deviceSet.add(ExpressionAnalyzer.getDeviceNameInSourceExpression(expression));
- }
- }
- DataPartition dataPartition = fetchDataPartitionByDevices(deviceSet, schemaTree);
- analysis.setDataPartitionInfo(dataPartition);
- } catch (StatementAnalyzeException e) {
- logger.error("Meet error when analyzing the query statement: ", e);
- throw new StatementAnalyzeException(
- "Meet error when analyzing the query statement: " + e.getMessage());
- }
- return analysis;
- }
-
- private List<Pair<Expression, String>> analyzeSelect(
- QueryStatement queryStatement, SchemaTree schemaTree) {
- List<Pair<Expression, String>> outputExpressions = new ArrayList<>();
- ColumnPaginationController paginationController =
- new ColumnPaginationController(
- queryStatement.getSeriesLimit(),
- queryStatement.getSeriesOffset(),
- queryStatement.isLastQuery() || queryStatement.isGroupByLevel());
-
- for (ResultColumn resultColumn : queryStatement.getSelectComponent().getResultColumns()) {
- boolean hasAlias = resultColumn.hasAlias();
- List<Expression> resultExpressions =
- ExpressionAnalyzer.removeWildcardInExpression(resultColumn.getExpression(), schemaTree);
- if (hasAlias && !queryStatement.isGroupByLevel() && resultExpressions.size() > 1) {
- throw new SemanticException(
- String.format(
- "alias '%s' can only be matched with one time series", resultColumn.getAlias()));
- }
- for (Expression expression : resultExpressions) {
- if (paginationController.hasCurOffset()) {
- paginationController.consumeOffset();
- continue;
- }
- if (paginationController.hasCurLimit()) {
- Expression expressionWithoutAlias =
- ExpressionAnalyzer.removeAliasFromExpression(expression);
- String alias =
- !Objects.equals(expressionWithoutAlias, expression)
- ? expression.getExpressionString()
- : null;
- alias = hasAlias ? resultColumn.getAlias() : alias;
- outputExpressions.add(new Pair<>(expressionWithoutAlias, alias));
- if (queryStatement.isGroupByLevel()
- && resultColumn.getExpression() instanceof FunctionExpression) {
- queryStatement
- .getGroupByLevelComponent()
- .updateIsCountStar((FunctionExpression) resultColumn.getExpression());
- }
- ExpressionAnalyzer.updateTypeProvider(expressionWithoutAlias, typeProvider);
- expressionWithoutAlias.inferTypes(typeProvider);
- paginationController.consumeLimit();
- } else {
- break;
- }
- }
- }
- return outputExpressions;
- }
-
- private Set<PartialPath> analyzeFrom(QueryStatement queryStatement, SchemaTree schemaTree) {
- // device path patterns in FROM clause
- List<PartialPath> devicePatternList = queryStatement.getFromComponent().getPrefixPaths();
-
- Set<PartialPath> deviceList = new LinkedHashSet<>();
- for (PartialPath devicePattern : devicePatternList) {
- // get all matched devices
- deviceList.addAll(
- schemaTree.getMatchedDevices(devicePattern).stream()
- .map(DeviceSchemaInfo::getDevicePath)
- .collect(Collectors.toList()));
- }
- return deviceList;
- }
-
- private List<Pair<Expression, String>> analyzeSelect(
- QueryStatement queryStatement,
- SchemaTree schemaTree,
- Set<PartialPath> deviceList,
- Map<String, Set<Expression>> deviceToTransformExpressions,
- Map<String, Set<String>> deviceToMeasurementsMap) {
- List<Pair<Expression, String>> outputExpressions = new ArrayList<>();
- ColumnPaginationController paginationController =
- new ColumnPaginationController(
- queryStatement.getSeriesLimit(), queryStatement.getSeriesOffset(), false);
-
- for (ResultColumn resultColumn : queryStatement.getSelectComponent().getResultColumns()) {
- Expression selectExpression = resultColumn.getExpression();
- boolean hasAlias = resultColumn.hasAlias();
-
- // measurement expression after removing wildcard
- // use LinkedHashMap for order-preserving
- Map<Expression, Map<String, Expression>> measurementToDeviceTransformExpressions =
- new LinkedHashMap<>();
- for (PartialPath device : deviceList) {
- List<Expression> transformExpressions =
- ExpressionAnalyzer.concatDeviceAndRemoveWildcard(
- selectExpression, device, schemaTree, typeProvider);
- for (Expression transformExpression : transformExpressions) {
- measurementToDeviceTransformExpressions
- .computeIfAbsent(
- ExpressionAnalyzer.getMeasurementExpression(transformExpression),
- key -> new LinkedHashMap<>())
- .put(
- device.getFullPath(),
- ExpressionAnalyzer.removeAliasFromExpression(transformExpression));
- }
- }
-
- if (hasAlias && measurementToDeviceTransformExpressions.keySet().size() > 1) {
- throw new SemanticException(
- String.format(
- "alias '%s' can only be matched with one time series", resultColumn.getAlias()));
- }
-
- for (Expression measurementExpression : measurementToDeviceTransformExpressions.keySet()) {
- if (paginationController.hasCurOffset()) {
- paginationController.consumeOffset();
- continue;
- }
- if (paginationController.hasCurLimit()) {
- Map<String, Expression> deviceToTransformExpressionOfOneMeasurement =
- measurementToDeviceTransformExpressions.get(measurementExpression);
- deviceToTransformExpressionOfOneMeasurement
- .values()
- .forEach(expression -> expression.inferTypes(typeProvider));
- // check whether the datatype of paths which has the same measurement name are
- // consistent
- // if not, throw a SemanticException
- checkDataTypeConsistencyInAlignByDevice(
- new ArrayList<>(deviceToTransformExpressionOfOneMeasurement.values()));
-
- // add outputExpressions
- Expression measurementExpressionWithoutAlias =
- ExpressionAnalyzer.removeAliasFromExpression(measurementExpression);
- String alias =
- !Objects.equals(measurementExpressionWithoutAlias, measurementExpression)
- ? measurementExpression.getExpressionString()
- : null;
- alias = hasAlias ? resultColumn.getAlias() : alias;
- ExpressionAnalyzer.updateTypeProvider(measurementExpressionWithoutAlias, typeProvider);
- measurementExpressionWithoutAlias.inferTypes(typeProvider);
- outputExpressions.add(new Pair<>(measurementExpressionWithoutAlias, alias));
-
- // add deviceToTransformExpressions
- for (String deviceName : deviceToTransformExpressionOfOneMeasurement.keySet()) {
- Expression transformExpression =
- deviceToTransformExpressionOfOneMeasurement.get(deviceName);
- ExpressionAnalyzer.updateTypeProvider(transformExpression, typeProvider);
- transformExpression.inferTypes(typeProvider);
- deviceToTransformExpressions
- .computeIfAbsent(deviceName, key -> new LinkedHashSet<>())
- .add(ExpressionAnalyzer.removeAliasFromExpression(transformExpression));
- deviceToMeasurementsMap
- .computeIfAbsent(deviceName, key -> new LinkedHashSet<>())
- .add(measurementExpressionWithoutAlias.getExpressionString());
- }
- paginationController.consumeLimit();
- } else {
- break;
- }
- }
- }
-
- return outputExpressions;
- }
-
- private Pair<Filter, Boolean> analyzeGlobalTimeFilter(QueryStatement queryStatement) {
- Filter globalTimeFilter = null;
- boolean hasValueFilter = false;
- if (queryStatement.getWhereCondition() != null) {
- Pair<Filter, Boolean> resultPair =
- ExpressionAnalyzer.transformToGlobalTimeFilter(
- queryStatement.getWhereCondition().getPredicate());
- globalTimeFilter = resultPair.left;
- hasValueFilter = resultPair.right;
- }
- if (queryStatement.isGroupByTime()) {
- GroupByTimeComponent groupByTimeComponent = queryStatement.getGroupByTimeComponent();
- Filter groupByFilter = initGroupByFilter(groupByTimeComponent);
- if (globalTimeFilter == null) {
- globalTimeFilter = groupByFilter;
- } else {
- // TODO: optimize the filter
- globalTimeFilter = FilterFactory.and(globalTimeFilter, groupByFilter);
- }
- }
- return new Pair<>(globalTimeFilter, hasValueFilter);
- }
-
- private void updateSource(
- Expression selectExpr, Set<Expression> sourceExpressions, boolean isRawDataSource) {
- sourceExpressions.addAll(
- ExpressionAnalyzer.searchSourceExpressions(selectExpr, isRawDataSource));
- }
-
- private boolean analyzeAggregation(
- Set<Expression> transformExpressions,
- Set<Expression> aggregationExpressions,
- Set<Expression> aggregationTransformExpressions) {
- // true if nested expressions and UDFs exist in aggregation function
- // i.e. select sum(s1 + 1) from root.sg.d1 align by device
- boolean isHasRawDataInputAggregation = false;
- for (Expression expression : transformExpressions) {
- for (Expression aggregationExpression :
- ExpressionAnalyzer.searchAggregationExpressions(expression)) {
- aggregationExpressions.add(aggregationExpression);
- aggregationTransformExpressions.addAll(aggregationExpression.getExpressions());
- }
- }
- for (Expression aggregationTransformExpression : aggregationTransformExpressions) {
- if (ExpressionAnalyzer.checkIsNeedTransform(aggregationTransformExpression)) {
- isHasRawDataInputAggregation = true;
- break;
- }
- }
- return isHasRawDataInputAggregation;
- }
-
- private Expression analyzeWhere(QueryStatement queryStatement, SchemaTree schemaTree) {
- List<Expression> rewrittenPredicates =
- ExpressionAnalyzer.removeWildcardInQueryFilter(
- queryStatement.getWhereCondition().getPredicate(),
- queryStatement.getFromComponent().getPrefixPaths(),
- schemaTree,
- typeProvider);
- return ExpressionUtils.constructQueryFilter(
- rewrittenPredicates.stream().distinct().collect(Collectors.toList()));
- }
-
- private Expression analyzeWhereSplitByDevice(
- QueryStatement queryStatement, PartialPath devicePath, SchemaTree schemaTree) {
- List<Expression> rewrittenPredicates =
- ExpressionAnalyzer.removeWildcardInQueryFilterByDevice(
- queryStatement.getWhereCondition().getPredicate(),
- devicePath,
- schemaTree,
- typeProvider);
- return ExpressionUtils.constructQueryFilter(
- rewrittenPredicates.stream().distinct().collect(Collectors.toList()));
- }
-
- private Map<Expression, Set<Expression>> analyzeGroupByLevel(
- QueryStatement queryStatement,
- List<Pair<Expression, String>> outputExpressions,
- Set<Expression> transformExpressions,
- Map<Expression, Expression> rawPathToGroupedPathMap) {
- GroupByLevelController groupByLevelController =
- new GroupByLevelController(
- queryStatement.getGroupByLevelComponent().getLevels(), typeProvider);
- for (int i = 0; i < outputExpressions.size(); i++) {
- Pair<Expression, String> measurementWithAlias = outputExpressions.get(i);
- boolean isCountStar = queryStatement.getGroupByLevelComponent().isCountStar(i);
- groupByLevelController.control(
- isCountStar, measurementWithAlias.left, measurementWithAlias.right);
- }
- Map<Expression, Set<Expression>> rawGroupByLevelExpressions =
- groupByLevelController.getGroupedPathMap();
- rawPathToGroupedPathMap.putAll(groupByLevelController.getRawPathToGroupedPathMap());
-
- Map<Expression, Set<Expression>> groupByLevelExpressions = new LinkedHashMap<>();
- ColumnPaginationController paginationController =
- new ColumnPaginationController(
- queryStatement.getSeriesLimit(), queryStatement.getSeriesOffset(), false);
- for (Expression groupedExpression : rawGroupByLevelExpressions.keySet()) {
- if (paginationController.hasCurOffset()) {
- paginationController.consumeOffset();
- continue;
- }
- if (paginationController.hasCurLimit()) {
- groupByLevelExpressions.put(
- groupedExpression, rawGroupByLevelExpressions.get(groupedExpression));
- paginationController.consumeLimit();
- } else {
- break;
- }
- }
-
- // reset outputExpressions & transformExpressions after applying SLIMIT/SOFFSET
- outputExpressions.clear();
- for (Expression groupedExpression : groupByLevelExpressions.keySet()) {
- TSDataType dataType =
- typeProvider.getType(
- new ArrayList<>(groupByLevelExpressions.get(groupedExpression))
- .get(0)
- .getExpressionString());
- typeProvider.setType(groupedExpression.getExpressionString(), dataType);
- outputExpressions.add(
- new Pair<>(
- groupedExpression,
- groupByLevelController.getAlias(groupedExpression.getExpressionString())));
- }
- transformExpressions.clear();
- transformExpressions.addAll(
- groupByLevelExpressions.values().stream()
- .flatMap(Set::stream)
- .collect(Collectors.toSet()));
- return groupByLevelExpressions;
- }
-
- private List<Expression> analyzeWithoutNullAlignByDevice(
- QueryStatement queryStatement, Set<Expression> outputExpressions) {
- List<Expression> resultFilterNullColumns = new ArrayList<>();
- List<Expression> rawFilterNullColumns =
- queryStatement.getFilterNullComponent().getWithoutNullColumns();
-
- // don't specify columns, by default, it is effective for all columns
- if (rawFilterNullColumns.isEmpty()) {
- resultFilterNullColumns.addAll(outputExpressions);
- return resultFilterNullColumns;
- }
-
- for (Expression filterNullColumn : rawFilterNullColumns) {
- if (!outputExpressions.contains(filterNullColumn)) {
- throw new SemanticException(
- String.format(
- "The without null column '%s' don't match the columns queried.",
- filterNullColumn));
- }
- resultFilterNullColumns.add(filterNullColumn);
- }
- return resultFilterNullColumns;
- }
-
- private List<Expression> analyzeWithoutNull(
- QueryStatement queryStatement,
- SchemaTree schemaTree,
- Set<Expression> transformExpressions) {
- List<Expression> resultFilterNullColumns = new ArrayList<>();
- List<Expression> rawFilterNullColumns =
- queryStatement.getFilterNullComponent().getWithoutNullColumns();
-
- // don't specify columns, by default, it is effective for all columns
- if (rawFilterNullColumns.isEmpty()) {
- resultFilterNullColumns.addAll(transformExpressions);
- return resultFilterNullColumns;
- }
-
- for (Expression filterNullColumn : rawFilterNullColumns) {
- List<Expression> resultExpressions =
- ExpressionAnalyzer.removeWildcardInExpression(filterNullColumn, schemaTree);
- for (Expression expression : resultExpressions) {
- Expression expressionWithoutAlias =
- ExpressionAnalyzer.removeAliasFromExpression(expression);
- if (!transformExpressions.contains(expressionWithoutAlias)) {
- throw new SemanticException(
- String.format(
- "The without null column '%s' don't match the columns queried.",
- filterNullColumn));
- }
- resultFilterNullColumns.add(expressionWithoutAlias);
- }
- }
- return resultFilterNullColumns;
- }
-
- private DatasetHeader analyzeOutput(
- QueryStatement queryStatement, List<Pair<Expression, String>> outputExpressions) {
- boolean isIgnoreTimestamp =
- queryStatement.isAggregationQuery() && !queryStatement.isGroupByTime();
- List<ColumnHeader> columnHeaders = new ArrayList<>();
- if (queryStatement.isAlignByDevice()) {
- columnHeaders.add(new ColumnHeader(HeaderConstant.COLUMN_DEVICE, TSDataType.TEXT, null));
- typeProvider.setType(HeaderConstant.COLUMN_DEVICE, TSDataType.TEXT);
- }
- columnHeaders.addAll(
- outputExpressions.stream()
- .map(
- expressionWithAlias -> {
- String columnName = expressionWithAlias.left.getExpressionString();
- String alias = expressionWithAlias.right;
- return new ColumnHeader(columnName, typeProvider.getType(columnName), alias);
- })
- .collect(Collectors.toList()));
- return new DatasetHeader(columnHeaders, isIgnoreTimestamp);
- }
-
- private Analysis analyzeLast(
- Analysis analysis, List<MeasurementPath> allSelectedPath, SchemaTree schemaTree) {
- Set<Expression> sourceExpressions =
- allSelectedPath.stream()
- .map(TimeSeriesOperand::new)
- .collect(Collectors.toCollection(LinkedHashSet::new));
- sourceExpressions.forEach(
- expression -> ExpressionAnalyzer.updateTypeProvider(expression, typeProvider));
- analysis.setSourceExpressions(sourceExpressions);
-
- analysis.setRespDatasetHeader(HeaderConstant.LAST_QUERY_HEADER);
- typeProvider.setType(HeaderConstant.COLUMN_TIMESERIES, TSDataType.TEXT);
- typeProvider.setType(HeaderConstant.COLUMN_VALUE, TSDataType.TEXT);
- typeProvider.setType(HeaderConstant.COLUMN_TIMESERIES_DATATYPE, TSDataType.TEXT);
-
- Set<String> deviceSet =
- allSelectedPath.stream().map(MeasurementPath::getDevice).collect(Collectors.toSet());
- Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
- for (String devicePath : deviceSet) {
- DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
- queryParam.setDevicePath(devicePath);
- sgNameToQueryParamsMap
- .computeIfAbsent(
- schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
- .add(queryParam);
- }
- DataPartition dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
- }
-
- private DataPartition fetchDataPartitionByDevices(
- Set<String> deviceSet, SchemaTree schemaTree) {
- Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
- for (String devicePath : deviceSet) {
- DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
- queryParam.setDevicePath(devicePath);
- sgNameToQueryParamsMap
- .computeIfAbsent(
- schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
- .add(queryParam);
- }
- return partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
- }
-
- /**
- * Check datatype consistency in ALIGN BY DEVICE.
- *
- * <p>an inconsistent example: select s0 from root.sg1.d1, root.sg1.d2 align by device, return
- * false while root.sg1.d1.s0 is INT32 and root.sg1.d2.s0 is FLOAT.
- */
- private void checkDataTypeConsistencyInAlignByDevice(List<Expression> expressions) {
- TSDataType checkedDataType = typeProvider.getType(expressions.get(0).getExpressionString());
- for (Expression expression : expressions) {
- if (typeProvider.getType(expression.getExpressionString()) != checkedDataType) {
- throw new SemanticException(
- "ALIGN BY DEVICE: the data types of the same measurement column should be the same across devices.");
- }
- }
- }
-
- @Override
- public Analysis visitLastPointFetch(
- LastPointFetchStatement statement, MPPQueryContext context) {
- context.setQueryType(QueryType.READ);
-
- Analysis analysis = new Analysis();
- analysis.setStatement(statement);
-
- SchemaTree schemaTree = new SchemaTree();
- schemaTree.setStorageGroups(statement.getStorageGroups());
-
- return analyzeLast(analysis, statement.getSelectedPaths(), schemaTree);
- }
-
- @Override
- public Analysis visitInsert(InsertStatement insertStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
- insertStatement.semanticCheck();
- long[] timeArray = insertStatement.getTimes();
- PartialPath devicePath = insertStatement.getDevice();
- String[] measurements = insertStatement.getMeasurementList();
- if (timeArray.length == 1) {
- // construct insert row statement
- InsertRowStatement insertRowStatement = new InsertRowStatement();
- insertRowStatement.setDevicePath(devicePath);
- insertRowStatement.setTime(timeArray[0]);
- insertRowStatement.setMeasurements(measurements);
- insertRowStatement.setDataTypes(
- new TSDataType[insertStatement.getMeasurementList().length]);
- Object[] values = new Object[insertStatement.getMeasurementList().length];
- System.arraycopy(insertStatement.getValuesList().get(0), 0, values, 0, values.length);
- insertRowStatement.setValues(values);
- insertRowStatement.setNeedInferType(true);
- insertRowStatement.setAligned(insertStatement.isAligned());
- return insertRowStatement.accept(this, context);
- } else {
- // construct insert rows statement
- // construct insert statement
- InsertRowsStatement insertRowsStatement = new InsertRowsStatement();
- List<InsertRowStatement> insertRowStatementList = new ArrayList<>();
- for (int i = 0; i < timeArray.length; i++) {
- InsertRowStatement statement = new InsertRowStatement();
- statement.setDevicePath(devicePath);
- statement.setMeasurements(measurements);
- statement.setTime(timeArray[i]);
- statement.setDataTypes(new TSDataType[insertStatement.getMeasurementList().length]);
- Object[] values = new Object[insertStatement.getMeasurementList().length];
- System.arraycopy(insertStatement.getValuesList().get(i), 0, values, 0, values.length);
- statement.setValues(values);
- statement.setAligned(insertStatement.isAligned());
- statement.setNeedInferType(true);
- insertRowStatementList.add(statement);
- }
- insertRowsStatement.setInsertRowStatementList(insertRowStatementList);
- return insertRowsStatement.accept(this, context);
- }
- }
-
- @Override
- public Analysis visitCreateTimeseries(
- CreateTimeSeriesStatement createTimeSeriesStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
- if (createTimeSeriesStatement.getTags() != null
- && !createTimeSeriesStatement.getTags().isEmpty()
- && createTimeSeriesStatement.getAttributes() != null
- && !createTimeSeriesStatement.getAttributes().isEmpty()) {
- for (String tagKey : createTimeSeriesStatement.getTags().keySet()) {
- if (createTimeSeriesStatement.getAttributes().containsKey(tagKey)) {
- throw new SemanticException(
- String.format(
- "Tag and attribute shouldn't have the same property key [%s]", tagKey));
- }
- }
- }
- Analysis analysis = new Analysis();
- analysis.setStatement(createTimeSeriesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendFullPath(createTimeSeriesStatement.getPath());
- SchemaPartition schemaPartitionInfo =
- partitionFetcher.getOrCreateSchemaPartition(patternTree);
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- return analysis;
- }
-
- @Override
- public Analysis visitCreateAlignedTimeseries(
- CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement,
- MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
- List<String> measurements = createAlignedTimeSeriesStatement.getMeasurements();
- Set<String> measurementsSet = new HashSet<>(measurements);
- if (measurementsSet.size() < measurements.size()) {
- throw new SemanticException(
- "Measurement under an aligned device is not allowed to have the same measurement name");
- }
-
- Analysis analysis = new Analysis();
- analysis.setStatement(createAlignedTimeSeriesStatement);
-
- PathPatternTree pathPatternTree = new PathPatternTree();
- for (String measurement : createAlignedTimeSeriesStatement.getMeasurements()) {
- pathPatternTree.appendFullPath(
- createAlignedTimeSeriesStatement.getDevicePath(), measurement);
- }
-
- SchemaPartition schemaPartitionInfo;
- schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(pathPatternTree);
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- return analysis;
- }
-
- @Override
- public Analysis visitInternalCreateTimeseries(
- InternalCreateTimeSeriesStatement internalCreateTimeSeriesStatement,
- MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
-
- Analysis analysis = new Analysis();
- analysis.setStatement(internalCreateTimeSeriesStatement);
-
- PathPatternTree pathPatternTree = new PathPatternTree();
- for (String measurement : internalCreateTimeSeriesStatement.getMeasurements()) {
- pathPatternTree.appendFullPath(
- internalCreateTimeSeriesStatement.getDevicePath(), measurement);
- }
-
- SchemaPartition schemaPartitionInfo;
- schemaPartitionInfo = partitionFetcher.getOrCreateSchemaPartition(pathPatternTree);
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- return analysis;
- }
-
- @Override
- public Analysis visitCreateMultiTimeseries(
- CreateMultiTimeSeriesStatement createMultiTimeSeriesStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
- Analysis analysis = new Analysis();
- analysis.setStatement(createMultiTimeSeriesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- for (PartialPath path : createMultiTimeSeriesStatement.getPaths()) {
- patternTree.appendFullPath(path);
- }
- SchemaPartition schemaPartitionInfo =
- partitionFetcher.getOrCreateSchemaPartition(patternTree);
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- return analysis;
- }
-
- @Override
- public Analysis visitAlterTimeseries(
- AlterTimeSeriesStatement alterTimeSeriesStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
- Analysis analysis = new Analysis();
- analysis.setStatement(alterTimeSeriesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendFullPath(alterTimeSeriesStatement.getPath());
- SchemaPartition schemaPartitionInfo;
- schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- return analysis;
- }
-
- @Override
- public Analysis visitInsertTablet(
- InsertTabletStatement insertTabletStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
-
- DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
- dataPartitionQueryParam.setDevicePath(insertTabletStatement.getDevicePath().getFullPath());
- dataPartitionQueryParam.setTimePartitionSlotList(
- insertTabletStatement.getTimePartitionSlots());
-
- DataPartition dataPartition =
- partitionFetcher.getOrCreateDataPartition(
- Collections.singletonList(dataPartitionQueryParam));
-
- Analysis analysis = new Analysis();
- analysis.setStatement(insertTabletStatement);
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
- }
-
- @Override
- public Analysis visitInsertRow(InsertRowStatement insertRowStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
-
- DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
- dataPartitionQueryParam.setDevicePath(insertRowStatement.getDevicePath().getFullPath());
- dataPartitionQueryParam.setTimePartitionSlotList(insertRowStatement.getTimePartitionSlots());
-
- DataPartition dataPartition =
- partitionFetcher.getOrCreateDataPartition(
- Collections.singletonList(dataPartitionQueryParam));
-
- Analysis analysis = new Analysis();
- analysis.setStatement(insertRowStatement);
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
- }
-
- @Override
- public Analysis visitInsertRows(
- InsertRowsStatement insertRowsStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
-
- List<DataPartitionQueryParam> dataPartitionQueryParams = new ArrayList<>();
- for (InsertRowStatement insertRowStatement :
- insertRowsStatement.getInsertRowStatementList()) {
- DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
- dataPartitionQueryParam.setDevicePath(insertRowStatement.getDevicePath().getFullPath());
- dataPartitionQueryParam.setTimePartitionSlotList(
- insertRowStatement.getTimePartitionSlots());
- dataPartitionQueryParams.add(dataPartitionQueryParam);
- }
-
- DataPartition dataPartition =
- partitionFetcher.getOrCreateDataPartition(dataPartitionQueryParams);
-
- Analysis analysis = new Analysis();
- analysis.setStatement(insertRowsStatement);
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
- }
-
- @Override
- public Analysis visitInsertMultiTablets(
- InsertMultiTabletsStatement insertMultiTabletsStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
-
- List<DataPartitionQueryParam> dataPartitionQueryParams = new ArrayList<>();
- for (InsertTabletStatement insertTabletStatement :
- insertMultiTabletsStatement.getInsertTabletStatementList()) {
- DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
- dataPartitionQueryParam.setDevicePath(insertTabletStatement.getDevicePath().getFullPath());
- dataPartitionQueryParam.setTimePartitionSlotList(
- insertTabletStatement.getTimePartitionSlots());
- dataPartitionQueryParams.add(dataPartitionQueryParam);
- }
-
- DataPartition dataPartition =
- partitionFetcher.getOrCreateDataPartition(dataPartitionQueryParams);
-
- Analysis analysis = new Analysis();
- analysis.setStatement(insertMultiTabletsStatement);
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
- }
-
- @Override
- public Analysis visitInsertRowsOfOneDevice(
- InsertRowsOfOneDeviceStatement insertRowsOfOneDeviceStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
-
- DataPartitionQueryParam dataPartitionQueryParam = new DataPartitionQueryParam();
- dataPartitionQueryParam.setDevicePath(
- insertRowsOfOneDeviceStatement.getDevicePath().getFullPath());
- dataPartitionQueryParam.setTimePartitionSlotList(
- insertRowsOfOneDeviceStatement.getTimePartitionSlots());
-
- DataPartition dataPartition =
- partitionFetcher.getOrCreateDataPartition(
- Collections.singletonList(dataPartitionQueryParam));
-
- Analysis analysis = new Analysis();
- analysis.setStatement(insertRowsOfOneDeviceStatement);
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
- }
-
- @Override
- public Analysis visitShowTimeSeries(
- ShowTimeSeriesStatement showTimeSeriesStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showTimeSeriesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(showTimeSeriesStatement.getPathPattern());
- SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
-
- if (showTimeSeriesStatement.isOrderByHeat()) {
- patternTree.constructTree();
- // request schema fetch API
- logger.info("{} fetch query schema...", getLogHeader());
- SchemaTree schemaTree = schemaFetcher.fetchSchema(patternTree);
- logger.info("{} fetch schema done", getLogHeader());
- List<MeasurementPath> allSelectedPath = schemaTree.getAllMeasurement();
-
- Set<Expression> sourceExpressions =
- allSelectedPath.stream()
- .map(TimeSeriesOperand::new)
- .collect(Collectors.toCollection(LinkedHashSet::new));
- analysis.setSourceExpressions(sourceExpressions);
-
- Set<String> deviceSet =
- allSelectedPath.stream().map(MeasurementPath::getDevice).collect(Collectors.toSet());
- Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
- for (String devicePath : deviceSet) {
- DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
- queryParam.setDevicePath(devicePath);
- sgNameToQueryParamsMap
- .computeIfAbsent(
- schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
- .add(queryParam);
- }
- DataPartition dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
- analysis.setDataPartitionInfo(dataPartition);
- }
-
- analysis.setRespDatasetHeader(HeaderConstant.showTimeSeriesHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitShowStorageGroup(
- ShowStorageGroupStatement showStorageGroupStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showStorageGroupStatement);
- analysis.setRespDatasetHeader(HeaderConstant.showStorageGroupHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitShowTTL(ShowTTLStatement showTTLStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showTTLStatement);
- analysis.setRespDatasetHeader(HeaderConstant.showTTLHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitShowDevices(
- ShowDevicesStatement showDevicesStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showDevicesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(
- showDevicesStatement.getPathPattern().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD));
- SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
-
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- analysis.setRespDatasetHeader(
- showDevicesStatement.hasSgCol()
- ? HeaderConstant.showDevicesWithSgHeader
- : HeaderConstant.showDevicesHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitShowCluster(
- ShowClusterStatement showClusterStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showClusterStatement);
- analysis.setRespDatasetHeader(HeaderConstant.showClusterHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitCountStorageGroup(
- CountStorageGroupStatement countStorageGroupStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(countStorageGroupStatement);
- analysis.setRespDatasetHeader(HeaderConstant.countStorageGroupHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitSchemaFetch(
- SchemaFetchStatement schemaFetchStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(schemaFetchStatement);
- analysis.setSchemaPartitionInfo(schemaFetchStatement.getSchemaPartition());
- return analysis;
- }
-
- @Override
- public Analysis visitCountDevices(
- CountDevicesStatement countDevicesStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(countDevicesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(
- countDevicesStatement.getPartialPath().concatNode(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD));
- SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
-
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- analysis.setRespDatasetHeader(HeaderConstant.countDevicesHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitCountTimeSeries(
- CountTimeSeriesStatement countTimeSeriesStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(countTimeSeriesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(countTimeSeriesStatement.getPartialPath());
- SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
-
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- analysis.setRespDatasetHeader(HeaderConstant.countTimeSeriesHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitCountLevelTimeSeries(
- CountLevelTimeSeriesStatement countLevelTimeSeriesStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(countLevelTimeSeriesStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(countLevelTimeSeriesStatement.getPartialPath());
- SchemaPartition schemaPartitionInfo = partitionFetcher.getSchemaPartition(patternTree);
-
- analysis.setSchemaPartitionInfo(schemaPartitionInfo);
- analysis.setRespDatasetHeader(HeaderConstant.countLevelTimeSeriesHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitCountNodes(CountNodesStatement countStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(countStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(countStatement.getPartialPath());
- SchemaNodeManagementPartition schemaNodeManagementPartition =
- partitionFetcher.getSchemaNodeManagementPartitionWithLevel(
- patternTree, countStatement.getLevel());
-
- if (schemaNodeManagementPartition == null) {
- return analysis;
- }
- if (!schemaNodeManagementPartition.getMatchedNode().isEmpty()
- && schemaNodeManagementPartition.getSchemaPartition().getSchemaPartitionMap().size()
- == 0) {
- analysis.setFinishQueryAfterAnalyze(true);
- }
- analysis.setMatchedNodes(schemaNodeManagementPartition.getMatchedNode());
- analysis.setSchemaPartitionInfo(schemaNodeManagementPartition.getSchemaPartition());
- analysis.setRespDatasetHeader(HeaderConstant.countNodesHeader);
- return analysis;
- }
-
- @Override
- public Analysis visitShowChildPaths(
- ShowChildPathsStatement showChildPathsStatement, MPPQueryContext context) {
- return visitSchemaNodeManagementPartition(
- showChildPathsStatement,
- showChildPathsStatement.getPartialPath(),
- HeaderConstant.showChildPathsHeader);
- }
-
- @Override
- public Analysis visitShowChildNodes(
- ShowChildNodesStatement showChildNodesStatement, MPPQueryContext context) {
- return visitSchemaNodeManagementPartition(
- showChildNodesStatement,
- showChildNodesStatement.getPartialPath(),
- HeaderConstant.showChildNodesHeader);
- }
-
- @Override
- public Analysis visitShowVersion(
- ShowVersionStatement showVersionStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showVersionStatement);
- analysis.setRespDatasetHeader(HeaderConstant.showVersionHeader);
- analysis.setFinishQueryAfterAnalyze(true);
- return analysis;
- }
-
- private Analysis visitSchemaNodeManagementPartition(
- Statement statement, PartialPath path, DatasetHeader header) {
- Analysis analysis = new Analysis();
- analysis.setStatement(statement);
-
- PathPatternTree patternTree = new PathPatternTree();
- patternTree.appendPathPattern(path);
- SchemaNodeManagementPartition schemaNodeManagementPartition =
- partitionFetcher.getSchemaNodeManagementPartition(patternTree);
-
- if (schemaNodeManagementPartition == null) {
- return analysis;
- }
- if (!schemaNodeManagementPartition.getMatchedNode().isEmpty()
- && schemaNodeManagementPartition.getSchemaPartition().getSchemaPartitionMap().size()
- == 0) {
- analysis.setFinishQueryAfterAnalyze(true);
- }
- analysis.setMatchedNodes(schemaNodeManagementPartition.getMatchedNode());
- analysis.setSchemaPartitionInfo(schemaNodeManagementPartition.getSchemaPartition());
- analysis.setRespDatasetHeader(header);
- return analysis;
- }
-
- @Override
- public Analysis visitDeleteData(
- DeleteDataStatement deleteDataStatement, MPPQueryContext context) {
- context.setQueryType(QueryType.WRITE);
- Analysis analysis = new Analysis();
- analysis.setStatement(deleteDataStatement);
-
- PathPatternTree patternTree = new PathPatternTree();
- for (PartialPath pathPattern : deleteDataStatement.getPathList()) {
- patternTree.appendPathPattern(pathPattern);
- }
-
- SchemaPartition schemaPartition = partitionFetcher.getSchemaPartition(patternTree);
-
- SchemaTree schemaTree = schemaFetcher.fetchSchema(patternTree, schemaPartition);
- analysis.setSchemaTree(schemaTree);
-
- Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
-
- Map<String, Map<TSeriesPartitionSlot, TRegionReplicaSet>> schemaPartitionMap =
- schemaPartition.getSchemaPartitionMap();
-
- // todo keep the behaviour consistency of cluster and standalone,
- // the behaviour of standalone fetcher and LocalConfigNode is not consistent with that of
- // cluster mode's
- if (IoTDBDescriptor.getInstance().getConfig().isClusterMode()) {
- for (String storageGroup : schemaPartitionMap.keySet()) {
- sgNameToQueryParamsMap.put(
- storageGroup,
- schemaPartitionMap.get(storageGroup).keySet().stream()
- .map(DataPartitionQueryParam::new)
- .collect(Collectors.toList()));
- }
- } else {
- // the StandalonePartitionFetcher and LocalConfigNode now doesn't support partition fetch
- // via slotId
- schemaTree
- .getMatchedDevices(new PartialPath(ALL_RESULT_NODES))
- .forEach(
- deviceSchemaInfo -> {
- PartialPath devicePath = deviceSchemaInfo.getDevicePath();
- DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
- queryParam.setDevicePath(devicePath.getFullPath());
- sgNameToQueryParamsMap
- .computeIfAbsent(
- schemaTree.getBelongedStorageGroup(devicePath), key -> new ArrayList<>())
- .add(queryParam);
- });
- }
-
- DataPartition dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
- analysis.setDataPartitionInfo(dataPartition);
-
- if (dataPartition.isEmpty()) {
- analysis.setFinishQueryAfterAnalyze(true);
- }
-
- return analysis;
- }
-
- @Override
- public Analysis visitCreateSchemaTemplate(
- CreateSchemaTemplateStatement createTemplateStatement, MPPQueryContext context) {
-
- context.setQueryType(QueryType.WRITE);
- List<List<String>> measurementsList = createTemplateStatement.getMeasurements();
- for (List measurements : measurementsList) {
- Set<String> measurementsSet = new HashSet<>(measurements);
- if (measurementsSet.size() < measurements.size()) {
- throw new SemanticException(
- "Measurement under an aligned device is not allowed to have the same measurement name");
- }
- }
- Analysis analysis = new Analysis();
- analysis.setStatement(createTemplateStatement);
- return analysis;
- }
-
- @Override
- public Analysis visitShowNodesInSchemaTemplate(
- ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement,
- MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showNodesInSchemaTemplateStatement);
- analysis.setRespDatasetHeader(HeaderConstant.showNodesInSchemaTemplate);
- return analysis;
- }
-
- @Override
- public Analysis visitShowSchemaTemplate(
- ShowSchemaTemplateStatement showSchemaTemplateStatement, MPPQueryContext context) {
- Analysis analysis = new Analysis();
- analysis.setStatement(showSchemaTemplateStatement);
- analysis.setRespDatasetHeader(HeaderConstant.showSchemaTemplate);
- return analysis;
- }
- }
-
- private GroupByFilter initGroupByFilter(GroupByTimeComponent groupByTimeComponent) {
- if (groupByTimeComponent.isIntervalByMonth() || groupByTimeComponent.isSlidingStepByMonth()) {
- return new GroupByMonthFilter(
- groupByTimeComponent.getInterval(),
- groupByTimeComponent.getSlidingStep(),
- groupByTimeComponent.getStartTime(),
- groupByTimeComponent.getEndTime(),
- groupByTimeComponent.isSlidingStepByMonth(),
- groupByTimeComponent.isIntervalByMonth(),
- TimeZone.getTimeZone("+00:00"));
- } else {
- return new GroupByFilter(
- groupByTimeComponent.getInterval(),
- groupByTimeComponent.getSlidingStep(),
- groupByTimeComponent.getStartTime(),
- groupByTimeComponent.getEndTime());
- }
+ return new AnalyzeVisitor(partitionFetcher, schemaFetcher, typeProvider, context)
+ .process(statement, context);
}
}
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
new file mode 100644
index 0000000000..f711c9a387
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java
@@ -0,0 +1,679 @@
+/*
+ * 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;
+
+import org.apache.iotdb.db.mpp.common.MPPQueryContext;
+import org.apache.iotdb.db.mpp.plan.analyze.Analysis;
+import org.apache.iotdb.db.mpp.plan.analyze.ExpressionAnalyzer;
+import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.AlterTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.InternalCreateTimeSeriesNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.MeasurementGroup;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.DeleteDataNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertMultiTabletsNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowsNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowsOfOneDeviceNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertTabletNode;
+import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.AggregationStep;
+import org.apache.iotdb.db.mpp.plan.statement.StatementNode;
+import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
+import org.apache.iotdb.db.mpp.plan.statement.crud.DeleteDataStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertMultiTabletsStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsOfOneDeviceStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.InsertTabletStatement;
+import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
+import org.apache.iotdb.db.mpp.plan.statement.internal.InternalCreateTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.internal.LastPointFetchStatement;
+import org.apache.iotdb.db.mpp.plan.statement.internal.SchemaFetchStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.AlterTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountDevicesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildNodesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildPathsStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDevicesStatement;
+import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+/**
+ * This visitor is used to generate a logical plan for the statement and returns the {@link
+ * PlanNode}.
+ */
+public class LogicalPlanVisitor extends StatementVisitor<PlanNode, MPPQueryContext> {
+
+ private final Analysis analysis;
+
+ public LogicalPlanVisitor(Analysis analysis) {
+ this.analysis = analysis;
+ }
+
+ @Override
+ public PlanNode visitNode(StatementNode node, MPPQueryContext context) {
+ throw new UnsupportedOperationException(
+ "Unsupported statement type: " + node.getClass().getName());
+ }
+
+ @Override
+ public PlanNode visitQuery(QueryStatement queryStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+
+ if (queryStatement.isLastQuery()) {
+ return planBuilder
+ .planLast(analysis.getSourceExpressions(), analysis.getGlobalTimeFilter())
+ .getRoot();
+ }
+
+ if (queryStatement.isAlignByDevice()) {
+ Map<String, PlanNode> deviceToSubPlanMap = new TreeMap<>();
+ for (String deviceName : analysis.getDeviceToSourceExpressions().keySet()) {
+ LogicalPlanBuilder subPlanBuilder = new LogicalPlanBuilder(context);
+ subPlanBuilder =
+ subPlanBuilder.withNewRoot(
+ visitQueryBody(
+ queryStatement,
+ analysis.getDeviceToIsRawDataSource().get(deviceName),
+ analysis.getDeviceToSourceExpressions().get(deviceName),
+ analysis.getDeviceToAggregationExpressions().get(deviceName),
+ analysis.getDeviceToAggregationTransformExpressions().get(deviceName),
+ analysis.getDeviceToTransformExpressions().get(deviceName),
+ analysis.getDeviceToQueryFilter() != null
+ ? analysis.getDeviceToQueryFilter().get(deviceName)
+ : null,
+ analysis.getDeviceToMeasurementIndexesMap().get(deviceName),
+ context));
+ deviceToSubPlanMap.put(deviceName, subPlanBuilder.getRoot());
+ }
+ // convert to ALIGN BY DEVICE view
+ planBuilder =
+ planBuilder.planDeviceView(
+ deviceToSubPlanMap,
+ analysis.getRespDatasetHeader().getColumnNameWithoutAlias().stream()
+ .distinct()
+ .collect(Collectors.toList()),
+ analysis.getDeviceToMeasurementIndexesMap(),
+ queryStatement.getResultOrder());
+ } else {
+ planBuilder =
+ planBuilder.withNewRoot(
+ visitQueryBody(
+ queryStatement,
+ analysis.isRawDataSource(),
+ analysis.getSourceExpressions(),
+ analysis.getAggregationExpressions(),
+ analysis.getAggregationTransformExpressions(),
+ analysis.getTransformExpressions(),
+ analysis.getQueryFilter(),
+ null,
+ context));
+ }
+
+ // other common upstream node
+ planBuilder =
+ planBuilder
+ .planFilterNull(analysis.getFilterNullParameter())
+ .planFill(analysis.getFillDescriptor(), queryStatement.getResultOrder())
+ .planOffset(queryStatement.getRowOffset())
+ .planLimit(queryStatement.getRowLimit());
+
+ return planBuilder.getRoot();
+ }
+
+ public PlanNode visitQueryBody(
+ QueryStatement queryStatement,
+ boolean isRawDataSource,
+ Set<Expression> sourceExpressions,
+ Set<Expression> aggregationExpressions,
+ Set<Expression> aggregationTransformExpressions,
+ Set<Expression> transformExpressions,
+ Expression queryFilter,
+ List<Integer> measurementIndexes, // only used in ALIGN BY DEVICE
+ MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+
+ // plan data source node
+ if (isRawDataSource) {
+ planBuilder =
+ planBuilder.planRawDataSource(
+ sourceExpressions, queryStatement.getResultOrder(), analysis.getGlobalTimeFilter());
+
+ if (queryStatement.isAggregationQuery()) {
+ if (analysis.hasValueFilter()) {
+ planBuilder =
+ planBuilder.planFilterAndTransform(
+ queryFilter,
+ aggregationTransformExpressions,
+ queryStatement.isGroupByTime(),
+ queryStatement.getSelectComponent().getZoneId(),
+ queryStatement.getResultOrder());
+ } else {
+ planBuilder =
+ planBuilder.planTransform(
+ aggregationTransformExpressions,
+ queryStatement.isGroupByTime(),
+ queryStatement.getSelectComponent().getZoneId(),
+ queryStatement.getResultOrder());
+ }
+
+ boolean outputPartial =
+ queryStatement.isGroupByLevel()
+ || (queryStatement.isGroupByTime()
+ && analysis.getGroupByTimeParameter().hasOverlap());
+ AggregationStep curStep = outputPartial ? AggregationStep.PARTIAL : AggregationStep.SINGLE;
+ planBuilder =
+ planBuilder.planAggregation(
+ aggregationExpressions,
+ analysis.getGroupByTimeParameter(),
+ curStep,
+ analysis.getTypeProvider(),
+ queryStatement.getResultOrder());
+
+ if (curStep.isOutputPartial()) {
+ if (queryStatement.isGroupByTime() && analysis.getGroupByTimeParameter().hasOverlap()) {
+ curStep =
+ queryStatement.isGroupByLevel()
+ ? AggregationStep.INTERMEDIATE
+ : AggregationStep.FINAL;
+ planBuilder =
+ planBuilder.planSlidingWindowAggregation(
+ aggregationExpressions,
+ analysis.getGroupByTimeParameter(),
+ curStep,
+ queryStatement.getResultOrder());
+ }
+
+ if (queryStatement.isGroupByLevel()) {
+ curStep = AggregationStep.FINAL;
+ planBuilder =
+ planBuilder.planGroupByLevel(
+ analysis.getGroupByLevelExpressions(),
+ curStep,
+ analysis.getGroupByTimeParameter(),
+ queryStatement.getResultOrder());
+ }
+ }
+
+ planBuilder =
+ planBuilder.planTransform(
+ transformExpressions,
+ queryStatement.isGroupByTime(),
+ queryStatement.getSelectComponent().getZoneId(),
+ queryStatement.getResultOrder());
+ } else {
+ if (analysis.hasValueFilter()) {
+ planBuilder =
+ planBuilder.planFilterAndTransform(
+ queryFilter,
+ transformExpressions,
+ queryStatement.isGroupByTime(),
+ queryStatement.getSelectComponent().getZoneId(),
+ queryStatement.getResultOrder());
+ } else {
+ planBuilder =
+ planBuilder.planTransform(
+ transformExpressions,
+ queryStatement.isGroupByTime(),
+ queryStatement.getSelectComponent().getZoneId(),
+ queryStatement.getResultOrder());
+ }
+ }
+ } else {
+ AggregationStep curStep =
+ (analysis.getGroupByLevelExpressions() != null
+ || (analysis.getGroupByTimeParameter() != null
+ && analysis.getGroupByTimeParameter().hasOverlap()))
+ ? AggregationStep.PARTIAL
+ : AggregationStep.SINGLE;
+
+ boolean needTransform = false;
+ for (Expression expression : transformExpressions) {
+ if (ExpressionAnalyzer.checkIsNeedTransform(expression)) {
+ needTransform = true;
+ break;
+ }
+ }
+
+ if (!needTransform && measurementIndexes != null) {
+ planBuilder =
+ planBuilder.planAggregationSourceWithIndexAdjust(
+ sourceExpressions,
+ curStep,
+ queryStatement.getResultOrder(),
+ analysis.getGlobalTimeFilter(),
+ analysis.getGroupByTimeParameter(),
+ aggregationExpressions,
+ measurementIndexes,
+ analysis.getGroupByLevelExpressions(),
+ analysis.getTypeProvider());
+ } else {
+ planBuilder =
+ planBuilder
+ .planAggregationSource(
+ sourceExpressions,
+ curStep,
+ queryStatement.getResultOrder(),
+ analysis.getGlobalTimeFilter(),
+ analysis.getGroupByTimeParameter(),
+ aggregationExpressions,
+ analysis.getGroupByLevelExpressions(),
+ analysis.getTypeProvider())
+ .planTransform(
+ transformExpressions,
+ queryStatement.isGroupByTime(),
+ queryStatement.getSelectComponent().getZoneId(),
+ queryStatement.getResultOrder());
+ }
+ }
+
+ return planBuilder.getRoot();
+ }
+
+ public PlanNode visitLastPointFetch(
+ LastPointFetchStatement lastPointFetchStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder.planLast(analysis.getSourceExpressions(), null).getRoot();
+ }
+
+ @Override
+ public PlanNode visitCreateTimeseries(
+ CreateTimeSeriesStatement createTimeSeriesStatement, MPPQueryContext context) {
+ return new CreateTimeSeriesNode(
+ context.getQueryId().genPlanNodeId(),
+ createTimeSeriesStatement.getPath(),
+ createTimeSeriesStatement.getDataType(),
+ createTimeSeriesStatement.getEncoding(),
+ createTimeSeriesStatement.getCompressor(),
+ createTimeSeriesStatement.getProps(),
+ createTimeSeriesStatement.getTags(),
+ createTimeSeriesStatement.getAttributes(),
+ createTimeSeriesStatement.getAlias());
+ }
+
+ @Override
+ public PlanNode visitCreateAlignedTimeseries(
+ CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement, MPPQueryContext context) {
+ return new CreateAlignedTimeSeriesNode(
+ context.getQueryId().genPlanNodeId(),
+ createAlignedTimeSeriesStatement.getDevicePath(),
+ createAlignedTimeSeriesStatement.getMeasurements(),
+ createAlignedTimeSeriesStatement.getDataTypes(),
+ createAlignedTimeSeriesStatement.getEncodings(),
+ createAlignedTimeSeriesStatement.getCompressors(),
+ createAlignedTimeSeriesStatement.getAliasList(),
+ createAlignedTimeSeriesStatement.getTagsList(),
+ createAlignedTimeSeriesStatement.getAttributesList());
+ }
+
+ @Override
+ public PlanNode visitInternalCreateTimeseries(
+ InternalCreateTimeSeriesStatement internalCreateTimeSeriesStatement,
+ MPPQueryContext context) {
+ int size = internalCreateTimeSeriesStatement.getMeasurements().size();
+
+ MeasurementGroup measurementGroup = new MeasurementGroup();
+ for (int i = 0; i < size; i++) {
+ measurementGroup.addMeasurement(
+ internalCreateTimeSeriesStatement.getMeasurements().get(i),
+ internalCreateTimeSeriesStatement.getTsDataTypes().get(i),
+ internalCreateTimeSeriesStatement.getEncodings().get(i),
+ internalCreateTimeSeriesStatement.getCompressors().get(i));
+ }
+
+ return new InternalCreateTimeSeriesNode(
+ context.getQueryId().genPlanNodeId(),
+ internalCreateTimeSeriesStatement.getDevicePath(),
+ measurementGroup,
+ internalCreateTimeSeriesStatement.isAligned());
+ }
+
+ @Override
+ public PlanNode visitCreateMultiTimeseries(
+ CreateMultiTimeSeriesStatement createMultiTimeSeriesStatement, MPPQueryContext context) {
+ return new CreateMultiTimeSeriesNode(
+ context.getQueryId().genPlanNodeId(),
+ createMultiTimeSeriesStatement.getPaths(),
+ createMultiTimeSeriesStatement.getDataTypes(),
+ createMultiTimeSeriesStatement.getEncodings(),
+ createMultiTimeSeriesStatement.getCompressors(),
+ createMultiTimeSeriesStatement.getPropsList(),
+ createMultiTimeSeriesStatement.getAliasList(),
+ createMultiTimeSeriesStatement.getTagsList(),
+ createMultiTimeSeriesStatement.getAttributesList());
+ }
+
+ @Override
+ public PlanNode visitAlterTimeseries(
+ AlterTimeSeriesStatement alterTimeSeriesStatement, MPPQueryContext context) {
+ return new AlterTimeSeriesNode(
+ context.getQueryId().genPlanNodeId(),
+ alterTimeSeriesStatement.getPath(),
+ alterTimeSeriesStatement.getAlterType(),
+ alterTimeSeriesStatement.getAlterMap(),
+ alterTimeSeriesStatement.getAlias(),
+ alterTimeSeriesStatement.getTagsMap(),
+ alterTimeSeriesStatement.getAttributesMap());
+ }
+
+ @Override
+ public PlanNode visitInsertTablet(
+ InsertTabletStatement insertTabletStatement, MPPQueryContext context) {
+ // convert insert statement to insert node
+ return new InsertTabletNode(
+ context.getQueryId().genPlanNodeId(),
+ insertTabletStatement.getDevicePath(),
+ insertTabletStatement.isAligned(),
+ insertTabletStatement.getMeasurements(),
+ insertTabletStatement.getDataTypes(),
+ insertTabletStatement.getTimes(),
+ insertTabletStatement.getBitMaps(),
+ insertTabletStatement.getColumns(),
+ insertTabletStatement.getRowCount());
+ }
+
+ @Override
+ public PlanNode visitInsertRow(InsertRowStatement insertRowStatement, MPPQueryContext context) {
+ // convert insert statement to insert node
+ return new InsertRowNode(
+ context.getQueryId().genPlanNodeId(),
+ insertRowStatement.getDevicePath(),
+ insertRowStatement.isAligned(),
+ insertRowStatement.getMeasurements(),
+ insertRowStatement.getDataTypes(),
+ insertRowStatement.getTime(),
+ insertRowStatement.getValues(),
+ insertRowStatement.isNeedInferType());
+ }
+
+ @Override
+ public PlanNode visitShowTimeSeries(
+ ShowTimeSeriesStatement showTimeSeriesStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(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
+ && !showTimeSeriesStatement.isOrderByHeat();
+
+ int limit = showTimeSeriesStatement.getLimit();
+ int offset = showTimeSeriesStatement.getOffset();
+ if (showTimeSeriesStatement.isOrderByHeat()) {
+ limit = 0;
+ offset = 0;
+ } else if (!canPushDownOffsetLimit) {
+ limit = showTimeSeriesStatement.getLimit() + showTimeSeriesStatement.getOffset();
+ offset = 0;
+ }
+ planBuilder =
+ planBuilder
+ .planTimeSeriesSchemaSource(
+ showTimeSeriesStatement.getPathPattern(),
+ showTimeSeriesStatement.getKey(),
+ showTimeSeriesStatement.getValue(),
+ limit,
+ offset,
+ showTimeSeriesStatement.isOrderByHeat(),
+ showTimeSeriesStatement.isContains(),
+ showTimeSeriesStatement.isPrefixPath())
+ .planSchemaQueryMerge(showTimeSeriesStatement.isOrderByHeat());
+ // show latest timeseries
+ if (showTimeSeriesStatement.isOrderByHeat()
+ && null != analysis.getDataPartitionInfo()
+ && 0 != analysis.getDataPartitionInfo().getDataPartitionMap().size()) {
+ PlanNode lastPlanNode =
+ new LogicalPlanBuilder(context)
+ .planLast(analysis.getSourceExpressions(), analysis.getGlobalTimeFilter())
+ .getRoot();
+ planBuilder = planBuilder.planSchemaQueryOrderByHeat(lastPlanNode);
+ }
+
+ if (canPushDownOffsetLimit) {
+ return planBuilder.getRoot();
+ }
+
+ return planBuilder
+ .planOffset(showTimeSeriesStatement.getOffset())
+ .planLimit(showTimeSeriesStatement.getLimit())
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitShowDevices(
+ ShowDevicesStatement showDevicesStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(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;
+
+ int limit = showDevicesStatement.getLimit();
+ int offset = showDevicesStatement.getOffset();
+ if (!canPushDownOffsetLimit) {
+ limit = showDevicesStatement.getLimit() + showDevicesStatement.getOffset();
+ offset = 0;
+ }
+
+ planBuilder =
+ planBuilder
+ .planDeviceSchemaSource(
+ showDevicesStatement.getPathPattern(),
+ limit,
+ offset,
+ showDevicesStatement.isPrefixPath(),
+ showDevicesStatement.hasSgCol())
+ .planSchemaQueryMerge(false);
+
+ if (!canPushDownOffsetLimit) {
+ return planBuilder
+ .planOffset(showDevicesStatement.getOffset())
+ .planLimit(showDevicesStatement.getLimit())
+ .getRoot();
+ }
+ return planBuilder.getRoot();
+ }
+
+ @Override
+ public PlanNode visitCountDevices(
+ CountDevicesStatement countDevicesStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planDevicesCountSource(
+ countDevicesStatement.getPartialPath(), countDevicesStatement.isPrefixPath())
+ .planCountMerge()
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitCountTimeSeries(
+ CountTimeSeriesStatement countTimeSeriesStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planTimeSeriesCountSource(
+ countTimeSeriesStatement.getPartialPath(), countTimeSeriesStatement.isPrefixPath())
+ .planCountMerge()
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitCountLevelTimeSeries(
+ CountLevelTimeSeriesStatement countLevelTimeSeriesStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planLevelTimeSeriesCountSource(
+ countLevelTimeSeriesStatement.getPartialPath(),
+ countLevelTimeSeriesStatement.isPrefixPath(),
+ countLevelTimeSeriesStatement.getLevel())
+ .planCountMerge()
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitCountNodes(CountNodesStatement countStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planNodePathsSchemaSource(countStatement.getPartialPath(), countStatement.getLevel())
+ .planSchemaQueryMerge(false)
+ .planNodeManagementMemoryMerge(analysis.getMatchedNodes())
+ .planNodePathsCount()
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitInsertRows(
+ InsertRowsStatement insertRowsStatement, MPPQueryContext context) {
+ // convert insert statement to insert node
+ InsertRowsNode insertRowsNode = new InsertRowsNode(context.getQueryId().genPlanNodeId());
+ for (int i = 0; i < insertRowsStatement.getInsertRowStatementList().size(); i++) {
+ InsertRowStatement insertRowStatement =
+ insertRowsStatement.getInsertRowStatementList().get(i);
+ insertRowsNode.addOneInsertRowNode(
+ new InsertRowNode(
+ insertRowsNode.getPlanNodeId(),
+ insertRowStatement.getDevicePath(),
+ insertRowStatement.isAligned(),
+ insertRowStatement.getMeasurements(),
+ insertRowStatement.getDataTypes(),
+ insertRowStatement.getTime(),
+ insertRowStatement.getValues(),
+ insertRowStatement.isNeedInferType()),
+ i);
+ }
+ return insertRowsNode;
+ }
+
+ @Override
+ public PlanNode visitInsertMultiTablets(
+ InsertMultiTabletsStatement insertMultiTabletsStatement, MPPQueryContext context) {
+ // convert insert statement to insert node
+ InsertMultiTabletsNode insertMultiTabletsNode =
+ new InsertMultiTabletsNode(context.getQueryId().genPlanNodeId());
+ for (int i = 0; i < insertMultiTabletsStatement.getInsertTabletStatementList().size(); i++) {
+ InsertTabletStatement insertTabletStatement =
+ insertMultiTabletsStatement.getInsertTabletStatementList().get(i);
+ insertMultiTabletsNode.addInsertTabletNode(
+ new InsertTabletNode(
+ insertMultiTabletsNode.getPlanNodeId(),
+ insertTabletStatement.getDevicePath(),
+ insertTabletStatement.isAligned(),
+ insertTabletStatement.getMeasurements(),
+ insertTabletStatement.getDataTypes(),
+ insertTabletStatement.getTimes(),
+ insertTabletStatement.getBitMaps(),
+ insertTabletStatement.getColumns(),
+ insertTabletStatement.getRowCount()),
+ i);
+ }
+ return insertMultiTabletsNode;
+ }
+
+ @Override
+ public PlanNode visitInsertRowsOfOneDevice(
+ InsertRowsOfOneDeviceStatement insertRowsOfOneDeviceStatement, MPPQueryContext context) {
+ // convert insert statement to insert node
+ InsertRowsOfOneDeviceNode insertRowsOfOneDeviceNode =
+ new InsertRowsOfOneDeviceNode(context.getQueryId().genPlanNodeId());
+
+ List<InsertRowNode> insertRowNodeList = new ArrayList<>();
+ List<Integer> insertRowNodeIndexList = new ArrayList<>();
+ for (int i = 0; i < insertRowsOfOneDeviceStatement.getInsertRowStatementList().size(); i++) {
+ InsertRowStatement insertRowStatement =
+ insertRowsOfOneDeviceStatement.getInsertRowStatementList().get(i);
+ insertRowNodeList.add(
+ new InsertRowNode(
+ insertRowsOfOneDeviceNode.getPlanNodeId(),
+ insertRowStatement.getDevicePath(),
+ insertRowStatement.isAligned(),
+ insertRowStatement.getMeasurements(),
+ insertRowStatement.getDataTypes(),
+ insertRowStatement.getTime(),
+ insertRowStatement.getValues(),
+ insertRowStatement.isNeedInferType()));
+ insertRowNodeIndexList.add(i);
+ }
+
+ insertRowsOfOneDeviceNode.setInsertRowNodeList(insertRowNodeList);
+ insertRowsOfOneDeviceNode.setInsertRowNodeIndexList(insertRowNodeIndexList);
+ return insertRowsOfOneDeviceNode;
+ }
+
+ @Override
+ public PlanNode visitSchemaFetch(
+ SchemaFetchStatement schemaFetchStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planSchemaFetchMerge()
+ .planSchemaFetchSource(
+ new ArrayList<>(
+ schemaFetchStatement.getSchemaPartition().getSchemaPartitionMap().keySet()),
+ schemaFetchStatement.getPatternTree())
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitShowChildPaths(
+ ShowChildPathsStatement showChildPathsStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planNodePathsSchemaSource(showChildPathsStatement.getPartialPath(), -1)
+ .planSchemaQueryMerge(false)
+ .planNodeManagementMemoryMerge(analysis.getMatchedNodes())
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitShowChildNodes(
+ ShowChildNodesStatement showChildNodesStatement, MPPQueryContext context) {
+ LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
+ return planBuilder
+ .planNodePathsSchemaSource(showChildNodesStatement.getPartialPath(), -1)
+ .planSchemaQueryMerge(false)
+ .planNodeManagementMemoryMerge(analysis.getMatchedNodes())
+ .planNodePathsConvert()
+ .getRoot();
+ }
+
+ @Override
+ public PlanNode visitDeleteData(
+ DeleteDataStatement deleteDataStatement, MPPQueryContext context) {
+ return new DeleteDataNode(
+ context.getQueryId().genPlanNodeId(),
+ deleteDataStatement.getPathList(),
+ deleteDataStatement.getDeleteStartTime(),
+ deleteDataStatement.getDeleteEndTime());
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java
index cac693ec6e..308887f53a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java
@@ -20,55 +20,12 @@ package org.apache.iotdb.db.mpp.plan.planner;
import org.apache.iotdb.db.mpp.common.MPPQueryContext;
import org.apache.iotdb.db.mpp.plan.analyze.Analysis;
-import org.apache.iotdb.db.mpp.plan.analyze.ExpressionAnalyzer;
-import org.apache.iotdb.db.mpp.plan.expression.Expression;
import org.apache.iotdb.db.mpp.plan.optimization.PlanOptimizer;
import org.apache.iotdb.db.mpp.plan.planner.plan.LogicalQueryPlan;
import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.AlterTimeSeriesNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateAlignedTimeSeriesNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateMultiTimeSeriesNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.CreateTimeSeriesNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.InternalCreateTimeSeriesNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.write.MeasurementGroup;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.DeleteDataNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertMultiTabletsNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowsNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowsOfOneDeviceNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertTabletNode;
-import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.AggregationStep;
-import org.apache.iotdb.db.mpp.plan.statement.StatementNode;
-import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
-import org.apache.iotdb.db.mpp.plan.statement.crud.DeleteDataStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertMultiTabletsStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsOfOneDeviceStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertRowsStatement;
-import org.apache.iotdb.db.mpp.plan.statement.crud.InsertTabletStatement;
import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
-import org.apache.iotdb.db.mpp.plan.statement.internal.InternalCreateTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.internal.LastPointFetchStatement;
-import org.apache.iotdb.db.mpp.plan.statement.internal.SchemaFetchStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.AlterTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountDevicesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountLevelTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountNodesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CountTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateMultiTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.CreateTimeSeriesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildNodesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowChildPathsStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowDevicesStatement;
-import org.apache.iotdb.db.mpp.plan.statement.metadata.ShowTimeSeriesStatement;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.stream.Collectors;
/** Generate a logical plan for the statement. */
public class LogicalPlanner {
@@ -93,616 +50,4 @@ public class LogicalPlanner {
return new LogicalQueryPlan(context, rootNode);
}
-
- /**
- * This visitor is used to generate a logical plan for the statement and returns the {@link
- * PlanNode}.
- */
- private static class LogicalPlanVisitor extends StatementVisitor<PlanNode, MPPQueryContext> {
-
- private final Analysis analysis;
-
- public LogicalPlanVisitor(Analysis analysis) {
- this.analysis = analysis;
- }
-
- @Override
- public PlanNode visitNode(StatementNode node, MPPQueryContext context) {
- throw new UnsupportedOperationException(
- "Unsupported statement type: " + node.getClass().getName());
- }
-
- @Override
- public PlanNode visitQuery(QueryStatement queryStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
-
- if (queryStatement.isLastQuery()) {
- return planBuilder
- .planLast(analysis.getSourceExpressions(), analysis.getGlobalTimeFilter())
- .getRoot();
- }
-
- if (queryStatement.isAlignByDevice()) {
- Map<String, PlanNode> deviceToSubPlanMap = new TreeMap<>();
- for (String deviceName : analysis.getDeviceToSourceExpressions().keySet()) {
- LogicalPlanBuilder subPlanBuilder = new LogicalPlanBuilder(context);
- subPlanBuilder =
- subPlanBuilder.withNewRoot(
- visitQueryBody(
- queryStatement,
- analysis.getDeviceToIsRawDataSource().get(deviceName),
- analysis.getDeviceToSourceExpressions().get(deviceName),
- analysis.getDeviceToAggregationExpressions().get(deviceName),
- analysis.getDeviceToAggregationTransformExpressions().get(deviceName),
- analysis.getDeviceToTransformExpressions().get(deviceName),
- analysis.getDeviceToQueryFilter() != null
- ? analysis.getDeviceToQueryFilter().get(deviceName)
- : null,
- analysis.getDeviceToMeasurementIndexesMap().get(deviceName),
- context));
- deviceToSubPlanMap.put(deviceName, subPlanBuilder.getRoot());
- }
- // convert to ALIGN BY DEVICE view
- planBuilder =
- planBuilder.planDeviceView(
- deviceToSubPlanMap,
- analysis.getRespDatasetHeader().getColumnNameWithoutAlias().stream()
- .distinct()
- .collect(Collectors.toList()),
- analysis.getDeviceToMeasurementIndexesMap(),
- queryStatement.getResultOrder());
- } else {
- planBuilder =
- planBuilder.withNewRoot(
- visitQueryBody(
- queryStatement,
- analysis.isRawDataSource(),
- analysis.getSourceExpressions(),
- analysis.getAggregationExpressions(),
- analysis.getAggregationTransformExpressions(),
- analysis.getTransformExpressions(),
- analysis.getQueryFilter(),
- null,
- context));
- }
-
- // other common upstream node
- planBuilder =
- planBuilder
- .planFilterNull(analysis.getFilterNullParameter())
- .planFill(analysis.getFillDescriptor(), queryStatement.getResultOrder())
- .planOffset(queryStatement.getRowOffset())
- .planLimit(queryStatement.getRowLimit());
-
- return planBuilder.getRoot();
- }
-
- public PlanNode visitQueryBody(
- QueryStatement queryStatement,
- boolean isRawDataSource,
- Set<Expression> sourceExpressions,
- Set<Expression> aggregationExpressions,
- Set<Expression> aggregationTransformExpressions,
- Set<Expression> transformExpressions,
- Expression queryFilter,
- List<Integer> measurementIndexes, // only used in ALIGN BY DEVICE
- MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
-
- // plan data source node
- if (isRawDataSource) {
- planBuilder =
- planBuilder.planRawDataSource(
- sourceExpressions, queryStatement.getResultOrder(), analysis.getGlobalTimeFilter());
-
- if (queryStatement.isAggregationQuery()) {
- if (analysis.hasValueFilter()) {
- planBuilder =
- planBuilder.planFilterAndTransform(
- queryFilter,
- aggregationTransformExpressions,
- queryStatement.isGroupByTime(),
- queryStatement.getSelectComponent().getZoneId(),
- queryStatement.getResultOrder());
- } else {
- planBuilder =
- planBuilder.planTransform(
- aggregationTransformExpressions,
- queryStatement.isGroupByTime(),
- queryStatement.getSelectComponent().getZoneId(),
- queryStatement.getResultOrder());
- }
-
- boolean outputPartial =
- queryStatement.isGroupByLevel()
- || (queryStatement.isGroupByTime()
- && analysis.getGroupByTimeParameter().hasOverlap());
- AggregationStep curStep =
- outputPartial ? AggregationStep.PARTIAL : AggregationStep.SINGLE;
- planBuilder =
- planBuilder.planAggregation(
- aggregationExpressions,
- analysis.getGroupByTimeParameter(),
- curStep,
- analysis.getTypeProvider(),
- queryStatement.getResultOrder());
-
- if (curStep.isOutputPartial()) {
- if (queryStatement.isGroupByTime() && analysis.getGroupByTimeParameter().hasOverlap()) {
- curStep =
- queryStatement.isGroupByLevel()
- ? AggregationStep.INTERMEDIATE
- : AggregationStep.FINAL;
- planBuilder =
- planBuilder.planSlidingWindowAggregation(
- aggregationExpressions,
- analysis.getGroupByTimeParameter(),
- curStep,
- queryStatement.getResultOrder());
- }
-
- if (queryStatement.isGroupByLevel()) {
- curStep = AggregationStep.FINAL;
- planBuilder =
- planBuilder.planGroupByLevel(
- analysis.getGroupByLevelExpressions(),
- curStep,
- analysis.getGroupByTimeParameter(),
- queryStatement.getResultOrder());
- }
- }
-
- planBuilder =
- planBuilder.planTransform(
- transformExpressions,
- queryStatement.isGroupByTime(),
- queryStatement.getSelectComponent().getZoneId(),
- queryStatement.getResultOrder());
- } else {
- if (analysis.hasValueFilter()) {
- planBuilder =
- planBuilder.planFilterAndTransform(
- queryFilter,
- transformExpressions,
- queryStatement.isGroupByTime(),
- queryStatement.getSelectComponent().getZoneId(),
- queryStatement.getResultOrder());
- } else {
- planBuilder =
- planBuilder.planTransform(
- transformExpressions,
- queryStatement.isGroupByTime(),
- queryStatement.getSelectComponent().getZoneId(),
- queryStatement.getResultOrder());
- }
- }
- } else {
- AggregationStep curStep =
- (analysis.getGroupByLevelExpressions() != null
- || (analysis.getGroupByTimeParameter() != null
- && analysis.getGroupByTimeParameter().hasOverlap()))
- ? AggregationStep.PARTIAL
- : AggregationStep.SINGLE;
-
- boolean needTransform = false;
- for (Expression expression : transformExpressions) {
- if (ExpressionAnalyzer.checkIsNeedTransform(expression)) {
- needTransform = true;
- break;
- }
- }
-
- if (!needTransform && measurementIndexes != null) {
- planBuilder =
- planBuilder.planAggregationSourceWithIndexAdjust(
- sourceExpressions,
- curStep,
- queryStatement.getResultOrder(),
- analysis.getGlobalTimeFilter(),
- analysis.getGroupByTimeParameter(),
- aggregationExpressions,
- measurementIndexes,
- analysis.getGroupByLevelExpressions(),
- analysis.getTypeProvider());
- } else {
- planBuilder =
- planBuilder
- .planAggregationSource(
- sourceExpressions,
- curStep,
- queryStatement.getResultOrder(),
- analysis.getGlobalTimeFilter(),
- analysis.getGroupByTimeParameter(),
- aggregationExpressions,
- analysis.getGroupByLevelExpressions(),
- analysis.getTypeProvider())
- .planTransform(
- transformExpressions,
- queryStatement.isGroupByTime(),
- queryStatement.getSelectComponent().getZoneId(),
- queryStatement.getResultOrder());
- }
- }
-
- return planBuilder.getRoot();
- }
-
- public PlanNode visitLastPointFetch(
- LastPointFetchStatement lastPointFetchStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder.planLast(analysis.getSourceExpressions(), null).getRoot();
- }
-
- @Override
- public PlanNode visitCreateTimeseries(
- CreateTimeSeriesStatement createTimeSeriesStatement, MPPQueryContext context) {
- return new CreateTimeSeriesNode(
- context.getQueryId().genPlanNodeId(),
- createTimeSeriesStatement.getPath(),
- createTimeSeriesStatement.getDataType(),
- createTimeSeriesStatement.getEncoding(),
- createTimeSeriesStatement.getCompressor(),
- createTimeSeriesStatement.getProps(),
- createTimeSeriesStatement.getTags(),
- createTimeSeriesStatement.getAttributes(),
- createTimeSeriesStatement.getAlias());
- }
-
- @Override
- public PlanNode visitCreateAlignedTimeseries(
- CreateAlignedTimeSeriesStatement createAlignedTimeSeriesStatement,
- MPPQueryContext context) {
- return new CreateAlignedTimeSeriesNode(
- context.getQueryId().genPlanNodeId(),
- createAlignedTimeSeriesStatement.getDevicePath(),
- createAlignedTimeSeriesStatement.getMeasurements(),
- createAlignedTimeSeriesStatement.getDataTypes(),
- createAlignedTimeSeriesStatement.getEncodings(),
- createAlignedTimeSeriesStatement.getCompressors(),
- createAlignedTimeSeriesStatement.getAliasList(),
- createAlignedTimeSeriesStatement.getTagsList(),
- createAlignedTimeSeriesStatement.getAttributesList());
- }
-
- @Override
- public PlanNode visitInternalCreateTimeseries(
- InternalCreateTimeSeriesStatement internalCreateTimeSeriesStatement,
- MPPQueryContext context) {
- int size = internalCreateTimeSeriesStatement.getMeasurements().size();
-
- MeasurementGroup measurementGroup = new MeasurementGroup();
- for (int i = 0; i < size; i++) {
- measurementGroup.addMeasurement(
- internalCreateTimeSeriesStatement.getMeasurements().get(i),
- internalCreateTimeSeriesStatement.getTsDataTypes().get(i),
- internalCreateTimeSeriesStatement.getEncodings().get(i),
- internalCreateTimeSeriesStatement.getCompressors().get(i));
- }
-
- return new InternalCreateTimeSeriesNode(
- context.getQueryId().genPlanNodeId(),
- internalCreateTimeSeriesStatement.getDevicePath(),
- measurementGroup,
- internalCreateTimeSeriesStatement.isAligned());
- }
-
- @Override
- public PlanNode visitCreateMultiTimeseries(
- CreateMultiTimeSeriesStatement createMultiTimeSeriesStatement, MPPQueryContext context) {
- return new CreateMultiTimeSeriesNode(
- context.getQueryId().genPlanNodeId(),
- createMultiTimeSeriesStatement.getPaths(),
- createMultiTimeSeriesStatement.getDataTypes(),
- createMultiTimeSeriesStatement.getEncodings(),
- createMultiTimeSeriesStatement.getCompressors(),
- createMultiTimeSeriesStatement.getPropsList(),
- createMultiTimeSeriesStatement.getAliasList(),
- createMultiTimeSeriesStatement.getTagsList(),
- createMultiTimeSeriesStatement.getAttributesList());
- }
-
- @Override
- public PlanNode visitAlterTimeseries(
- AlterTimeSeriesStatement alterTimeSeriesStatement, MPPQueryContext context) {
- return new AlterTimeSeriesNode(
- context.getQueryId().genPlanNodeId(),
- alterTimeSeriesStatement.getPath(),
- alterTimeSeriesStatement.getAlterType(),
- alterTimeSeriesStatement.getAlterMap(),
- alterTimeSeriesStatement.getAlias(),
- alterTimeSeriesStatement.getTagsMap(),
- alterTimeSeriesStatement.getAttributesMap());
- }
-
- @Override
- public PlanNode visitInsertTablet(
- InsertTabletStatement insertTabletStatement, MPPQueryContext context) {
- // convert insert statement to insert node
- return new InsertTabletNode(
- context.getQueryId().genPlanNodeId(),
- insertTabletStatement.getDevicePath(),
- insertTabletStatement.isAligned(),
- insertTabletStatement.getMeasurements(),
- insertTabletStatement.getDataTypes(),
- insertTabletStatement.getTimes(),
- insertTabletStatement.getBitMaps(),
- insertTabletStatement.getColumns(),
- insertTabletStatement.getRowCount());
- }
-
- @Override
- public PlanNode visitInsertRow(InsertRowStatement insertRowStatement, MPPQueryContext context) {
- // convert insert statement to insert node
- return new InsertRowNode(
- context.getQueryId().genPlanNodeId(),
- insertRowStatement.getDevicePath(),
- insertRowStatement.isAligned(),
- insertRowStatement.getMeasurements(),
- insertRowStatement.getDataTypes(),
- insertRowStatement.getTime(),
- insertRowStatement.getValues(),
- insertRowStatement.isNeedInferType());
- }
-
- @Override
- public PlanNode visitShowTimeSeries(
- ShowTimeSeriesStatement showTimeSeriesStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(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
- && !showTimeSeriesStatement.isOrderByHeat();
-
- int limit = showTimeSeriesStatement.getLimit();
- int offset = showTimeSeriesStatement.getOffset();
- if (showTimeSeriesStatement.isOrderByHeat()) {
- limit = 0;
- offset = 0;
- } else if (!canPushDownOffsetLimit) {
- limit = showTimeSeriesStatement.getLimit() + showTimeSeriesStatement.getOffset();
- offset = 0;
- }
- planBuilder =
- planBuilder
- .planTimeSeriesSchemaSource(
- showTimeSeriesStatement.getPathPattern(),
- showTimeSeriesStatement.getKey(),
- showTimeSeriesStatement.getValue(),
- limit,
- offset,
- showTimeSeriesStatement.isOrderByHeat(),
- showTimeSeriesStatement.isContains(),
- showTimeSeriesStatement.isPrefixPath())
- .planSchemaQueryMerge(showTimeSeriesStatement.isOrderByHeat());
- // show latest timeseries
- if (showTimeSeriesStatement.isOrderByHeat()
- && null != analysis.getDataPartitionInfo()
- && 0 != analysis.getDataPartitionInfo().getDataPartitionMap().size()) {
- PlanNode lastPlanNode =
- new LogicalPlanBuilder(context)
- .planLast(analysis.getSourceExpressions(), analysis.getGlobalTimeFilter())
- .getRoot();
- planBuilder = planBuilder.planSchemaQueryOrderByHeat(lastPlanNode);
- }
-
- if (canPushDownOffsetLimit) {
- return planBuilder.getRoot();
- }
-
- return planBuilder
- .planOffset(showTimeSeriesStatement.getOffset())
- .planLimit(showTimeSeriesStatement.getLimit())
- .getRoot();
- }
-
- @Override
- public PlanNode visitShowDevices(
- ShowDevicesStatement showDevicesStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(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;
-
- int limit = showDevicesStatement.getLimit();
- int offset = showDevicesStatement.getOffset();
- if (!canPushDownOffsetLimit) {
- limit = showDevicesStatement.getLimit() + showDevicesStatement.getOffset();
- offset = 0;
- }
-
- planBuilder =
- planBuilder
- .planDeviceSchemaSource(
- showDevicesStatement.getPathPattern(),
- limit,
- offset,
- showDevicesStatement.isPrefixPath(),
- showDevicesStatement.hasSgCol())
- .planSchemaQueryMerge(false);
-
- if (!canPushDownOffsetLimit) {
- return planBuilder
- .planOffset(showDevicesStatement.getOffset())
- .planLimit(showDevicesStatement.getLimit())
- .getRoot();
- }
- return planBuilder.getRoot();
- }
-
- @Override
- public PlanNode visitCountDevices(
- CountDevicesStatement countDevicesStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planDevicesCountSource(
- countDevicesStatement.getPartialPath(), countDevicesStatement.isPrefixPath())
- .planCountMerge()
- .getRoot();
- }
-
- @Override
- public PlanNode visitCountTimeSeries(
- CountTimeSeriesStatement countTimeSeriesStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planTimeSeriesCountSource(
- countTimeSeriesStatement.getPartialPath(), countTimeSeriesStatement.isPrefixPath())
- .planCountMerge()
- .getRoot();
- }
-
- @Override
- public PlanNode visitCountLevelTimeSeries(
- CountLevelTimeSeriesStatement countLevelTimeSeriesStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planLevelTimeSeriesCountSource(
- countLevelTimeSeriesStatement.getPartialPath(),
- countLevelTimeSeriesStatement.isPrefixPath(),
- countLevelTimeSeriesStatement.getLevel())
- .planCountMerge()
- .getRoot();
- }
-
- @Override
- public PlanNode visitCountNodes(CountNodesStatement countStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planNodePathsSchemaSource(countStatement.getPartialPath(), countStatement.getLevel())
- .planSchemaQueryMerge(false)
- .planNodeManagementMemoryMerge(analysis.getMatchedNodes())
- .planNodePathsCount()
- .getRoot();
- }
-
- @Override
- public PlanNode visitInsertRows(
- InsertRowsStatement insertRowsStatement, MPPQueryContext context) {
- // convert insert statement to insert node
- InsertRowsNode insertRowsNode = new InsertRowsNode(context.getQueryId().genPlanNodeId());
- for (int i = 0; i < insertRowsStatement.getInsertRowStatementList().size(); i++) {
- InsertRowStatement insertRowStatement =
- insertRowsStatement.getInsertRowStatementList().get(i);
- insertRowsNode.addOneInsertRowNode(
- new InsertRowNode(
- insertRowsNode.getPlanNodeId(),
- insertRowStatement.getDevicePath(),
- insertRowStatement.isAligned(),
- insertRowStatement.getMeasurements(),
- insertRowStatement.getDataTypes(),
- insertRowStatement.getTime(),
- insertRowStatement.getValues(),
- insertRowStatement.isNeedInferType()),
- i);
- }
- return insertRowsNode;
- }
-
- @Override
- public PlanNode visitInsertMultiTablets(
- InsertMultiTabletsStatement insertMultiTabletsStatement, MPPQueryContext context) {
- // convert insert statement to insert node
- InsertMultiTabletsNode insertMultiTabletsNode =
- new InsertMultiTabletsNode(context.getQueryId().genPlanNodeId());
- for (int i = 0; i < insertMultiTabletsStatement.getInsertTabletStatementList().size(); i++) {
- InsertTabletStatement insertTabletStatement =
- insertMultiTabletsStatement.getInsertTabletStatementList().get(i);
- insertMultiTabletsNode.addInsertTabletNode(
- new InsertTabletNode(
- insertMultiTabletsNode.getPlanNodeId(),
- insertTabletStatement.getDevicePath(),
- insertTabletStatement.isAligned(),
- insertTabletStatement.getMeasurements(),
- insertTabletStatement.getDataTypes(),
- insertTabletStatement.getTimes(),
- insertTabletStatement.getBitMaps(),
- insertTabletStatement.getColumns(),
- insertTabletStatement.getRowCount()),
- i);
- }
- return insertMultiTabletsNode;
- }
-
- @Override
- public PlanNode visitInsertRowsOfOneDevice(
- InsertRowsOfOneDeviceStatement insertRowsOfOneDeviceStatement, MPPQueryContext context) {
- // convert insert statement to insert node
- InsertRowsOfOneDeviceNode insertRowsOfOneDeviceNode =
- new InsertRowsOfOneDeviceNode(context.getQueryId().genPlanNodeId());
-
- List<InsertRowNode> insertRowNodeList = new ArrayList<>();
- List<Integer> insertRowNodeIndexList = new ArrayList<>();
- for (int i = 0; i < insertRowsOfOneDeviceStatement.getInsertRowStatementList().size(); i++) {
- InsertRowStatement insertRowStatement =
- insertRowsOfOneDeviceStatement.getInsertRowStatementList().get(i);
- insertRowNodeList.add(
- new InsertRowNode(
- insertRowsOfOneDeviceNode.getPlanNodeId(),
- insertRowStatement.getDevicePath(),
- insertRowStatement.isAligned(),
- insertRowStatement.getMeasurements(),
- insertRowStatement.getDataTypes(),
- insertRowStatement.getTime(),
- insertRowStatement.getValues(),
- insertRowStatement.isNeedInferType()));
- insertRowNodeIndexList.add(i);
- }
-
- insertRowsOfOneDeviceNode.setInsertRowNodeList(insertRowNodeList);
- insertRowsOfOneDeviceNode.setInsertRowNodeIndexList(insertRowNodeIndexList);
- return insertRowsOfOneDeviceNode;
- }
-
- @Override
- public PlanNode visitSchemaFetch(
- SchemaFetchStatement schemaFetchStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planSchemaFetchMerge()
- .planSchemaFetchSource(
- new ArrayList<>(
- schemaFetchStatement.getSchemaPartition().getSchemaPartitionMap().keySet()),
- schemaFetchStatement.getPatternTree())
- .getRoot();
- }
-
- @Override
- public PlanNode visitShowChildPaths(
- ShowChildPathsStatement showChildPathsStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planNodePathsSchemaSource(showChildPathsStatement.getPartialPath(), -1)
- .planSchemaQueryMerge(false)
- .planNodeManagementMemoryMerge(analysis.getMatchedNodes())
- .getRoot();
- }
-
- @Override
- public PlanNode visitShowChildNodes(
- ShowChildNodesStatement showChildNodesStatement, MPPQueryContext context) {
- LogicalPlanBuilder planBuilder = new LogicalPlanBuilder(context);
- return planBuilder
- .planNodePathsSchemaSource(showChildNodesStatement.getPartialPath(), -1)
- .planSchemaQueryMerge(false)
- .planNodeManagementMemoryMerge(analysis.getMatchedNodes())
- .planNodePathsConvert()
- .getRoot();
- }
-
- @Override
- public PlanNode visitDeleteData(
- DeleteDataStatement deleteDataStatement, MPPQueryContext context) {
- return new DeleteDataNode(
- context.getQueryId().genPlanNodeId(),
- deleteDataStatement.getPathList(),
- deleteDataStatement.getDeleteStartTime(),
- deleteDataStatement.getDeleteEndTime());
- }
- }
}