private static Optional findCommonPrimitiveTypeForComparison()

in fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java [1341:1489]


    private static Optional<DataType> findCommonPrimitiveTypeForComparison(
            DataType leftType, DataType rightType, boolean intStringToString) {
        // same type
        if (leftType.equals(rightType)) {
            return Optional.of(leftType);
        }

        if (leftType.isNullType()) {
            return Optional.of(rightType);
        }
        if (rightType.isNullType()) {
            return Optional.of(leftType);
        }

        // decimal v3
        if (leftType.isDecimalV3Type() && rightType.isDecimalV3Type()) {
            return Optional.of(DecimalV3Type.widerDecimalV3Type(
                    (DecimalV3Type) leftType, (DecimalV3Type) rightType, true));
        }

        // decimal v2
        if (leftType.isDecimalV2Type() && rightType.isDecimalV2Type()) {
            return Optional.of(DecimalV2Type.widerDecimalV2Type((DecimalV2Type) leftType, (DecimalV2Type) rightType));
        }

        // date
        if (canCompareDate(leftType, rightType)) {
            if (leftType.isDateTimeV2Type() && rightType.isDateTimeV2Type()) {
                return Optional.of(DateTimeV2Type.getWiderDatetimeV2Type(
                        (DateTimeV2Type) leftType, (DateTimeV2Type) rightType));
            } else if (leftType.isDateTimeV2Type()) {
                if (rightType instanceof IntegralType || rightType.isDateType()
                        || rightType.isDateV2Type() || rightType.isDateTimeType()) {
                    return Optional.of(leftType);
                } else {
                    return Optional.of(DateTimeV2Type.MAX);
                }
            } else if (rightType.isDateTimeV2Type()) {
                if (leftType instanceof IntegralType || leftType.isDateType()
                        || leftType.isDateV2Type() || leftType.isDateTimeType()) {
                    return Optional.of(rightType);
                } else {
                    return Optional.of(DateTimeV2Type.MAX);
                }
            } else if (leftType.isDateV2Type()) {
                if (rightType instanceof IntegralType || rightType.isDateType() || rightType.isDateV2Type()) {
                    return Optional.of(leftType);
                } else if (rightType.isDateTimeType() || rightType.isStringLikeType() || rightType.isHllType()) {
                    return Optional.of(DateTimeV2Type.SYSTEM_DEFAULT);
                } else {
                    return Optional.of(DateTimeV2Type.MAX);
                }
            } else if (rightType.isDateV2Type()) {
                if (leftType instanceof IntegralType || leftType.isDateType() || leftType.isDateV2Type()) {
                    return Optional.of(rightType);
                } else if (leftType.isDateTimeType() || leftType.isStringLikeType() || leftType.isHllType()) {
                    return Optional.of(DateTimeV2Type.SYSTEM_DEFAULT);
                } else {
                    return Optional.of(DateTimeV2Type.MAX);
                }
            } else {
                return Optional.of(DateTimeType.INSTANCE);
            }
        }

        // varchar-like vs varchar-like
        if (maybeCastToVarchar(leftType) && maybeCastToVarchar(rightType)) {
            return Optional.of(VarcharType.SYSTEM_DEFAULT);
        }

        // varchar-like vs string
        if ((maybeCastToVarchar(leftType) && rightType instanceof StringType)
                || (maybeCastToVarchar(rightType) && leftType instanceof StringType)) {
            return Optional.of(StringType.INSTANCE);
        }

        // in legacy planner, comparison predicate convert int vs string to double.
        // however, in predicate and between predicate convert int vs string to string
        // but after between rewritten to comparison predicate,
        // int vs string been convert to double again
        // so, in Nereids, only in predicate set this flag to true.
        if (intStringToString) {
            if ((leftType instanceof IntegralType && rightType.isStringLikeType())
                    || (rightType instanceof IntegralType && leftType.isStringLikeType())) {
                return Optional.of(StringType.INSTANCE);
            }
        }

        // numeric
        if (leftType.isFloatType() || leftType.isDoubleType()
                || rightType.isFloatType() || rightType.isDoubleType()) {
            return Optional.of(DoubleType.INSTANCE);
        }
        if (leftType.isNumericType() && rightType.isNumericType()) {
            DataType commonType = leftType;
            for (DataType dataType : NUMERIC_PRECEDENCE) {
                if (leftType.equals(dataType) || rightType.equals(dataType)) {
                    commonType = dataType;
                    break;
                }
            }
            if (leftType instanceof DecimalV3Type || rightType instanceof DecimalV3Type) {
                return Optional.of(DecimalV3Type.widerDecimalV3Type(
                        DecimalV3Type.forType(leftType), DecimalV3Type.forType(rightType), true));
            }
            if (leftType instanceof DecimalV2Type || rightType instanceof DecimalV2Type) {
                if (leftType instanceof BigIntType || rightType instanceof BigIntType
                        || leftType instanceof LargeIntType || rightType instanceof LargeIntType) {
                    // only decimalv3 can hold big or large int
                    return Optional
                            .of(DecimalV3Type.widerDecimalV3Type(DecimalV3Type.forType(leftType),
                                    DecimalV3Type.forType(rightType), true));
                } else {
                    return Optional.of(DecimalV2Type.widerDecimalV2Type(
                            DecimalV2Type.forType(leftType), DecimalV2Type.forType(rightType)));
                }
            }
            return Optional.of(commonType);
        }

        // ip type
        if ((leftType.isIPv4Type() && rightType.isStringLikeType())
                || (rightType.isIPv4Type() && leftType.isStringLikeType())) {
            return Optional.of(IPv4Type.INSTANCE);
        }
        if ((leftType.isIPv6Type() && rightType.isStringLikeType())
                || (rightType.isIPv6Type() && leftType.isStringLikeType())
                || (leftType.isIPv4Type() && rightType.isIPv6Type())
                || (leftType.isIPv6Type() && rightType.isIPv4Type())) {
            return Optional.of(IPv6Type.INSTANCE);
        }

        // variant type
        if ((leftType.isVariantType() && (rightType.isStringLikeType() || rightType.isNumericType()))) {
            if (rightType.isDecimalLikeType()) {
                // TODO support decimal
                return Optional.of(DoubleType.INSTANCE);
            }
            return Optional.of(rightType);
        }
        if ((rightType.isVariantType() && (leftType.isStringLikeType() || leftType.isNumericType()))) {
            if (leftType.isDecimalLikeType()) {
                // TODO support decimal
                return Optional.of(DoubleType.INSTANCE);
            }
            return Optional.of(leftType);
        }
        return Optional.of(DoubleType.INSTANCE);
    }