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);
}