private void analyzeModelInference(Analysis analysis, QueryStatement queryStatement) {
    if (!queryStatement.hasModelInference()) {
      return;
    }

    // Get model metadata from configNode and do some check
    String modelId = queryStatement.getModelName();
    TSStatus status = modelFetcher.fetchModel(modelId, analysis);
    if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
      throw new GetModelInfoException(status.getMessage());
    }
    ModelInformation modelInformation = analysis.getModelInformation();
    if (modelInformation == null || !modelInformation.available()) {
      throw new SemanticException("Model " + modelId + " is not active");
    }

    // set inference window if there is
    if (queryStatement.isSetInferenceWindow()) {
      InferenceWindow window = queryStatement.getInferenceWindow();
      if (InferenceWindowType.HEAD == window.getType()) {
        long windowSize = ((HeadInferenceWindow) window).getWindowSize();
        checkWindowSize(windowSize, modelInformation);
        if (queryStatement.hasLimit() && queryStatement.getRowLimit() < windowSize) {
          throw new SemanticException(
              "Limit in Sql should be larger than window size in inference");
        }
        // optimize head window by limitNode
        queryStatement.setRowLimit(windowSize);
      } else if (InferenceWindowType.TAIL == window.getType()) {
        long windowSize = ((TailInferenceWindow) window).getWindowSize();
        checkWindowSize(windowSize, modelInformation);
        InferenceWindowParameter inferenceWindowParameter =
            new BottomInferenceWindowParameter(windowSize);
        analysis
            .getModelInferenceDescriptor()
            .setInferenceWindowParameter(inferenceWindowParameter);
      } else if (InferenceWindowType.COUNT == window.getType()) {
        CountInferenceWindow countInferenceWindow = (CountInferenceWindow) window;
        checkWindowSize(countInferenceWindow.getInterval(), modelInformation);
        InferenceWindowParameter inferenceWindowParameter =
            new CountInferenceWindowParameter(
                countInferenceWindow.getInterval(), countInferenceWindow.getStep());
        analysis
            .getModelInferenceDescriptor()
            .setInferenceWindowParameter(inferenceWindowParameter);
      }
    }

    // set inference attributes if there is
    if (queryStatement.hasInferenceAttributes()) {
      analysis
          .getModelInferenceDescriptor()
          .setInferenceAttributes(queryStatement.getInferenceAttributes());
    }
  }
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