@Override
  public Analysis visitQuery(QueryStatement queryStatement, MPPQueryContext context) {
    Analysis analysis = new Analysis();
    analysis.setLastLevelUseWildcard(queryStatement.isLastLevelUseWildcard());

    try {
      // check for semantic errors
      queryStatement.semanticCheck();

      // fetch model inference information and check
      analyzeModelInference(analysis, queryStatement);

      ISchemaTree schemaTree = analyzeSchema(queryStatement, analysis, context);

      // If there is no leaf node in the schema tree, the query should be completed immediately
      if (schemaTree.isEmpty()) {
        return finishQuery(queryStatement, analysis);
      }

      // extract global time filter from query filter and determine if there is a value filter
      analyzeGlobalTimeFilter(analysis, queryStatement);

      if (queryStatement.isLastQuery()) {
        return analyzeLastQuery(queryStatement, analysis, schemaTree, context);
      }

      List<Pair<Expression, String>> outputExpressions;
      if (queryStatement.isAlignByDevice()) {
        List<PartialPath> deviceList = analyzeFrom(queryStatement, schemaTree);

        if (deviceList.size() > 1
            && TemplatedAnalyze.canBuildPlanUseTemplate(
                analysis, queryStatement, partitionFetcher, schemaTree, context, deviceList)) {
          // when device size is less than 1, there is no need to use template optimization, i.e. no
          // need to extract common variables
          return analysis;
        }

        if (canPushDownLimitOffsetInGroupByTimeForDevice(queryStatement)) {
          // remove the device which won't appear in resultSet after limit/offset
          deviceList =
              pushDownLimitOffsetInGroupByTimeForDevice(
                  deviceList, queryStatement, context.getZoneId());
        }

        outputExpressions =
            analyzeSelect(analysis, queryStatement, schemaTree, deviceList, context);
        if (outputExpressions.isEmpty()) {
          return finishQuery(queryStatement, analysis);
        }

        analyzeDeviceToWhere(analysis, queryStatement, schemaTree, deviceList, context);
        if (deviceList.isEmpty()) {
          return finishQuery(queryStatement, analysis, outputExpressions);
        }
        analysis.setDeviceList(deviceList);

        analyzeDeviceToGroupBy(analysis, queryStatement, schemaTree, deviceList, context);
        analyzeDeviceToOrderBy(analysis, queryStatement, schemaTree, deviceList, context);
        analyzeHaving(analysis, queryStatement, schemaTree, deviceList, context);

        analyzeDeviceToAggregation(analysis, queryStatement);
        analyzeDeviceToSourceTransform(analysis, queryStatement);
        analyzeDeviceToSource(analysis, queryStatement);

        analyzeDeviceViewOutput(analysis, queryStatement);
        analyzeDeviceViewInput(analysis, queryStatement);

        analyzeInto(analysis, queryStatement, deviceList, outputExpressions, context);
      } else {
        // analyze output expressions
        if (queryStatement.isGroupByLevel()) {
          GroupByLevelHelper groupByLevelHelper =
              new GroupByLevelHelper(queryStatement.getGroupByLevelComponent().getLevels());

          outputExpressions =
              analyzeGroupByLevelSelect(
                  analysis, queryStatement, schemaTree, groupByLevelHelper, context);
          if (outputExpressions.isEmpty()) {
            return finishQuery(queryStatement, analysis);
          }
          analysis.setOutputExpressions(outputExpressions);
          setSelectExpressions(analysis, queryStatement, outputExpressions);

          analyzeGroupByLevelHaving(
              analysis, queryStatement, schemaTree, groupByLevelHelper, context);

          analyzeGroupByLevelOrderBy(
              analysis, queryStatement, schemaTree, groupByLevelHelper, context);

          checkDataTypeConsistencyInGroupByLevel(
              analysis, groupByLevelHelper.getGroupByLevelExpressions());
          analysis.setCrossGroupByExpressions(groupByLevelHelper.getGroupByLevelExpressions());
        } else {
          outputExpressions = analyzeSelect(analysis, queryStatement, schemaTree, context);

          analyzeGroupByTag(analysis, queryStatement, outputExpressions);

          if (outputExpressions.isEmpty()) {
            return finishQuery(queryStatement, analysis);
          }
          analysis.setOutputExpressions(outputExpressions);
          setSelectExpressions(analysis, queryStatement, outputExpressions);

          analyzeHaving(analysis, queryStatement, schemaTree, context);

          analyzeOrderBy(analysis, queryStatement, schemaTree, context);
        }

        // analyze aggregation
        analyzeAggregation(analysis, queryStatement);

        // analyze aggregation input
        analyzeGroupBy(analysis, queryStatement, schemaTree, context);
        analyzeWhere(analysis, queryStatement, schemaTree, context);
        if (analysis.getWhereExpression() != null
            && analysis.getWhereExpression().equals(ConstantOperand.FALSE)) {
          return finishQuery(queryStatement, analysis, outputExpressions);
        }
        analyzeSourceTransform(analysis, outputExpressions, queryStatement);

        // analyze series scan
        analyzeSource(analysis, queryStatement);

        // analyze into paths
        analyzeInto(analysis, queryStatement, outputExpressions, context);
      }

      analyzeGroupByTime(analysis, queryStatement);
      context.generateGlobalTimeFilter(analysis);

      analyzeFill(analysis, queryStatement);

      // generate result set header according to output expressions
      analyzeOutput(analysis, queryStatement, outputExpressions);

      // fetch partition information
      analyzeDataPartition(analysis, queryStatement, schemaTree, context);

    } catch (StatementAnalyzeException e) {
      throw new StatementAnalyzeException(
          "Meet error when analyzing the query statement: " + e.getMessage());
    }
    return analysis;
  }
This visitor is used to analyze each type of Statement and returns the {@link Analysis}.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java