in fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java [1580:1721]
protected static Optional<DataType> findCommonPrimitiveTypeForCaseWhen(DataType t1, DataType t2) {
if (!(t1 instanceof PrimitiveType) || !(t2 instanceof PrimitiveType)) {
return Optional.empty();
}
if (t1.equals(t2)) {
return Optional.of(t1);
}
if (t1.isNullType()) {
return Optional.of(t2);
}
if (t2.isNullType()) {
return Optional.of(t1);
}
// objectType only support compare with itself, so return empty here.
if (t1.isObjectType() || t2.isObjectType()) {
return Optional.empty();
}
// TODO: support ALL type
// string-like vs all other type
if (t1.isStringLikeType() || t2.isStringLikeType()) {
if ((t1.isCharType() || t1.isVarcharType()) && (t2.isCharType() || t2.isVarcharType())) {
int len = Math.max(((CharacterType) t1).getLen(), ((CharacterType) t2).getLen());
if (((CharacterType) t1).getLen() < 0 || ((CharacterType) t2).getLen() < 0) {
len = VarcharType.SYSTEM_DEFAULT.getLen();
}
return Optional.of(VarcharType.createVarcharType(len));
}
return Optional.of(StringType.INSTANCE);
}
// forbidden decimal with date
if ((t1.isDecimalV2Type() && t2.isDateType()) || (t2.isDecimalV2Type() && t1.isDateType())) {
return Optional.empty();
}
if ((t1.isDecimalV2Type() && t2.isDateV2Type()) || (t2.isDecimalV2Type() && t1.isDateV2Type())) {
return Optional.empty();
}
if ((t1.isDecimalV3Type() && t2.isDateType()) || (t2.isDecimalV3Type() && t1.isDateType())) {
return Optional.empty();
}
if ((t1.isDecimalV3Type() && t2.isDateV2Type()) || (t2.isDecimalV3Type() && t1.isDateV2Type())) {
return Optional.empty();
}
// decimalv3 and floating type
if (t1.isDecimalV3Type() || t2.isDecimalV3Type()) {
if (t1.isFloatType() || t2.isDoubleType() || t1.isDoubleType() || t2.isFloatType()) {
return Optional.of(DoubleType.INSTANCE);
}
}
// decimal precision derive
if (t1.isDecimalV3Type() || t2.isDecimalV3Type()) {
return Optional.of(DecimalV3Type.widerDecimalV3Type(
DecimalV3Type.forType(t1), DecimalV3Type.forType(t2), true));
}
// decimalv2 and floating type
if (t1.isDecimalV2Type() || t2.isDecimalV2Type()) {
if (t1.isFloatType() || t2.isDoubleType() || t1.isDoubleType() || t2.isFloatType()) {
return Optional.of(DoubleType.INSTANCE);
}
}
if (t1.isDecimalV2Type() || t2.isDecimalV2Type()) {
return Optional.of(DecimalV2Type.widerDecimalV2Type(DecimalV2Type.forType(t1), DecimalV2Type.forType(t2)));
}
// date-like type
if (t1.isDateTimeV2Type() && t2.isDateTimeV2Type()) {
return Optional.of(DateTimeV2Type.getWiderDatetimeV2Type((DateTimeV2Type) t1, (DateTimeV2Type) t2));
}
if (t1.isDateLikeType() && t2.isDateLikeType()) {
if (t1.isDateTimeV2Type()) {
return Optional.of(t1);
}
if (t2.isDateTimeV2Type()) {
return Optional.of(t2);
}
if (t1.isDateV2Type() || t2.isDateV2Type()) {
// datev2 vs datetime
if (t1.isDateTimeType() || t2.isDateTimeType()) {
return Optional.of(DateTimeV2Type.SYSTEM_DEFAULT);
}
// datev2 vs date
return Optional.of(DateV2Type.INSTANCE);
}
// date vs datetime
return Optional.of(DateTimeType.INSTANCE);
}
if (t1.isDateLikeType() || t2.isDateLikeType()) {
DataType dateType = t1;
DataType otherType = t2;
if (t2.isDateLikeType()) {
dateType = t2;
otherType = t1;
}
if (dateType.isDateType() || dateType.isDateV2Type()) {
if (otherType.isIntegerType() || otherType.isBigIntType() || otherType.isLargeIntType()) {
return Optional.of(otherType);
}
}
if (dateType.isDateTimeType() || dateType.isDateTimeV2Type()) {
if (otherType.isLargeIntType() || otherType.isDoubleType()) {
return Optional.of(otherType);
}
}
return Optional.empty();
}
// time-like vs all other type
if (t1.isTimeLikeType() && t2.isTimeLikeType()) {
if (t1.isTimeType() && t2.isTimeType()) {
return Optional.of(TimeType.INSTANCE);
}
return Optional.of(TimeV2Type.INSTANCE);
}
if (t1.isTimeLikeType() || t2.isTimeLikeType()) {
if (t1.isNumericType() || t2.isNumericType() || t1.isBooleanType() || t2.isBooleanType()) {
return Optional.of(DoubleType.INSTANCE);
}
return Optional.empty();
}
// string-like, null, objected, decimal, date-like and time already processed
// so only need to process numeric type without decimal plus boolean.
if ((t1.isFloatType() && t2.isLargeIntType()) || (t1.isLargeIntType() && t2.isFloatType())) {
return Optional.of(DoubleType.INSTANCE);
}
for (DataType dataType : NUMERIC_PRECEDENCE) {
if (t1.equals(dataType) || t2.equals(dataType)) {
return Optional.of(dataType);
}
}
return Optional.empty();
}