@Override
    protected Scope visitQuery(Query node, Optional<Scope> context) {
      analysis.setQuery(true);
      Scope withScope = analyzeWith(node, context);
      hasFillInParentScope = node.getFill().isPresent() || hasFillInParentScope;
      Scope queryBodyScope = process(node.getQueryBody(), withScope);

      if (node.getFill().isPresent()) {
        analyzeFill(node.getFill().get(), queryBodyScope);
      }

      List<Expression> orderByExpressions = emptyList();
      if (node.getOrderBy().isPresent()) {
        orderByExpressions =
            analyzeOrderBy(node, getSortItemsFromOrderBy(node.getOrderBy()), queryBodyScope);

        if ((queryBodyScope.getOuterQueryParent().isPresent() || !isTopLevel)
            && !node.getLimit().isPresent()
            && !node.getOffset().isPresent()
            && !hasFillInParentScope) {
          // not the root scope and ORDER BY is ineffective
          analysis.markRedundantOrderBy(node.getOrderBy().get());
          warningCollector.add(
              new IoTDBWarning(REDUNDANT_ORDER_BY, "ORDER BY in subquery may have no effect"));
        }
      }
      analysis.setOrderByExpressions(node, orderByExpressions);

      if (node.getOffset().isPresent()) {
        analyzeOffset(node.getOffset().get(), queryBodyScope);
      }

      if (node.getLimit().isPresent()) {
        boolean requiresOrderBy = analyzeLimit(node.getLimit().get(), queryBodyScope);
        if (requiresOrderBy && !node.getOrderBy().isPresent()) {
          throw new SemanticException("FETCH FIRST WITH TIES clause requires ORDER BY");
        }
      }

      // Input fields == Output fields
      analysis.setSelectExpressions(
          node,
          descriptorToFields(queryBodyScope).stream()
              .map(expression -> new Analysis.SelectExpression(expression, Optional.empty()))
              .collect(toImmutableList()));

      Scope queryScope =
          Scope.builder()
              .withParent(withScope)
              .withRelationType(RelationId.of(node), queryBodyScope.getRelationType())
              .build();

      analysis.setScope(node, queryScope);
      return queryScope;
    }
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