private Analysis.ResolvedWindow resolveWindowSpecification(
        QuerySpecification querySpecification, Window window) {
      if (window instanceof WindowReference) {
        WindowReference windowReference = (WindowReference) window;
        CanonicalizationAware<Identifier> canonicalName =
            canonicalizationAwareKey(windowReference.getName());
        Analysis.ResolvedWindow referencedWindow =
            analysis.getWindowDefinition(querySpecification, canonicalName);
        if (referencedWindow == null) {
          throw new SemanticException(
              String.format("Cannot resolve WINDOW name %s", windowReference.getName()));
        }

        return new Analysis.ResolvedWindow(
            referencedWindow.getPartitionBy(),
            referencedWindow.getOrderBy(),
            referencedWindow.getFrame(),
            !referencedWindow.getPartitionBy().isEmpty(),
            referencedWindow.getOrderBy().isPresent(),
            referencedWindow.getFrame().isPresent());
      }

      WindowSpecification windowSpecification = (WindowSpecification) window;

      if (windowSpecification.getExistingWindowName().isPresent()) {
        Identifier referencedName = windowSpecification.getExistingWindowName().get();
        CanonicalizationAware<Identifier> canonicalName = canonicalizationAwareKey(referencedName);
        Analysis.ResolvedWindow referencedWindow =
            analysis.getWindowDefinition(querySpecification, canonicalName);
        if (referencedWindow == null) {
          throw new SemanticException(
              String.format("Cannot resolve WINDOW name %s", referencedName));
        }

        // analyze dependencies between this window specification and referenced window
        // specification
        if (!windowSpecification.getPartitionBy().isEmpty()) {
          throw new SemanticException(
              "WINDOW specification with named WINDOW reference cannot specify PARTITION BY");
        }
        if (windowSpecification.getOrderBy().isPresent()
            && referencedWindow.getOrderBy().isPresent()) {
          throw new SemanticException(
              "Cannot specify ORDER BY if referenced named WINDOW specifies ORDER BY");
        }
        if (referencedWindow.getFrame().isPresent()) {
          throw new SemanticException(
              "Cannot reference named WINDOW containing frame specification");
        }

        // resolve window
        Optional<OrderBy> orderBy = windowSpecification.getOrderBy();
        boolean orderByInherited = false;
        if (!orderBy.isPresent() && referencedWindow.getOrderBy().isPresent()) {
          orderBy = referencedWindow.getOrderBy();
          orderByInherited = true;
        }

        List<Expression> partitionBy = windowSpecification.getPartitionBy();
        boolean partitionByInherited = false;
        if (!referencedWindow.getPartitionBy().isEmpty()) {
          partitionBy = referencedWindow.getPartitionBy();
          partitionByInherited = true;
        }

        Optional<WindowFrame> windowFrame = windowSpecification.getFrame();
        boolean frameInherited = false;
        if (!windowFrame.isPresent() && referencedWindow.getFrame().isPresent()) {
          windowFrame = referencedWindow.getFrame();
          frameInherited = true;
        }

        return new Analysis.ResolvedWindow(
            partitionBy,
            orderBy,
            windowFrame,
            partitionByInherited,
            orderByInherited,
            frameInherited);
      }

      return new Analysis.ResolvedWindow(
          windowSpecification.getPartitionBy(),
          windowSpecification.getOrderBy(),
          windowSpecification.getFrame(),
          false,
          false,
          false);
    }
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