diff options
author | Alexander Barkov <bar@mariadb.com> | 2018-09-12 09:06:27 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2018-09-12 09:06:27 +0400 |
commit | 2fe51a6fdda7eb91ddac1e24bc3f972e57067fd2 (patch) | |
tree | 29a96e8d741fc9658cf6f6e50cddab423cec5a25 /sql | |
parent | 5567a8c936ede50efcdf4a7f898dbaa058106d70 (diff) | |
download | mariadb-git-2fe51a6fdda7eb91ddac1e24bc3f972e57067fd2.tar.gz |
MDEV-17175 Change Time/Datetime constructors to return warnings in MYSQL_TIME_STATUS
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 18 | ||||
-rw-r--r-- | sql/sql_time.cc | 49 | ||||
-rw-r--r-- | sql/sql_time.h | 9 | ||||
-rw-r--r-- | sql/sql_type.cc | 56 | ||||
-rw-r--r-- | sql/sql_type.h | 41 |
5 files changed, 99 insertions, 74 deletions
diff --git a/sql/field.cc b/sql/field.cc index 743f12f3cc9..d695be4feff 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5093,9 +5093,9 @@ int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs) { ErrConvString str(from, len, cs); THD *thd= get_thd(); - int error; - Datetime dt(&error, from, len, cs, sql_mode_for_timestamp(thd)); - return store_TIME_with_warning(thd, &dt, &str, error); + MYSQL_TIME_STATUS st; + Datetime dt(&st, from, len, cs, sql_mode_for_timestamp(thd)); + return store_TIME_with_warning(thd, &dt, &str, st.warnings); } @@ -5577,10 +5577,10 @@ int Field_temporal_with_date::store_TIME_with_warning(const Datetime *dt, int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *cs) { - int error; + MYSQL_TIME_STATUS st; ErrConvString str(from, len, cs); - Datetime dt(&error, from, len, cs, sql_mode_for_dates(get_thd())); - return store_TIME_with_warning(&dt, &str, error); + Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd())); + return store_TIME_with_warning(&dt, &str, st.warnings); } int Field_temporal_with_date::store(double nr) @@ -5731,9 +5731,9 @@ void Field_time::store_TIME(const MYSQL_TIME *ltime) int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs) { ErrConvString str(from, len, cs); - int error; - Time tm(&error, from, len, cs, sql_mode_for_dates(get_thd())); - return store_TIME_with_warning(&tm, &str, error); + MYSQL_TIME_STATUS st; + Time tm(&st, from, len, cs, sql_mode_for_dates(get_thd())); + return store_TIME_with_warning(&tm, &str, st.warnings); } diff --git a/sql/sql_time.cc b/sql/sql_time.cc index c1300c78ad9..7b1cb504f08 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -351,33 +351,43 @@ to_ascii(CHARSET_INFO *cs, } -/* Character set-aware version of str_to_time() */ -bool -str_to_time(CHARSET_INFO *cs, const char *str, size_t length, - MYSQL_TIME *l_time, ulonglong fuzzydate, MYSQL_TIME_STATUS *status) +class TemporalAsciiBuffer: public LEX_CSTRING { char cnv[32]; - if ((cs->state & MY_CS_NONASCII) != 0) +public: + TemporalAsciiBuffer(const char *str, size_t length, CHARSET_INFO *cs) { - length= to_ascii(cs, str, length, cnv, sizeof(cnv)); - str= cnv; + if ((cs->state & MY_CS_NONASCII) != 0) + { + LEX_CSTRING::str= cnv; + LEX_CSTRING::length= to_ascii(cs, str, length, cnv, sizeof(cnv)); + } + else + { + LEX_CSTRING::str= str; + LEX_CSTRING::length= length; + } } - return str_to_time(str, length, l_time, fuzzydate, status); +}; + + +/* Character set-aware version of str_to_time() */ +bool Temporal::str_to_time(MYSQL_TIME_STATUS *status, + const char *str, size_t length, CHARSET_INFO *cs, + sql_mode_t fuzzydate) +{ + TemporalAsciiBuffer tmp(str, length, cs); + return ::str_to_time(tmp.str, tmp.length, this, fuzzydate, status); } /* Character set-aware version of str_to_datetime() */ -bool str_to_datetime(CHARSET_INFO *cs, const char *str, size_t length, - MYSQL_TIME *l_time, ulonglong flags, - MYSQL_TIME_STATUS *status) +bool Temporal::str_to_datetime(MYSQL_TIME_STATUS *status, + const char *str, size_t length, CHARSET_INFO *cs, + sql_mode_t flags) { - char cnv[32]; - if ((cs->state & MY_CS_NONASCII) != 0) - { - length= to_ascii(cs, str, length, cnv, sizeof(cnv)); - str= cnv; - } - return str_to_datetime(str, length, l_time, flags, status); + TemporalAsciiBuffer tmp(str, length, cs); + return ::str_to_datetime(tmp.str, tmp.length, this, flags, status); } @@ -396,7 +406,8 @@ str_to_datetime_with_warn(CHARSET_INFO *cs, { MYSQL_TIME_STATUS status; THD *thd= current_thd; - bool ret_val= str_to_datetime(cs, str, length, l_time, flags, &status); + TemporalAsciiBuffer tmp(str, length, cs); + bool ret_val= str_to_datetime(tmp.str, tmp.length, l_time, flags, &status); if (ret_val || status.warnings) { const ErrConvString err(str, length, &my_charset_bin); diff --git a/sql/sql_time.h b/sql/sql_time.h index 8c6e58856e6..862289ffdf1 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -126,15 +126,6 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week); bool parse_date_time_format(timestamp_type format_type, const char *format, uint format_length, DATE_TIME_FORMAT *date_time_format); -/* Character set-aware version of str_to_time() */ -bool str_to_time(CHARSET_INFO *cs, const char *str,size_t length, - MYSQL_TIME *l_time, ulonglong fuzzydate, - MYSQL_TIME_STATUS *status); -/* Character set-aware version of str_to_datetime() */ -bool str_to_datetime(CHARSET_INFO *cs, - const char *str, size_t length, - MYSQL_TIME *l_time, ulonglong flags, - MYSQL_TIME_STATUS *status); /* convenience wrapper */ inline bool parse_date_time_format(timestamp_type format_type, diff --git a/sql/sql_type.cc b/sql/sql_type.cc index e7fcdf499ec..e3c854a227f 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -5489,17 +5489,19 @@ uint Type_handler::Item_datetime_precision(Item *item) const uint Type_handler_string_result::Item_temporal_precision(Item *item, bool is_time) const { - MYSQL_TIME ltime; StringBuffer<64> buf; String *tmp; MYSQL_TIME_STATUS status; DBUG_ASSERT(item->is_fixed()); if ((tmp= item->val_str(&buf)) && - !(is_time ? - str_to_time(tmp->charset(), tmp->ptr(), tmp->length(), - <ime, TIME_TIME_ONLY, &status) : - str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(), - <ime, TIME_FUZZY_DATES, &status))) + (is_time ? + Time(&status, tmp->ptr(), tmp->length(), tmp->charset(), + Time::Options(TIME_TIME_ONLY, + Time::DATETIME_TO_TIME_YYYYMMDD_TRUNCATE)). + is_valid_time() : + Datetime(&status, tmp->ptr(), tmp->length(), tmp->charset(), + TIME_FUZZY_DATES). + is_valid_datetime())) return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS); return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); } @@ -7208,7 +7210,7 @@ static bool have_important_literal_warnings(const MYSQL_TIME_STATUS *status) static void literal_warn(THD *thd, const Item *item, const char *str, size_t length, CHARSET_INFO *cs, - const MYSQL_TIME *ltime, + timestamp_type time_type, const MYSQL_TIME_STATUS *st, const char *typestr, bool send_error) { @@ -7219,7 +7221,7 @@ static void literal_warn(THD *thd, const Item *item, ErrConvString err(str, length, cs); make_truncated_value_warning(thd, Sql_condition::time_warn_level(st->warnings), - &err, ltime->time_type, 0); + &err, time_type, 0); } } else if (send_error) @@ -7238,13 +7240,14 @@ Type_handler_date_common::create_literal_item(THD *thd, bool send_error) const { MYSQL_TIME_STATUS st; - MYSQL_TIME ltime; Item_literal *item= NULL; - sql_mode_t flags= sql_mode_for_dates(thd); - if (!str_to_datetime(cs, str, length, <ime, flags, &st) && - ltime.time_type == MYSQL_TIMESTAMP_DATE && !st.warnings) - item= new (thd->mem_root) Item_date_literal(thd, <ime); - literal_warn(thd, item, str, length, cs, <ime, &st, "DATE", send_error); + Temporal_hybrid tmp(&st, str, length, cs, sql_mode_for_dates(thd)); + if (tmp.is_valid_temporal() && + tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATE && + !have_important_literal_warnings(&st)) + item= new (thd->mem_root) Item_date_literal(thd, tmp.get_mysql_time()); + literal_warn(thd, item, str, length, cs, MYSQL_TIMESTAMP_DATE, + &st, "DATE", send_error); return item; } @@ -7257,14 +7260,15 @@ Type_handler_temporal_with_date::create_literal_item(THD *thd, bool send_error) const { MYSQL_TIME_STATUS st; - MYSQL_TIME ltime; Item_literal *item= NULL; - sql_mode_t flags= sql_mode_for_dates(thd); - if (!str_to_datetime(cs, str, length, <ime, flags, &st) && - ltime.time_type == MYSQL_TIMESTAMP_DATETIME && + Temporal_hybrid tmp(&st, str, length, cs, sql_mode_for_dates(thd)); + if (tmp.is_valid_temporal() && + tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATETIME && !have_important_literal_warnings(&st)) - item= new (thd->mem_root) Item_datetime_literal(thd, <ime, st.precision); - literal_warn(thd, item, str, length, cs, <ime, &st, "DATETIME", send_error); + item= new (thd->mem_root) Item_datetime_literal(thd, tmp.get_mysql_time(), + st.precision); + literal_warn(thd, item, str, length, cs, MYSQL_TIMESTAMP_DATETIME, + &st, "DATETIME", send_error); return item; } @@ -7277,12 +7281,14 @@ Type_handler_time_common::create_literal_item(THD *thd, bool send_error) const { MYSQL_TIME_STATUS st; - MYSQL_TIME ltime; Item_literal *item= NULL; - if (!str_to_time(cs, str, length, <ime, 0, &st) && - ltime.time_type == MYSQL_TIMESTAMP_TIME && + Time::Options opt(TIME_TIME_ONLY, Time::DATETIME_TO_TIME_DISALLOW); + Time tmp(&st, str, length, cs, opt); + if (tmp.is_valid_time() && !have_important_literal_warnings(&st)) - item= new (thd->mem_root) Item_time_literal(thd, <ime, st.precision); - literal_warn(thd, item, str, length, cs, <ime, &st, "TIME", send_error); + item= new (thd->mem_root) Item_time_literal(thd, tmp.get_mysql_time(), + st.precision); + literal_warn(thd, item, str, length, cs, MYSQL_TIMESTAMP_TIME, + &st, "TIME", send_error); return item; } diff --git a/sql/sql_type.h b/sql/sql_type.h index 40433fdaabd..29a0db9ed53 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -446,12 +446,13 @@ public: class Temporal: protected MYSQL_TIME { -protected: +public: bool is_valid_temporal() const { DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); return time_type != MYSQL_TIMESTAMP_NONE; } +protected: my_decimal *bad_to_decimal(my_decimal *to) const; my_decimal *to_decimal(my_decimal *to) const; static double to_double(bool negate, ulonglong num, ulong frac) @@ -465,6 +466,10 @@ protected: *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; time_type= MYSQL_TIMESTAMP_NONE; } + bool str_to_time(MYSQL_TIME_STATUS *st, const char *str, size_t length, + CHARSET_INFO *cs, sql_mode_t fuzzydate); + bool str_to_datetime(MYSQL_TIME_STATUS *st, const char *str, size_t length, + CHARSET_INFO *cs, sql_mode_t fuzzydate); public: long fraction_remainder(uint dec) const { @@ -483,6 +488,12 @@ class Temporal_hybrid: public Temporal public: Temporal_hybrid(THD *thd, Item *item); Temporal_hybrid(Item *item) { *this= Temporal_hybrid(current_thd, item); } + Temporal_hybrid(MYSQL_TIME_STATUS *st, const char *str, size_t length, + CHARSET_INFO *cs, sql_mode_t fuzzydate) + { + if (str_to_datetime(st, str, length, cs, fuzzydate)) + time_type= MYSQL_TIMESTAMP_NONE; + } longlong to_longlong() const { if (!is_valid_temporal()) @@ -507,6 +518,11 @@ public: str->length(my_TIME_to_str(this, const_cast<char*>(str->ptr()), dec)); return str; } + const MYSQL_TIME *get_mysql_time() const + { + DBUG_ASSERT(is_valid_temporal()); + return this; + } }; @@ -533,6 +549,7 @@ class Time: public Temporal public: enum datetime_to_time_mode_t { + DATETIME_TO_TIME_DISALLOW, DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS, DATETIME_TO_TIME_YYYYMMDD_TRUNCATE, DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY, @@ -674,6 +691,8 @@ private: DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY && (year || month || day)) make_from_out_of_range(warn); + else if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_DISALLOW) + make_from_out_of_range(warn); else valid_datetime_to_valid_time(warn, opt); break; @@ -729,15 +748,13 @@ public: make_from_item(&warn, item, opt); } Time(int *warn, const MYSQL_TIME *from, long curdays); - Time(int *warn, const char *str, size_t len, CHARSET_INFO *cs, + Time(MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, const Options opt) { - MYSQL_TIME_STATUS status; - if (str_to_time(cs, str, len, this, opt.get_date_flags(), &status)) + if (str_to_time(status, str, len, cs, opt.get_date_flags())) time_type= MYSQL_TIMESTAMP_NONE; // The below call will optionally add notes to already collected warnings: - xxx_to_time_result_to_valid_value(&status.warnings, opt); - *warn= status.warnings; + xxx_to_time_result_to_valid_value(&status->warnings, opt); } Time(int *warn, const Sec6 &nr, const Options opt) { @@ -885,14 +902,13 @@ protected: if (nr.to_datetime(this, flags, warn)) time_type= MYSQL_TIMESTAMP_NONE; } - Temporal_with_date(int *warn, const char *str, size_t len, CHARSET_INFO *cs, + Temporal_with_date(MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, sql_mode_t flags) { DBUG_ASSERT((flags & TIME_TIME_ONLY) == 0); - MYSQL_TIME_STATUS status; - if (str_to_datetime(cs, str, len, this, flags, &status)) + if (str_to_datetime(status, str, len, cs, flags)) time_type= MYSQL_TIMESTAMP_NONE; - *warn= status.warnings; } public: bool check_date_with_warn(ulonglong flags) @@ -1051,9 +1067,10 @@ public: { set_zero_time(this, MYSQL_TIMESTAMP_DATETIME); } - Datetime(int *warn, const char *str, size_t len, CHARSET_INFO *cs, + Datetime(MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, sql_mode_t flags) - :Temporal_with_date(warn, str, len, cs, flags) + :Temporal_with_date(status, str, len, cs, flags) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); |