From 40d1a1ecc1c3440b4217c3debcdffa4656b1d8bc Mon Sep 17 00:00:00 2001 From: sdc Date: Mon, 6 May 2024 02:46:46 +0000 Subject: [PATCH] fix some bugs --- .../src/lib/timezone/ob_time_convert.cpp | 36 ++++++++++++---- deps/oblib/src/lib/timezone/ob_time_convert.h | 2 + .../lib/timezone/test_ob_time_convert.cpp | 6 +-- src/sql/engine/expr/ob_datum_cast.h | 1 + src/sql/engine/expr/ob_expr_date_format.h | 21 +++------- .../engine/expr/ob_expr_from_unix_time.cpp | 13 ++++-- src/sql/engine/expr/ob_expr_time.h | 42 +------------------ 7 files changed, 51 insertions(+), 70 deletions(-) diff --git a/deps/oblib/src/lib/timezone/ob_time_convert.cpp b/deps/oblib/src/lib/timezone/ob_time_convert.cpp index d23227b61f..5415f6cae0 100644 --- a/deps/oblib/src/lib/timezone/ob_time_convert.cpp +++ b/deps/oblib/src/lib/timezone/ob_time_convert.cpp @@ -1802,6 +1802,9 @@ int ObTimeConverter::int_to_ob_time_without_date(int64_t time_second, ObTime &ob } else { parts[DT_HOUR] = TIME_MAX_HOUR + 1; } + if (OB_SUCC(ret)) { + adjust_ob_time(ob_time); + } UNUSED(mode); return ret; } @@ -1990,6 +1993,7 @@ int ObTimeConverter::str_to_ob_time_with_date(const ObString &str, ObTime &ob_ti LOG_WARN("datetime is invalid or out of range", K(ret), K(str), K(ob_time), K(date_sql_mode), KCSTRING(lbt())); } else { + adjust_ob_time(ob_time); ob_time.parts_[DT_DATE] = ob_time_to_date(ob_time); } if (NULL != scale) { @@ -2152,17 +2156,11 @@ int ObTimeConverter::str_to_ob_time_without_date(const ObString &str, ObTime &ob } if (OB_SUCC(ret) && OB_FAIL(validate_time(ob_time))) { LOG_WARN("time value is invalid or out of range", K(ret), K(str)); - } else { - // '2:59:59.9999999' ---> '03:00:00.000000' - const int64_t *part_max = DT_PART_BASE; - for (int i = DATETIME_PART_CNT - 1; OB_SUCC(ret) && i > DATE_PART_CNT; i--) { - if (ob_time.parts_[i] == part_max[i]) { - ob_time.parts_[i] = 0; - ob_time.parts_[i - 1]++; - } - } } } + if (OB_SUCC(ret)) { + adjust_ob_time(ob_time); + } } } return ret; @@ -3136,6 +3134,26 @@ int ObTimeConverter::data_fmt_s(char *buffer, int64_t buf_len, int64_t &pos, con return ret; } +void ObTimeConverter::adjust_ob_time(ObTime &ob_time) +{ + // '2:59:59.9999995' ---> '03:00:00.000000' + for (int i = DATETIME_PART_CNT - 1; i > DT_MDAY; i--) { + if (ob_time.parts_[i] == DT_PART_BASE[i]) { + ob_time.parts_[i] -= DT_PART_BASE[i]; + ob_time.parts_[i - 1]++; + } + } + int32_t days = DAYS_PER_MON[IS_LEAP_YEAR(ob_time.parts_[DT_YEAR])][ob_time.parts_[DT_MON]]; + if (ob_time.parts_[DT_MDAY] > days) { + ob_time.parts_[DT_MDAY] -= days; + ob_time.parts_[DT_MON]++; + } + if (ob_time.parts_[DT_MON] > 12) { + ob_time.parts_[DT_MON] -= 12; + ob_time.parts_[DT_YEAR]++; + } +} + /** * @brief ObTimeConverter::str_to_ob_time_oracle_strict * convert str to ob_time according to oracle literal format of DATE or TIMESTAMP diff --git a/deps/oblib/src/lib/timezone/ob_time_convert.h b/deps/oblib/src/lib/timezone/ob_time_convert.h index c85f94d1c3..89747653e0 100644 --- a/deps/oblib/src/lib/timezone/ob_time_convert.h +++ b/deps/oblib/src/lib/timezone/ob_time_convert.h @@ -581,6 +581,8 @@ public: static int data_fmt_nd(char *buffer, int64_t buf_len, int64_t &pos, const int64_t n, int64_t target, bool has_fm_flag = false); static int data_fmt_d(char *buffer, int64_t buf_len, int64_t &pos, int64_t target); static int data_fmt_s(char *buffer, int64_t buf_len, int64_t &pos, const char *ptr); + // check each part of ObTime and carry if necessary. + static void adjust_ob_time(ObTime &ot); public: // other functions. diff --git a/deps/oblib/unittest/lib/timezone/test_ob_time_convert.cpp b/deps/oblib/unittest/lib/timezone/test_ob_time_convert.cpp index 97b6c1a436..6962ed7607 100644 --- a/deps/oblib/unittest/lib/timezone/test_ob_time_convert.cpp +++ b/deps/oblib/unittest/lib/timezone/test_ob_time_convert.cpp @@ -2396,7 +2396,7 @@ TEST(ObTimeConvertTest, str_to_ob_time) STR_TO_OB_TIME_FAIL("2015-05-30 24:12:13.1415", DT_TYPE_DATETIME); STR_TO_OB_TIME_FAIL("2015-05-30 11:60:13.1415", DT_TYPE_DATETIME); STR_TO_OB_TIME_FAIL("2015-05-30 11:12:60.1415", DT_TYPE_DATETIME); - STR_TO_OB_TIME_SUCC("2015-12-31 23:59:59.9999999", DT_TYPE_DATETIME, 2015, 12, 31, 23, 59, 59, 1000000); + STR_TO_OB_TIME_SUCC("2015-12-31 23:59:59.9999999", DT_TYPE_DATETIME, 2016, 1, 1, 00, 00, 00, 000000); STR_TO_OB_TIME_FAIL("10", DT_TYPE_DATETIME); STR_TO_OB_TIME_FAIL("101", DT_TYPE_DATETIME); STR_TO_OB_TIME_FAIL("1011", DT_TYPE_DATETIME); @@ -2596,7 +2596,7 @@ TEST(ObTimeConvertTest, str_to_ob_time) STR_TO_OB_TIME_FAIL("2015-05-30 24:12:13.1415", DT_TYPE_DATE); STR_TO_OB_TIME_FAIL("2015-05-30 11:60:13.1415", DT_TYPE_DATE); STR_TO_OB_TIME_FAIL("2015-05-30 11:12:60.1415", DT_TYPE_DATE); - STR_TO_OB_TIME_SUCC("2015-12-31 23:59:59.9999999", DT_TYPE_DATE, 2015, 12, 31, -1, -1, -1, -1); + STR_TO_OB_TIME_SUCC("2015-12-31 23:59:59.9999999", DT_TYPE_DATE, 2016, 1, 1, -1, -1, -1, -1); STR_TO_OB_TIME_FAIL("10", DT_TYPE_DATE); STR_TO_OB_TIME_FAIL("101", DT_TYPE_DATE); STR_TO_OB_TIME_FAIL("1011", DT_TYPE_DATE); @@ -2796,7 +2796,7 @@ TEST(ObTimeConvertTest, str_to_ob_time) STR_TO_OB_TIME_FAIL("2015-05-30 24:12:13.1415", DT_TYPE_TIME); STR_TO_OB_TIME_FAIL("2015-05-30 11:60:13.1415", DT_TYPE_TIME); STR_TO_OB_TIME_FAIL("2015-05-30 11:12:60.1415", DT_TYPE_TIME); - STR_TO_OB_TIME_SUCC("2015-12-31 23:59:59.9999999", DT_TYPE_TIME, -1, -1, -1, 23, 59, 59, 1000000); + STR_TO_OB_TIME_SUCC("2015-12-31 23:59:59.9999999", DT_TYPE_TIME, -1, -1, -1, 0, 0, 0, 000000); STR_TO_OB_TIME_SUCC("10", DT_TYPE_TIME, -1, -1, -1, 0, 0, 10, 0); STR_TO_OB_TIME_SUCC("101", DT_TYPE_TIME, -1, -1, -1, 0, 1, 1, 0); STR_TO_OB_TIME_SUCC("1011", DT_TYPE_TIME, -1, -1, -1, 0, 10, 11, 0); diff --git a/src/sql/engine/expr/ob_datum_cast.h b/src/sql/engine/expr/ob_datum_cast.h index 4ced8e61a7..24427f7df1 100644 --- a/src/sql/engine/expr/ob_datum_cast.h +++ b/src/sql/engine/expr/ob_datum_cast.h @@ -159,6 +159,7 @@ int ob_datum_to_ob_time_with_date(const T &datum, ret = ObTimeConverter::int_to_ob_time_with_date(int_part, ob_time, date_sql_mode); if (OB_SUCC(ret)) { ob_time.parts_[DT_USEC] = (dec_part + 500) / 1000; + ObTimeConverter::adjust_ob_time(ob_time); } } break; diff --git a/src/sql/engine/expr/ob_expr_date_format.h b/src/sql/engine/expr/ob_expr_date_format.h index 35ce535641..98857b8037 100644 --- a/src/sql/engine/expr/ob_expr_date_format.h +++ b/src/sql/engine/expr/ob_expr_date_format.h @@ -54,27 +54,18 @@ inline int ObExprDateFormat::calc_result_type2(ObExprResType &type, UNUSED(date); UNUSED(format); int ret = common::OB_SUCCESS; -// common::ObCollationType collation_connection = common::CS_TYPE_INVALID; type.set_varchar(); type.set_collation_type(type_ctx.get_coll_type()); type.set_collation_level(common::CS_LEVEL_COERCIBLE); type.set_length(DATETIME_MAX_LENGTH); - date.set_calc_collation_type(type.get_collation_type()); - format.set_calc_collation_type(type.get_collation_type()); - - if (OB_SUCC(ret)) { - //for enum or set obj, we need calc type - if (ob_is_enum_or_set_type(date.get_type())) { - date.set_calc_type(common::ObVarcharType); - } else if (ob_is_double_tc(date.get_type()) || ob_is_float_tc(date.get_type())) { - date.set_calc_type(common::ObNumberType); - } - if (ob_is_enum_or_set_type(format.get_type())) { - format.set_calc_type(common::ObVarcharType); - } + //for enum or set obj, we need calc type + if (ob_is_enum_or_set_type(date.get_type()) || ob_is_string_type(date.get_type())) { + date.set_calc_type_default_varchar(); + } else if (ob_is_double_tc(date.get_type()) || ob_is_float_tc(date.get_type())) { + date.set_calc_type(common::ObNumberType); } - + format.set_calc_type_default_varchar(); return ret; } diff --git a/src/sql/engine/expr/ob_expr_from_unix_time.cpp b/src/sql/engine/expr/ob_expr_from_unix_time.cpp index 3509d54a3b..4fa4ee95e3 100644 --- a/src/sql/engine/expr/ob_expr_from_unix_time.cpp +++ b/src/sql/engine/expr/ob_expr_from_unix_time.cpp @@ -319,10 +319,17 @@ int ObExprFromUnixTime::get_usec_from_datum(const common::ObDatum ¶m_datum, LOG_WARN("failed to get number", K(ret)); } else if (OB_FAIL(param1.mul(param2, res, alloc))) { LOG_WARN("failed to mul", K(ret)); - } else if (OB_LIKELY(res.is_valid_int64(tmp))) { - usec_val = tmp; + } else if (OB_FAIL(res.extract_valid_int64_with_round(tmp))) { + if (OB_DATA_OUT_OF_RANGE == ret) { + ret = OB_ERR_TRUNCATED_WRONG_VALUE; + ObString dec("DECIMAL"); + const char *num_str = param2_tmp.format(); + LOG_USER_ERROR(OB_ERR_TRUNCATED_WRONG_VALUE, dec.length(), dec.ptr(), + static_cast(strlen(num_str)), num_str); + } + LOG_WARN("extract valid int64 with round failed", K(ret), K(res)); } else { - ret = OB_ERR_TRUNCATED_WRONG_VALUE; + usec_val = tmp; } return ret; } diff --git a/src/sql/engine/expr/ob_expr_time.h b/src/sql/engine/expr/ob_expr_time.h index 8b640d41c8..06bbaf4568 100644 --- a/src/sql/engine/expr/ob_expr_time.h +++ b/src/sql/engine/expr/ob_expr_time.h @@ -66,10 +66,10 @@ inline int ObExprTimeBase::calc_result_type1(ObExprResType &type, type.set_precision(4); type.set_scale(0); common::ObObjTypeClass tc1 = ob_obj_type_class(type1.get_type()); - if (common::ObEnumSetTC == tc1) { + if (ob_is_enum_or_set_type(type1.get_type()) || ob_is_string_type(type1.get_type())) { type1.set_calc_type_default_varchar(); } else if ((common::ObFloatTC == tc1) || (common::ObDoubleTC == tc1)) { - type1.set_calc_type(common::ObIntType); + type1.set_calc_type(common::ObNumberType); } return common::OB_SUCCESS; } @@ -102,60 +102,22 @@ public: ObExprSecond(); explicit ObExprSecond(common::ObIAllocator &alloc); virtual ~ObExprSecond(); - virtual int calc_result_type1(ObExprResType &type, - ObExprResType &type1, - common::ObExprTypeCtx &type_ctx) const; static int calc_second(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); private: DISALLOW_COPY_AND_ASSIGN(ObExprSecond); }; -inline int ObExprSecond::calc_result_type1(ObExprResType &type, - ObExprResType &type1, - common::ObExprTypeCtx &type_ctx) const -{ - type.set_int32(); - type.set_precision(4); - type.set_scale(0); - common::ObObjTypeClass tc1 = ob_obj_type_class(type1.get_type()); - if ((common::ObEnumSetTC == tc1)) { - type1.set_calc_type_default_varchar(); - } else if ((common::ObFloatTC == tc1) || (common::ObDoubleTC == tc1)) { - type1.set_calc_type(common::ObNumberType); - } - return common::OB_SUCCESS; -} - class ObExprMicrosecond: public ObExprTimeBase { public: ObExprMicrosecond(); explicit ObExprMicrosecond(common::ObIAllocator &alloc); virtual ~ObExprMicrosecond(); - virtual int calc_result_type1(ObExprResType &type, - ObExprResType &type1, - common::ObExprTypeCtx &type_ctx) const; static int calc_microsecond(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); private: DISALLOW_COPY_AND_ASSIGN(ObExprMicrosecond); }; -inline int ObExprMicrosecond::calc_result_type1(ObExprResType &type, - ObExprResType &type1, - common::ObExprTypeCtx &type_ctx) const -{ - type.set_int32(); - type.set_precision(4); - type.set_scale(0); - common::ObObjTypeClass tc1 = ob_obj_type_class(type1.get_type()); - if ((common::ObEnumSetTC == tc1)) { - type1.set_calc_type_default_varchar(); - } else if ((common::ObFloatTC == tc1) || (common::ObDoubleTC == tc1)) { - type1.set_calc_type(common::ObNumberType); - } - return common::OB_SUCCESS; -} - class ObExprYear: public ObExprTimeBase { public: