diff --git a/deps/oblib/src/common/cell/ob_cell_writer.cpp b/deps/oblib/src/common/cell/ob_cell_writer.cpp index 02bd6bb9b2..836a7f3ca9 100644 --- a/deps/oblib/src/common/cell/ob_cell_writer.cpp +++ b/deps/oblib/src/common/cell/ob_cell_writer.cpp @@ -12,6 +12,7 @@ #include "common/cell/ob_cell_writer.h" #include "common/object/ob_object.h" +#include "lib/timezone/ob_time_convert.h" namespace oceanbase { namespace common @@ -505,7 +506,7 @@ int ObCellWriter::append(uint64_t column_id, const ObObj &obj, ObObj *clone_obj) WRITE_DATA(ObTimestampType, 0, int64_t, obj.get_timestamp()); break; case ObTimeType: { - const int64_t ob_time_max_value = 3020399999999; // 838:59:59 + const int64_t ob_time_max_value = TIME_MAX_VAL; assert(obj.get_time() <= ob_time_max_value && obj.get_time() >= -ob_time_max_value); WRITE_DATA(ObTimeType, 0, int64_t, obj.get_time()); break; diff --git a/deps/oblib/src/lib/timezone/ob_time_convert.cpp b/deps/oblib/src/lib/timezone/ob_time_convert.cpp index addda5350d..abe71d30b1 100644 --- a/deps/oblib/src/lib/timezone/ob_time_convert.cpp +++ b/deps/oblib/src/lib/timezone/ob_time_convert.cpp @@ -792,8 +792,7 @@ int ObTimeConverter::str_to_date(const ObString &str, int32_t &value, return ret; } -int ObTimeConverter::str_to_time(const ObString &str, int64_t &value, int16_t *scale, - const ObScale &time_scale, const bool &need_truncate) +int ObTimeConverter::str_to_time(const ObString &str, int64_t &value, int16_t *scale, const bool &need_truncate) { int ret = OB_SUCCESS; ObTime ob_time(DT_TYPE_TIME); @@ -801,14 +800,14 @@ int ObTimeConverter::str_to_time(const ObString &str, int64_t &value, int16_t *s LOG_WARN("failed to convert string to time", K(ret), K(str)); if (OB_ERR_TRUNCATED_WRONG_VALUE == ret) { value = ob_time_to_time(ob_time); - time_overflow_trunc(value, time_scale); + time_overflow_trunc(value); if (DT_MODE_NEG & ob_time.mode_) { value = -value; } } } else { value = ob_time_to_time(ob_time); - ret = time_overflow_trunc(value, time_scale); + ret = time_overflow_trunc(value); if (DT_MODE_NEG & ob_time.mode_) { value = -value; } @@ -5386,8 +5385,7 @@ int ObTimeConverter::set_ob_time_year_may_conflict(ObTime &ob_time, int32_t &jul int ObTimeConverter::time_overflow_trunc(int64_t &value, const ObScale &time_scale) { int ret = OB_SUCCESS; - int64_t increment = (6 == time_scale) ? 999999 : 0; - if (value > (TIME_MAX_VAL + increment)) { + if (value > TIME_MAX_VAL) { // we need some ob error codes that map to ER_TRUNCATED_WRONG_VALUE, // so we get OB_INVALID_DATE_FORMAT / OB_INVALID_DATE_VALUE / OB_ERR_TRUNCATED_WRONG_VALUE. // another requirement comes from cast function in ob_obj_cast.cpp is this time object will be @@ -5395,7 +5393,7 @@ int ObTimeConverter::time_overflow_trunc(int64_t &value, const ObScale &time_sca // so we get the ONLY one: OB_ERR_TRUNCATED_WRONG_VALUE, because the other two will direct to // ZERO_VAL of the temporal types, like cast 'abc' or '1998-76-54' to date. ret = OB_ERR_TRUNCATED_WRONG_VALUE; - value = TIME_MAX_VAL + increment; + value = TIME_MAX_VAL; } return ret; } diff --git a/deps/oblib/src/lib/timezone/ob_time_convert.h b/deps/oblib/src/lib/timezone/ob_time_convert.h index 1a4cc241b5..562561015e 100644 --- a/deps/oblib/src/lib/timezone/ob_time_convert.h +++ b/deps/oblib/src/lib/timezone/ob_time_convert.h @@ -157,7 +157,7 @@ extern const int64_t USECS_PER_MIN; #define MYSQL_TIMESTAMP_MIN_VAL -62167046400000000 #define ORACLE_DATETIME_MIN_VAL -62135596800000000 //start from '0001-1-1 00:00:00' #define TIME_MAX_HOUR 838 -#define TIME_MAX_VAL (3020399 * 1000000LL) // 838:59:59 . +#define TIME_MAX_VAL (3020399 * 1000000LL) // 838:59:59. struct ObIntervalLimit { static const ObOracleTimeLimiter YEAR; @@ -408,8 +408,7 @@ public: static int str_is_date_format(const ObString &str, bool &date_flag); static int str_to_date(const ObString &str, int32_t &value, const ObDateSqlMode date_sql_mode = 0); - static int str_to_time(const ObString &str, int64_t &value, int16_t *scale = NULL, - const ObScale &time_scale = 0, const bool &need_truncate = false); + static int str_to_time(const ObString &str, int64_t &value, int16_t *scale = NULL, const bool &need_truncate = false); static int str_to_year(const ObString &str, uint8_t &value); static int str_to_interval(const ObString &str, ObDateUnitType unit_type, int64_t &value); // int / double / string <- datetime(timestamp) / date / time / year. diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index d94381e25b..0b132e1328 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -5212,7 +5212,7 @@ static int string_time(const ObObjType expect_type, ObObjCastParams ¶ms, ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); - } else if (CAST_FAIL(ObTimeConverter::str_to_time(in.get_string(), value, &res_scale, 0, need_truncate))) { + } else if (CAST_FAIL(ObTimeConverter::str_to_time(in.get_string(), value, &res_scale, need_truncate))) { } else { SET_RES_TIME(out); } @@ -12182,7 +12182,7 @@ int ob_obj_to_ob_time_without_date(const ObObj &obj, const ObTimeZoneInfo *tz_in LOG_WARN("int to ob time without date failed", K(ret)); } else { //mysql中intTC转time时,如果hour超过838,那么time应该为null,而不是最大值。 - const int64_t time_max_val = 3020399 * 1000000LL; // 838:59:59 . + const int64_t time_max_val = TIME_MAX_VAL; // 838:59:59 . int64_t value = ObTimeConverter::ob_time_to_time(ob_time); if (value > time_max_val) { ret = OB_INVALID_DATE_VALUE; @@ -12218,6 +12218,14 @@ int ob_obj_to_ob_time_without_date(const ObObj &obj, const ObTimeZoneInfo *tz_in } case ObStringTC: { ret = ObTimeConverter::str_to_ob_time_without_date(obj.get_string(), ob_time); + if (OB_SUCC(ret)) { + int64_t value = ObTimeConverter::ob_time_to_time(ob_time); + int64_t tmp_value = value; + ObTimeConverter::time_overflow_trunc(value); + if (value != tmp_value) { + ObTimeConverter::time_to_ob_time(value, ob_time); + } + } break; } case ObLobTC: { @@ -12230,13 +12238,25 @@ int ob_obj_to_ob_time_without_date(const ObObj &obj, const ObTimeZoneInfo *tz_in break; } case ObNumberTC: { - const char *num_format = obj.get_number().format(); - if (OB_ISNULL(num_format)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("number format value is null", K(ret)); + int64_t int_part = 0; + int64_t dec_part = 0; + const number::ObNumber num(obj.get_number()); + if (!num.is_int_parts_valid_int64(int_part, dec_part)) { + ret = OB_INVALID_DATE_FORMAT; + LOG_WARN("invalid date format", K(ret), K(num)); } else { - ObString num_str(num_format); - ret = ObTimeConverter::str_to_ob_time_without_date(num_str, ob_time); + if (OB_FAIL(ObTimeConverter::int_to_ob_time_without_date(int_part, ob_time, dec_part))) { + LOG_WARN("int to ob time without date failed", K(ret)); + } else { + if ((!ob_time.parts_[DT_YEAR]) && (!ob_time.parts_[DT_MON]) && (!ob_time.parts_[DT_MDAY])) { + //mysql中intTC转time时,如果超过838:59:59,那么time应该为null,而不是最大值。 + const int64_t time_max_val = TIME_MAX_VAL; // 838:59:59 . + int64_t value = ObTimeConverter::ob_time_to_time(ob_time); + if(value > time_max_val) { + ret = OB_INVALID_DATE_VALUE; + } + } + } } break; } diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index db9c2f7615..61a2710190 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -1051,11 +1051,10 @@ static OB_INLINE int common_string_time(const ObExpr &expr, int warning = OB_SUCCESS; int64_t out_val = 0; ObScale res_scale; // useless - ObScale time_scale = expr.datum_meta_.scale_; // support sqlmode TIME_TRUNCATE_FRACTIONAL const ObCastMode cast_mode = expr.extra_; bool need_truncate = CM_IS_COLUMN_CONVERT(cast_mode) ? CM_IS_TIME_TRUNCATE_FRACTIONAL(cast_mode) : false; - if (CAST_FAIL(ObTimeConverter::str_to_time(in_str, out_val, &res_scale, time_scale, need_truncate))) { + if (CAST_FAIL(ObTimeConverter::str_to_time(in_str, out_val, &res_scale, need_truncate))) { LOG_WARN("str_to_time failed", K(ret), K(in_str)); } else { SET_RES_TIME(out_val); @@ -11594,7 +11593,7 @@ int ob_datum_to_ob_time_without_date(const ObDatum &datum, const ObObjType type, LOG_WARN("int to ob time without date failed", K(ret)); } else { //mysql中intTC转time时,如果hour超过838,那么time应该为null,而不是最大值。 - const int64_t time_max_val = TIME_MAX_VAL; // 838:59:59 . + const int64_t time_max_val = TIME_MAX_VAL; // 838:59:59. int64_t value = ObTimeConverter::ob_time_to_time(ob_time); if (value > time_max_val) { ret = OB_INVALID_DATE_VALUE; @@ -11656,8 +11655,8 @@ int ob_datum_to_ob_time_without_date(const ObDatum &datum, const ObObjType type, LOG_WARN("int to ob time without date failed", K(ret)); } else { if ((!ob_time.parts_[DT_YEAR]) && (!ob_time.parts_[DT_MON]) && (!ob_time.parts_[DT_MDAY])) { - //mysql中intTC转time时,如果超过838:59:59.999999,那么time应该为null,而不是最大值。 - const int64_t time_max_val = TIME_MAX_VAL + 999999; // 838:59:59.999999 . + //mysql中intTC转time时,如果超过838:59:59,那么time应该为null,而不是最大值。 + const int64_t time_max_val = TIME_MAX_VAL; // 838:59:59. int64_t value = ObTimeConverter::ob_time_to_time(ob_time); if(value > time_max_val) { ret = OB_INVALID_DATE_VALUE; diff --git a/unittest/sql/optimizer/ob_mock_stat_manager.h b/unittest/sql/optimizer/ob_mock_stat_manager.h index f15288e180..007518e8ba 100644 --- a/unittest/sql/optimizer/ob_mock_stat_manager.h +++ b/unittest/sql/optimizer/ob_mock_stat_manager.h @@ -129,7 +129,7 @@ class MockStatManager : public oceanbase::common::ObStatManager { static const uint64_t DEFAULT_TABLE1_ID = 1099511677777; static const uint64_t DEFAULT_TABLE2_ID = 1099511677778; - static const int64_t TIME_MAX_VALUE = (3020399 * 1000000LL); + static const int64_t TIME_MAX_VALUE = TIME_MAX_VAL; static const int64_t DATE_MAX_VALUE = 2932896; static const int64_t DATE_MIN_VALUE = -354258; public: