diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index 471a8e50e9677cbc49cfc89da3344ceca7f2e49c..8baf4384bafc8dffb4211bae23a46445b3697e64 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -598,13 +598,11 @@ int real_range_check_only(const ObAccuracy &accuracy, Type value) if (OB_LIKELY(precision > 0) && OB_LIKELY(scale >= 0) && OB_LIKELY(precision >= scale)) { - // Because double type represents a larger width, use double type instead of float to check - // result range. - double integer_part = static_cast(pow(10.0, static_cast(precision - scale))); - double decimal_part = static_cast(pow(10.0, static_cast(scale))); - double max_value = integer_part - 1 / decimal_part; - double min_value = -max_value; - if (OB_FAIL(numeric_range_check(static_cast(value), min_value, max_value, value))) { + Type integer_part = static_cast(pow(10.0, static_cast(precision - scale))); + Type decimal_part = static_cast(pow(10.0, static_cast(scale))); + Type max_value = integer_part - 1 / decimal_part; + Type min_value = -max_value; + if (OB_FAIL(numeric_range_check(value, min_value, max_value, value))) { } } return ret; diff --git a/src/share/object/ob_obj_cast_util.h b/src/share/object/ob_obj_cast_util.h index 2014fd429dede0f02afd28c94b9ed09a9e5059fc..503337d8f0a41793c0c0a059993e4f2c7d9b2250 100644 --- a/src/share/object/ob_obj_cast_util.h +++ b/src/share/object/ob_obj_cast_util.h @@ -84,27 +84,6 @@ OB_INLINE int numeric_range_check(const double in_val, return ret; } -// check range using double type -OB_INLINE int numeric_range_check(const double in_val, - const double min_out_val, - const double max_out_val, - float &out_val) -{ - int ret = OB_SUCCESS; - if (isinf(in_val)) { - out_val = static_cast(in_val); - } else { - if (in_val < min_out_val) { - ret = OB_DATA_OUT_OF_RANGE; - out_val = static_cast(min_out_val); - } else if (in_val > max_out_val) { - ret = OB_DATA_OUT_OF_RANGE; - out_val = static_cast(max_out_val); - } - } - return ret; -} - // check if is negative only. template OB_INLINE int numeric_negative_check(OutType &out_val) @@ -191,13 +170,11 @@ int real_range_check(const ObAccuracy &accuracy, Type &value) if (OB_LIKELY(precision > 0) && OB_LIKELY(scale >= 0) && OB_LIKELY(precision >= scale)) { - // Because double type represents a larger width, use double type instead of float to check - // result range. - double integer_part = static_cast(pow(10.0, static_cast(precision - scale))); - double decimal_part = static_cast(pow(10.0, static_cast(scale))); - double max_value = static_cast(integer_part - 1 / decimal_part); - double min_value = static_cast(-max_value); - if (OB_FAIL(numeric_range_check(static_cast(value), min_value, max_value, value))) { + Type integer_part = static_cast(pow(10.0, static_cast(precision - scale))); + Type decimal_part = static_cast(pow(10.0, static_cast(scale))); + Type max_value = static_cast(integer_part - 1 / decimal_part); + Type min_value = static_cast(-max_value); + if (OB_FAIL(numeric_range_check(value, min_value, max_value, value))) { } else { value = static_cast(rint((value - floor(static_cast(value)))* decimal_part) / diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index f4d9c60626b804e88eafba03199c747168ac0ad6..dcb49f8a8ef5bd81e2832966147cbcb3f9c19c14 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -1092,8 +1092,20 @@ static OB_INLINE int common_double_float(const ObExpr &expr, ObObjType out_type = expr.datum_meta_.type_; // oracle support float/double infiniy, no need to verify data overflow. // C language would cast value to infinity, which is correct behavor in oracle mode - if (lib::is_mysql_mode() && CAST_FAIL(real_range_check(out_type, in_val, out_val))) { - LOG_WARN("real_range_check failed", K(ret), K(in_val)); + if (lib::is_mysql_mode()) { + double truncated_val = in_val; + if (ob_is_float_tc(out_type) && CM_IS_COLUMN_CONVERT(expr.extra_)) { + // truncate float value if its ps information is fixed. + ObAccuracy accuracy(expr.datum_meta_.precision_, expr.datum_meta_.scale_); + if (CAST_FAIL(real_range_check(accuracy, truncated_val))) { + LOG_WARN("fail to real range check", K(ret)); + } else { + out_val = static_cast(truncated_val); + } + } + if (OB_SUCC(ret) && CAST_FAIL(real_range_check(out_type, truncated_val, out_val))) { + LOG_WARN("real_range_check failed", K(ret), K(in_val)); + } } return ret; }