private List<FunctionCall> analyzeWindowFunctions(
        QuerySpecification node, List<Expression> expressions) {
      List<FunctionCall> windowFunctions = extractWindowFunctions(expressions);

      for (FunctionCall windowFunction : windowFunctions) {
        List<Expression> nestedWindowExpressions =
            extractWindowExpressions(windowFunction.getArguments());
        if (!nestedWindowExpressions.isEmpty()) {
          throw new SemanticException(
              "Cannot nest window functions or row pattern measures inside window function arguments");
        }

        if (windowFunction.isDistinct()) {
          throw new SemanticException(
              String.format(
                  "DISTINCT in window function parameters not yet supported: %s", windowFunction));
        }

        Analysis.ResolvedWindow window = analysis.getWindow(windowFunction);
        String name = windowFunction.getName().toString().toLowerCase(ENGLISH);
        if (name.equals("lag") || name.equals("lead")) {
          if (!window.getOrderBy().isPresent()) {
            throw new SemanticException(
                String.format(
                    "%s function requires an ORDER BY window clause", windowFunction.getName()));
          }
          if (window.getFrame().isPresent()) {
            throw new SemanticException(
                String.format(
                    "Cannot specify window frame for %s function", windowFunction.getName()));
          }
        }
      }

      return windowFunctions;
    }
Visitor context represents local query scope (if exists). The invariant is that the local query
scopes hierarchy should always have outer query scope (if provided) as ancestor.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java