提交 676c105d 编写于 作者: O obdev 提交者: ob-robot

Fix bug about second and microsecond function and update cases

上级 4d38a86d
......@@ -140,7 +140,6 @@ static const int32_t DAYS_PER_YEAR[2]=
#define EPOCH_WDAY 4 // 1970-1-1 is thursday.
#define LEAP_YEAR_COUNT(y) ((y) / 4 - (y) / 100 + (y) / 400)
#define IS_LEAP_YEAR(y) ((((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) ? 1 : 0)
#define TIME_MAX_VAL (3020399 * 1000000LL) // 838:59:59 .
#define YEAR_MAX_YEAR 2155
#define YEAR_MIN_YEAR 1901
#define YEAR_BASE_YEAR 1900
......@@ -793,7 +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)
int ObTimeConverter::str_to_time(const ObString &str, int64_t &value, int16_t *scale, const ObScale &time_scale)
{
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_overflow_trunc(value, time_scale);
if (DT_MODE_NEG & ob_time.mode_) {
value = -value;
}
}
} else {
value = ob_time_to_time(ob_time);
ret = time_overflow_trunc(value);
ret = time_overflow_trunc(value, time_scale);
if (DT_MODE_NEG & ob_time.mode_) {
value = -value;
}
......@@ -1710,39 +1709,45 @@ int ObTimeConverter::int_to_ob_time_with_date(int64_t int64, ObTime &ob_time, bo
return ret;
}
int ObTimeConverter::int_to_ob_time_without_date(int64_t int64, ObTime &ob_time)
int ObTimeConverter::int_to_ob_time_without_date(int64_t time_second, ObTime &ob_time, int64_t nano_second)
{
int ret = OB_SUCCESS;
int32_t *parts = ob_time.parts_;
ObDTMode mode = DT_TYPE_TIME;
if (int64 < 0) {
if (time_second < 0) {
ob_time.mode_ |= DT_MODE_NEG;
if (INT64_MIN == int64) {
int64 = INT64_MAX;
if (INT64_MIN == time_second) {
time_second = INT64_MAX;
} else {
int64 = -int64;
time_second = -time_second;
}
}
if (int64 / power_of_10[4] < power_of_10[6]) {
if (time_second / power_of_10[4] < power_of_10[6]) {
// [H]HHMMSS, like 123:45:56.
parts[DT_SEC] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_MIN] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_HOUR] = static_cast<int32_t>(int64 % power_of_10[6]);
if(nano_second) {
parts[DT_USEC] = static_cast<int32_t>((nano_second + 500) / power_of_10[3]);
}
parts[DT_SEC] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_MIN] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_HOUR] = static_cast<int32_t>(time_second % power_of_10[6]);
if (OB_FAIL(validate_time(ob_time))) {
LOG_WARN("time integer is invalid", K(ret), K(int64));
LOG_WARN("time integer is invalid", K(ret), K(time_second));
}
} else if (int64 / power_of_10[6] < power_of_10[8]) {
} else if (time_second / power_of_10[6] < power_of_10[8]) {
// HHHHMMDDHHMMSS.
mode = DT_TYPE_DATETIME;
parts[DT_SEC] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_MIN] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_HOUR] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_MDAY] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_MON] = static_cast<int32_t>(int64 % power_of_10[2]); int64 /= power_of_10[2];
parts[DT_YEAR] = static_cast<int32_t>(int64 % power_of_10[4]);
if(nano_second) {
parts[DT_USEC] = static_cast<int32_t>((nano_second + 500) / power_of_10[3]);
}
parts[DT_SEC] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_MIN] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_HOUR] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_MDAY] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_MON] = static_cast<int32_t>(time_second % power_of_10[2]); time_second /= power_of_10[2];
parts[DT_YEAR] = static_cast<int32_t>(time_second % power_of_10[4]);
apply_date_year2_rule(parts[DT_YEAR]);
if (OB_FAIL(validate_datetime(ob_time, false, 0))) {
LOG_WARN("datetime is invalid or out of range", K(ret), K(int64));
LOG_WARN("datetime is invalid or out of range", K(ret), K(time_second), K(nano_second));
} else if (ZERO_DATE != parts[DT_DATE]) {
parts[DT_DATE] = ob_time_to_date(ob_time);
}
......@@ -5362,10 +5367,11 @@ int ObTimeConverter::set_ob_time_year_may_conflict(ObTime &ob_time, int32_t &jul
return ret;
}
int ObTimeConverter::time_overflow_trunc(int64_t &value)
int ObTimeConverter::time_overflow_trunc(int64_t &value, const ObScale &time_scale)
{
int ret = OB_SUCCESS;
if (value > TIME_MAX_VAL) {
int64_t increment = (6 == time_scale) ? 999999 : 0;
if (value > (TIME_MAX_VAL + increment)) {
// 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
......@@ -5373,7 +5379,7 @@ int ObTimeConverter::time_overflow_trunc(int64_t &value)
// 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;
value = TIME_MAX_VAL + increment;
}
return ret;
}
......
......@@ -157,6 +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 .
struct ObIntervalLimit {
static const ObOracleTimeLimiter YEAR;
......@@ -405,7 +406,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);
static int str_to_time(const ObString &str, int64_t &value, int16_t *scale = NULL, const ObScale &time_scale = 0);
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.
......@@ -475,7 +476,7 @@ public:
// int / string -> ObTime / ObInterval <- datetime(timestamp) / date / time / year.
static int int_to_ob_time_with_date(int64_t int64, ObTime &ob_time, bool is_dayofmonth,
const ObDateSqlMode date_sql_mode);
static int int_to_ob_time_without_date(int64_t int64, ObTime &ob_time);
static int int_to_ob_time_without_date(int64_t time_second, ObTime &ob_time, int64_t nano_second = 0);
static int str_to_ob_time_with_date(const ObString &str, ObTime &ob_time, int16_t *scale,
const bool is_dayofmonth, const ObDateSqlMode date_sql_mode);
static int str_to_ob_time_without_date(const ObString &str, ObTime &ob_time, int16_t *scale = NULL);
......@@ -569,7 +570,7 @@ public:
static int set_ob_time_part_directly(ObTime &ob_time, int64_t &conflict_bitset, const int64_t part_offset, const int32_t part_value);
static int set_ob_time_part_may_conflict(ObTime &ob_time, int64_t &conflict_bitset, const int64_t part_offset, const int32_t part_value);
static int32_t calc_max_name_length(const ObTimeConstStr names[], const int64_t size);
static int time_overflow_trunc(int64_t &value);
static int time_overflow_trunc(int64_t &value, const ObScale &time_scale = 0);
static void round_datetime(int16_t scale, int64_t &value);
static ObOTimestampData round_otimestamp(const int16_t scale, const ObOTimestampData &in_ot_data);
static int round_interval_ds(const ObScale scale, ObIntervalDSValue &value);
......
......@@ -32,7 +32,6 @@ namespace oceanbase
namespace sql
{
using namespace oceanbase::common;
//// common function and macro
#define CAST_FUNC_NAME(intype, outtype) \
int intype##_##outtype(const sql::ObExpr &expr, \
......@@ -959,7 +958,8 @@ static OB_INLINE int common_string_time(const ObExpr &expr,
int warning = OB_SUCCESS;
int64_t out_val = 0;
ObScale res_scale; // useless
if (CAST_FAIL(ObTimeConverter::str_to_time(in_str, out_val, &res_scale))) {
ObScale time_scale = expr.datum_meta_.scale_;
if (CAST_FAIL(ObTimeConverter::str_to_time(in_str, out_val, &res_scale, time_scale))) {
LOG_WARN("str_to_time failed", K(ret), K(in_str));
} else {
SET_RES_TIME(out_val);
......@@ -9234,7 +9234,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 = 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;
......@@ -9279,21 +9279,23 @@ int ob_datum_to_ob_time_without_date(const ObDatum &datum, const ObObjType type,
break;
}
case ObNumberTC: {
number::ObNumber num(datum.get_number());
const char *num_format = num.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(datum.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);
if (OB_FAIL(ObTimeConverter::str_to_ob_time_without_date(num_str, ob_time))) {
LOG_WARN("str to obtime without date failed", K(ret));
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 {
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);
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 .
int64_t value = ObTimeConverter::ob_time_to_time(ob_time);
if(value > time_max_val) {
ret = OB_INVALID_DATE_VALUE;
}
}
}
}
......
......@@ -116,8 +116,10 @@ inline int ObExprSecond::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) || (common::ObFloatTC == tc1) || (common::ObDoubleTC == tc1)) {
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;
}
......@@ -144,8 +146,10 @@ inline int ObExprMicrosecond::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) || (common::ObFloatTC == tc1) || (common::ObDoubleTC == tc1)) {
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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册