From 50003a9508f53cbaf6ad46ad071ff48f830ad389 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 22 Sep 2018 18:33:07 +0400 Subject: [PATCH] MDEV-17274 Split Field_temporal_with_date::store*() for Field_date_common and Field_datetime --- sql/field.cc | 118 ++++++++++++++++++++++++++++++++++----------------- sql/field.h | 48 ++++++++++++++------- 2 files changed, 112 insertions(+), 54 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 7f3498079ac..878c23862a8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5536,38 +5536,24 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level, 3 Datetime value that was cut (warning level NOTE) This is used by opt_range.cc:get_mm_leaf(). */ -int Field_temporal_with_date::store_TIME_with_warning(const Datetime *dt, - const ErrConv *str, - int was_cut) +int Field_datetime::store_TIME_with_warning(const Datetime *dt, + const ErrConv *str, + int was_cut) { - Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN; - timestamp_type ts_type= type_handler()->mysql_timestamp_type(); - ASSERT_COLUMN_MARKED_FOR_WRITE; // Handle totally bad values if (!dt->is_valid_datetime()) - { - static const Datetime zero; - store_TIME(zero.get_mysql_time()); - if (was_cut == 0) // special case: zero date - { - set_warnings(trunc_level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, ts_type); - return 2; - } - set_warnings(trunc_level, str, MYSQL_TIME_WARN_TRUNCATED, ts_type); - return 1; - } + return store_invalid_with_warning(str, was_cut, MYSQL_TIMESTAMP_DATETIME); // Store the value DBUG_ASSERT(!dt->fraction_remainder(decimals())); - if (ts_type == MYSQL_TIMESTAMP_DATE && !dt->hhmmssff_is_zero()) - was_cut|= MYSQL_TIME_NOTE_TRUNCATED; store_TIME(dt->get_mysql_time()); // Caclulate return value and send warnings if needed - return store_TIME_return_code_with_warnings(was_cut, str, ts_type); + return store_TIME_return_code_with_warnings(was_cut, str, + MYSQL_TIMESTAMP_DATETIME); } -int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *cs) +int Field_datetime::store(const char *from, size_t len, CHARSET_INFO *cs) { MYSQL_TIME_STATUS st; ErrConvString str(from, len, cs); @@ -5575,7 +5561,7 @@ int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO * return store_TIME_with_warning(&dt, &str, st.warnings); } -int Field_temporal_with_date::store(double nr) +int Field_datetime::store(double nr) { int error; ErrConvDouble str(nr); @@ -5584,7 +5570,7 @@ int Field_temporal_with_date::store(double nr) } -int Field_temporal_with_date::store(longlong nr, bool unsigned_val) +int Field_datetime::store(longlong nr, bool unsigned_val) { int error; ErrConvInteger str(nr, unsigned_val); @@ -5592,7 +5578,7 @@ int Field_temporal_with_date::store(longlong nr, bool unsigned_val) return store_TIME_with_warning(&dt, &str, error); } -int Field_temporal_with_date::store_time_dec(const MYSQL_TIME *ltime, uint dec) +int Field_datetime::store_time_dec(const MYSQL_TIME *ltime, uint dec) { int error; ErrConvTime str(ltime); @@ -5602,6 +5588,14 @@ int Field_temporal_with_date::store_time_dec(const MYSQL_TIME *ltime, uint dec) } +int Field_datetime::store_decimal(const my_decimal *d) +{ + int error; + ErrConvDecimal str(d); + Datetime tm(&error, d, sql_mode_for_dates(get_thd()), decimals()); + return store_TIME_with_warning(&tm, &str, error); +} + bool Field_temporal_with_date::validate_value_in_record(THD *thd, const uchar *record) const @@ -5690,12 +5684,7 @@ int Field_time::store_TIME_with_warning(const Time *t, ASSERT_COLUMN_MARKED_FOR_WRITE; // Handle totally bad values if (!t->is_valid_time()) - { - static const Datetime zero; - store_TIME(zero.get_mysql_time()); - set_warnings(Sql_condition::WARN_LEVEL_WARN, str, MYSQL_TIME_WARN_TRUNCATED); - return 1; - } + return store_invalid_with_warning(str, warn, MYSQL_TIMESTAMP_TIME); // Store the value DBUG_ASSERT(!t->fraction_remainder(decimals())); store_TIME(t->get_mysql_time()); @@ -6236,6 +6225,67 @@ void Field_year::sql_type(String &res) const } +/*****************************************************************************/ + +int Field_date_common::store_TIME_with_warning(const Datetime *dt, + const ErrConv *str, + int was_cut) +{ + ASSERT_COLUMN_MARKED_FOR_WRITE; + // Handle totally bad values + if (!dt->is_valid_datetime()) + return store_invalid_with_warning(str, was_cut, MYSQL_TIMESTAMP_DATE); + // Store the value + if (!dt->hhmmssff_is_zero()) + was_cut|= MYSQL_TIME_NOTE_TRUNCATED; + store_TIME(dt->get_mysql_time()); + // Caclulate return value and send warnings if needed + return store_TIME_return_code_with_warnings(was_cut, str, + MYSQL_TIMESTAMP_DATE); +} + +int Field_date_common::store(const char *from, size_t len, CHARSET_INFO *cs) +{ + MYSQL_TIME_STATUS st; + ErrConvString str(from, len, cs); + Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd())); + return store_TIME_with_warning(&dt, &str, st.warnings); +} + +int Field_date_common::store(double nr) +{ + int error; + ErrConvDouble str(nr); + Datetime dt(&error, nr, sql_mode_for_dates(get_thd())); + return store_TIME_with_warning(&dt, &str, error); +} + +int Field_date_common::store(longlong nr, bool unsigned_val) +{ + int error; + ErrConvInteger str(nr, unsigned_val); + Datetime dt(&error, nr, unsigned_val, sql_mode_for_dates(get_thd())); + return store_TIME_with_warning(&dt, &str, error); +} + +int Field_date_common::store_time_dec(const MYSQL_TIME *ltime, uint dec) +{ + int error; + ErrConvTime str(ltime); + THD *thd= get_thd(); + Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd)); + return store_TIME_with_warning(&dt, &str, error); +} + +int Field_date_common::store_decimal(const my_decimal *d) +{ + int error; + ErrConvDecimal str(d); + Datetime tm(&error, d, sql_mode_for_dates(get_thd())); + return store_TIME_with_warning(&tm, &str, error); +} + + /**************************************************************************** ** date type ** In string context: YYYY-MM-DD @@ -6638,14 +6688,6 @@ void Field_datetime_hires::store_TIME(const MYSQL_TIME *ltime) store_bigendian(packed, ptr, Field_datetime_hires::pack_length()); } -int Field_temporal_with_date::store_decimal(const my_decimal *d) -{ - int error; - ErrConvDecimal str(d); - Datetime tm(&error, d, sql_mode_for_dates(get_thd()), decimals()); - return store_TIME_with_warning(&tm, &str, error); -} - bool Field_datetime_with_dec::send_binary(Protocol *protocol) { MYSQL_TIME ltime; diff --git a/sql/field.h b/sql/field.h index ed61afe01eb..b753111f331 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2594,6 +2594,8 @@ class Field_temporal: public Field { protected: Item *get_equal_const_item_datetime(THD *thd, const Context &ctx, Item *const_item); + void set_warnings(Sql_condition::enum_warning_level trunc_level, + const ErrConv *str, int was_cut, timestamp_type ts_type); int store_TIME_return_code_with_warnings(int warn, const ErrConv *str, timestamp_type ts_type) { @@ -2607,7 +2609,20 @@ protected: set_warnings(Sql_condition::WARN_LEVEL_WARN, str, warn, ts_type); return warn ? 2 : 0; } - + int store_invalid_with_warning(const ErrConv *str, int was_cut, + timestamp_type ts_type) + { + reset(); + Sql_condition::enum_warning_level level= Sql_condition::WARN_LEVEL_WARN; + if (was_cut == 0) // special case: zero date + { + DBUG_ASSERT(ts_type != MYSQL_TIMESTAMP_TIME); + set_warnings(level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, ts_type); + return 2; + } + set_warnings(level, str, MYSQL_TIME_WARN_TRUNCATED, ts_type); + return 1; + } public: Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -2642,8 +2657,6 @@ public: return (Field::eq_def(field) && decimals() == field->decimals()); } my_decimal *val_decimal(my_decimal*); - void set_warnings(Sql_condition::enum_warning_level trunc_level, - const ErrConv *str, int was_cut, timestamp_type ts_type); double pos_in_interval(Field *min, Field *max) { return pos_in_interval_val_real(min, max); @@ -2673,9 +2686,6 @@ public: */ class Field_temporal_with_date: public Field_temporal { protected: - int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, - int was_cut); - void store_TIME_with_trunc(const Time *); virtual void store_TIME(const MYSQL_TIME *ltime) = 0; virtual bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const = 0; @@ -2696,11 +2706,6 @@ public: :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} - int store(const char *to, size_t length, CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr, bool unsigned_val); - int store_time_dec(const MYSQL_TIME *ltime, uint dec); - int store_decimal(const my_decimal *); bool validate_value_in_record(THD *thd, const uchar *record) const; }; @@ -2951,6 +2956,9 @@ public: class Field_date_common: public Field_temporal_with_date { +protected: + int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, + int was_cut); public: Field_date_common(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, @@ -2962,6 +2970,11 @@ public: SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value); + int store(const char *to, size_t length, CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr, bool unsigned_val); + int store_time_dec(const MYSQL_TIME *ltime, uint dec); + int store_decimal(const my_decimal *); }; @@ -3039,11 +3052,6 @@ class Field_time :public Field_temporal { protected: virtual void store_TIME(const MYSQL_TIME *ltime); int store_TIME_with_warning(const Time *ltime, const ErrConv *str, int warn); - void set_warnings(Sql_condition::enum_warning_level level, - const ErrConv *str, int was_cut) - { - Field_temporal::set_warnings(level, str, was_cut, MYSQL_TIMESTAMP_TIME); - } bool check_zero_in_date_with_warn(ulonglong fuzzydate); static void do_field_time(Copy_field *copy); public: @@ -3198,6 +3206,9 @@ public: class Field_datetime :public Field_temporal_with_date { void store_TIME(const MYSQL_TIME *ltime); bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; +protected: + int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, + int was_cut); public: Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, @@ -3211,6 +3222,11 @@ public: } const Type_handler *type_handler() const { return &type_handler_datetime; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } + int store(const char *to, size_t length, CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr, bool unsigned_val); + int store_time_dec(const MYSQL_TIME *ltime, uint dec); + int store_decimal(const my_decimal *); double val_real(void); longlong val_int(void); String *val_str(String*,String *);