@Override
    protected Scope visitSetOperation(SetOperation node, Optional<Scope> scope) {
      checkState(node.getRelations().size() >= 2);

      List<RelationType> childrenTypes =
          node.getRelations().stream()
              .map(relation -> process(relation, scope).getRelationType().withOnlyVisibleFields())
              .collect(toImmutableList());

      String setOperationName = node.getClass().getSimpleName().toUpperCase(ENGLISH);
      Type[] outputFieldTypes =
          childrenTypes.get(0).getVisibleFields().stream().map(Field::getType).toArray(Type[]::new);
      for (RelationType relationType : childrenTypes) {
        int outputFieldSize = outputFieldTypes.length;
        int descFieldSize = relationType.getVisibleFields().size();
        if (outputFieldSize != descFieldSize) {
          throw new SemanticException(
              String.format(
                  "%s query has different number of fields: %d, %d",
                  setOperationName, outputFieldSize, descFieldSize));
        }
        for (int i = 0; i < descFieldSize; i++) {
          Type descFieldType = relationType.getFieldByIndex(i).getType();
          if (descFieldType != outputFieldTypes[i]) {
            throw new SemanticException(
                String.format(
                    "column %d in %s query has incompatible types: %s, %s",
                    i + 1,
                    setOperationName,
                    outputFieldTypes[i].getDisplayName(),
                    descFieldType.getDisplayName()));
          }
        }
      }

      if (node instanceof Intersect
          || node instanceof Except
          || node instanceof Union && node.isDistinct()) {
        for (Type type : outputFieldTypes) {
          if (!type.isComparable()) {
            throw new SemanticException(
                String.format(
                    "Type %s is not comparable and therefore cannot be used in %s%s",
                    type, setOperationName, node instanceof Union ? " DISTINCT" : ""));
          }
        }
      }

      Field[] outputDescriptorFields = new Field[outputFieldTypes.length];
      RelationType firstDescriptor = childrenTypes.get(0);
      for (int i = 0; i < outputFieldTypes.length; i++) {
        Field oldField = firstDescriptor.getFieldByIndex(i);
        outputDescriptorFields[i] =
            new Field(
                oldField.getRelationAlias(),
                oldField.getName(),
                outputFieldTypes[i],
                oldField.getColumnCategory(),
                oldField.isHidden(),
                oldField.getOriginTable(),
                oldField.getOriginColumnName(),
                oldField.isAliased());

        int index = i; // Variable used in Lambda should be final
        analysis.addSourceColumns(
            outputDescriptorFields[index],
            childrenTypes.stream()
                .map(relationType -> relationType.getFieldByIndex(index))
                .flatMap(field -> analysis.getSourceColumns(field).stream())
                .collect(toImmutableSet()));
      }

      for (int i = 0; i < node.getRelations().size(); i++) {
        Relation relation = node.getRelations().get(i);
        RelationType relationType = childrenTypes.get(i);
        for (int j = 0; j < relationType.getVisibleFields().size(); j++) {
          Type outputFieldType = outputFieldTypes[j];
          Type descFieldType = relationType.getFieldByIndex(j).getType();
          if (!outputFieldType.equals(descFieldType)) {
            analysis.addRelationCoercion(relation, outputFieldTypes);
            break;
          }
        }
      }
      return createAndAssignScope(node, scope, outputDescriptorFields);
    }
Check if there is Columns function in expression, and verify they are same if there are multi
Column functions.

@param expression input expression
@return if there is Columns function in expression
@throws SemanticException if there are multi Columns functions but different
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java