private void analyzeFrameRangeOffset(
        Expression offsetValue,
        FrameBound.Type boundType,
        StackableAstVisitorContext<Context> context,
        Analysis.ResolvedWindow window,
        Node originalNode) {
      OrderBy orderBy =
          window
              .getOrderBy()
              .orElseThrow(
                  () ->
                      new SemanticException(
                          "Window frame of type RANGE PRECEDING or FOLLOWING requires ORDER BY"));
      if (orderBy.getSortItems().size() != 1) {
        throw new SemanticException(
            "Window frame of type RANGE PRECEDING or FOLLOWING requires single sort item in ORDER BY (actual: %s)",
            orderBy.getSortItems().size());
      }
      Expression sortKey = Iterables.getOnlyElement(orderBy.getSortItems()).getSortKey();
      Type sortKeyType;
      if (window.isOrderByInherited()) {
        sortKeyType = getPreanalyzedType.apply(sortKey);
      } else {
        sortKeyType = getExpressionType(sortKey);
      }
      if (!isNumericType(sortKeyType)) {
        throw new SemanticException(
            String.format(
                "Window frame of type RANGE PRECEDING or FOLLOWING requires that sort item type be numeric, datetime or interval (actual: %s)",
                sortKeyType));
      }

      Type offsetValueType = process(offsetValue, context);

      if (isNumericType(sortKeyType)) {
        if (!isNumericType(offsetValueType)) {
          throw new SemanticException(
              String.format(
                  "Window frame RANGE value type (%s) not compatible with sort item type (%s)",
                  offsetValueType, sortKeyType));
        }
      }
    }
@return the common supertype between the value type and subquery type
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java