private Scope analyzeWith(Query node, Optional<Scope> scope) {
      if (!node.getWith().isPresent()) {
        return createScope(scope);
      }

      // analyze WITH clause
      With with = node.getWith().get();
      Scope.Builder withScopeBuilder = scopeBuilder(scope);

      for (WithQuery withQuery : with.getQueries()) {
        String name = withQuery.getName().getValue().toLowerCase(ENGLISH);
        if (withScopeBuilder.containsNamedQuery(name)) {
          throw new SemanticException(
              String.format("WITH query name '%s' specified more than once", name));
        }

        boolean isRecursive = false;
        if (with.isRecursive()) {
          // cannot nest pattern recognition within recursive query

          isRecursive = tryProcessRecursiveQuery(withQuery, name, withScopeBuilder);
          // WITH query is not shaped accordingly to the rules for expandable query and will be
          // processed like a plain WITH query.
          // Since RECURSIVE is specified, any reference to WITH query name is considered a
          // recursive reference and is not allowed.
          if (!isRecursive) {
            List<Node> recursiveReferences =
                findReferences(withQuery.getQuery(), withQuery.getName());
            if (!recursiveReferences.isEmpty()) {
              throw new SemanticException("recursive reference not allowed in this context");
            }
          }
        }

        if (!isRecursive) {
          Query query = withQuery.getQuery();
          analyze(query, withScopeBuilder.build());

          // check if all or none of the columns are explicitly alias
          if (withQuery.getColumnNames().isPresent()) {
            validateColumnAliases(
                withQuery.getColumnNames().get(),
                analysis.getOutputDescriptor(query).getVisibleFieldCount());
          }

          withScopeBuilder.withNamedQuery(name, withQuery);
        }
      }
      Scope withScope = withScopeBuilder.build();
      analysis.setScope(with, withScope);
      return withScope;
    }
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