in fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java [341:494]
private Type getCmpType() throws AnalysisException {
if (!getChild(0).isConstantImpl() && getChild(1).isConstantImpl()) {
getChild(1).compactForLiteral(getChild(0).getType());
} else if (!getChild(1).isConstantImpl() && getChild(0).isConstantImpl()) {
getChild(0).compactForLiteral(getChild(1).getType());
}
PrimitiveType t1 = getChild(0).getType().getResultType().getPrimitiveType();
PrimitiveType t2 = getChild(1).getType().getResultType().getPrimitiveType();
for (Expr e : getChildren()) {
if (e.getType().getPrimitiveType() == PrimitiveType.HLL) {
throw new AnalysisException("Hll type dose not support operand: " + toSql());
}
if (e.getType().getPrimitiveType() == PrimitiveType.BITMAP) {
throw new AnalysisException("Bitmap type dose not support operand: " + toSql());
}
if (e.getType().isArrayType()) {
throw new AnalysisException("Array type dose not support operand: " + toSql());
}
}
if (canCompareDate(getChild(0).getType().getPrimitiveType(), getChild(1).getType().getPrimitiveType())) {
if (getChild(0).getType().isDatetimeV2() && getChild(1).getType().isDatetimeV2()) {
Preconditions.checkArgument(getChild(0).getType() instanceof ScalarType
&& getChild(1).getType() instanceof ScalarType);
return dateV2ComparisonResultType((ScalarType) getChild(0).getType(),
(ScalarType) getChild(1).getType());
} else if (getChild(0).getType().isDatetimeV2()) {
return getChild(0).getType();
} else if (getChild(1).getType().isDatetimeV2()) {
return getChild(1).getType();
} else if (getChild(0).getType().isDateV2()
&& (getChild(1).getType().isDate() || getChild(1).getType().isDateV2())) {
return getChild(0).getType();
} else if (getChild(1).getType().isDateV2()
&& (getChild(0).getType().isDate() || getChild(0).getType().isDateV2())) {
return getChild(1).getType();
} else if (getChild(0).getType().isDateV2()
&& (getChild(1).getType().isStringType() && getChild(1) instanceof StringLiteral)) {
if (((StringLiteral) getChild(1)).canConvertToDateType(Type.DATEV2)) {
return Type.DATEV2;
} else {
return Type.DATETIMEV2;
}
} else if (getChild(1).getType().isDateV2()
&& (getChild(0).getType().isStringType() && getChild(0) instanceof StringLiteral)) {
if (((StringLiteral) getChild(0)).canConvertToDateType(Type.DATEV2)) {
return Type.DATEV2;
} else {
return Type.DATETIMEV2;
}
} else if (getChild(0).getType().isDatetimeV2()
&& (getChild(1).getType().isStringType() && getChild(1) instanceof StringLiteral)) {
return getChild(0).getType();
} else if (getChild(1).getType().isDatetimeV2()
&& (getChild(0).getType().isStringType() && getChild(0) instanceof StringLiteral)) {
return getChild(1).getType();
} else if (getChild(0).getType().isDate()
&& (getChild(1).getType().isStringType() && getChild(1) instanceof StringLiteral)) {
return ((StringLiteral) getChild(1)).canConvertToDateType(Type.DATE) ? Type.DATE : Type.DATETIME;
} else if (getChild(1).getType().isDate()
&& (getChild(0).getType().isStringType() && getChild(0) instanceof StringLiteral)) {
return ((StringLiteral) getChild(0)).canConvertToDateType(Type.DATE) ? Type.DATE : Type.DATETIME;
} else if (getChild(1).getType().isDate() && getChild(0).getType().isDate()) {
return Type.DATE;
} else {
return Type.DATETIME;
}
}
if (canCompareIP(getChild(0).getType().getPrimitiveType(), getChild(1).getType().getPrimitiveType())) {
if ((getChild(0).getType().isIP() && getChild(1) instanceof StringLiteral)
|| (getChild(1).getType().isIP() && getChild(0) instanceof StringLiteral)
|| (getChild(0).getType().isIP() && getChild(1).getType().isIP())) {
if (getChild(0).getType().isIPv4() || getChild(1).getType().isIPv4()) {
return Type.IPV4;
}
if (getChild(0).getType().isIPv6() || getChild(1).getType().isIPv6()) {
return Type.IPV6;
}
}
}
// Following logical is compatible with MySQL:
// Cast to DOUBLE by default, because DOUBLE has the largest range of values.
if (t1 == PrimitiveType.VARCHAR && t2 == PrimitiveType.VARCHAR) {
return Type.VARCHAR;
}
if ((t1 == PrimitiveType.STRING && (t2 == PrimitiveType.VARCHAR || t2 == PrimitiveType.STRING)) || (
t2 == PrimitiveType.STRING && (t1 == PrimitiveType.VARCHAR || t1 == PrimitiveType.STRING))) {
return Type.STRING;
}
if (t1 == PrimitiveType.BIGINT && t2 == PrimitiveType.BIGINT) {
return Type.getAssignmentCompatibleType(getChild(0).getType(), getChild(1).getType(), false,
SessionVariable.getEnableDecimal256());
}
if (t1 == PrimitiveType.DECIMALV2 && t2 == PrimitiveType.DECIMALV2) {
return ScalarType.getAssignmentCompatibleDecimalV2Type((ScalarType) getChild(0).getType(),
(ScalarType) getChild(1).getType());
}
if ((t1 == PrimitiveType.BIGINT && t2 == PrimitiveType.DECIMALV2)
|| (t2 == PrimitiveType.BIGINT && t1 == PrimitiveType.DECIMALV2)
|| (t1 == PrimitiveType.LARGEINT && t2 == PrimitiveType.DECIMALV2)
|| (t2 == PrimitiveType.LARGEINT && t1 == PrimitiveType.DECIMALV2)) {
// only decimalv3 can hold big and large int
return ScalarType.createDecimalType(PrimitiveType.DECIMAL128, ScalarType.MAX_DECIMAL128_PRECISION,
ScalarType.MAX_DECIMALV2_SCALE);
}
if ((t1 == PrimitiveType.BIGINT || t1 == PrimitiveType.LARGEINT)
&& (t2 == PrimitiveType.BIGINT || t2 == PrimitiveType.LARGEINT)) {
return Type.LARGEINT;
}
// Implicit conversion affects query performance.
// For a common example datekey='20200825' which datekey is int type.
// If we up conversion to double type directly.
// PartitionPruner will not take effect. Then it will scan all partitions.
// When int column compares with string, Mysql will convert string to int.
// So it is also compatible with Mysql.
if (t1.isStringType() || t2.isStringType()) {
if ((t1 == PrimitiveType.BIGINT || t1 == PrimitiveType.LARGEINT) && TypeUtils.canParseTo(getChild(1), t1)) {
return Type.fromPrimitiveType(t1);
}
if ((t2 == PrimitiveType.BIGINT || t2 == PrimitiveType.LARGEINT) && TypeUtils.canParseTo(getChild(0), t2)) {
return Type.fromPrimitiveType(t2);
}
}
if ((t1.isDecimalV3Type() && !t2.isStringType() && !t2.isFloatingPointType() && !t2.isVariantType())
|| (t2.isDecimalV3Type() && !t1.isStringType() && !t1.isFloatingPointType() && !t1.isVariantType())) {
return Type.getAssignmentCompatibleType(getChild(0).getType(), getChild(1).getType(), false,
SessionVariable.getEnableDecimal256());
}
// Variant can be implicit cast to numeric type and string type at present
if (t1.isVariantType() && (t2.isNumericType() || t2.isStringType())) {
if (t2.isDecimalV2Type() || t2.isDecimalV3Type()) {
// TODO support decimal
return Type.DOUBLE;
}
return Type.fromPrimitiveType(t2);
}
if (t2.isVariantType() && (t1.isNumericType() || t1.isStringType())) {
if (t1.isDecimalV2Type() || t1.isDecimalV3Type()) {
return Type.DOUBLE;
}
return Type.fromPrimitiveType(t1);
}
return Type.DOUBLE;
}