private List<Expression> analyzeSelect(QuerySpecification node, Scope scope) {
      ImmutableList.Builder<Expression> outputExpressionBuilder = ImmutableList.builder();
      ImmutableList.Builder<Analysis.SelectExpression> selectExpressionBuilder =
          ImmutableList.builder();

      for (SelectItem item : node.getSelect().getSelectItems()) {
        if (item instanceof AllColumns) {
          analyzeSelectAllColumns(
              (AllColumns) item, node, scope, outputExpressionBuilder, selectExpressionBuilder);
        } else if (item instanceof SingleColumn) {
          SingleColumn singleColumn = (SingleColumn) item;
          Expression selectExpression = singleColumn.getExpression();
          if (containsColumns(selectExpression)) {
            ExpandColumnsVisitor visitor =
                new ExpandColumnsVisitor(singleColumn.getAlias().orElse(null));
            List<Expression> expandedExpressions = visitor.process(selectExpression, scope);
            if (expandedExpressions.isEmpty()) {
              throw new IllegalStateException("There is at least one result of expanded");
            }
            singleColumn.setExpandedExpressions(expandedExpressions);
            singleColumn.setAccordingColumnName(visitor.getAccordingColumnNames());
            for (Expression expression : expandedExpressions) {
              analyzeSelectSingleColumn(
                  expression, node, scope, outputExpressionBuilder, selectExpressionBuilder);
            }
          } else {
            analyzeSelectSingleColumn(
                selectExpression, node, scope, outputExpressionBuilder, selectExpressionBuilder);
          }
        } else {
          throw new IllegalArgumentException(
              "Unsupported SelectItem type: " + item.getClass().getName());
        }
      }
      analysis.setSelectExpressions(node, selectExpressionBuilder.build());

      if (node.getSelect().isDistinct()) {
        analysis.setContainsSelectDistinct();
      }

      return outputExpressionBuilder.build();
    }
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