1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-14032 SEC_TO_TIME executes side effect two times

- Adding a helper class Sec6 to store (neg,seconds,microseconds)
- Adding a helper class VSec6 (Sec6  with a flag for "IS NULL")
- Wrapping related functions as methods of Sec6;
  * number_to_datetime()
  * number_to_time()
  * my_decimal2seconds()
  * Item::get_seconds()
  * A big piece of code in Item_func_sec_to_time::get_date()

- Using the new classes in places where second-to-temporal
  conversion takes place:
  * Field_timestamp::store(double)
  * Field_timestamp::store(longlong)
  * Field_timestamp_with_dec::store_decimal(my_decimal)
  * Field_temporal_with_date::store(double)
  * Field_temporal_with_date::store(longlong)
  * Field_time::store(double)
  * Field_time::store(longlong)
  * Field_time::store_decimal(my_decimal)
  * Field_temporal_with_date::store_decimal(my_decimal)
  * get_interval_value()
  * Item_func_sec_to_time::get_date()
  * Item_func_from_unixtime::get_date()
  * Item_func_maketime::get_date()
  This change simplifies these methods and functions a lot.

- Warnings are now sent at VSec6 initialization time, when the source
  data is available in its original data type representation.

  If Sec6::to_time() or Sec6::to_datetime() truncate data again during
  conversion to MYSQL_TIME, they send warnings, but only if no warnings
  were sent during VSec6 initialization. This helps prevents double warnings.

  The call for val_str() in Item_func_sec_to_time::get_date() is not
  needed any more, so it's removed. This change actually fixes the problem.

  As a good effect, FROM_UNIXTIME() and MAKETIME() now also send warnings
  in case if the seconds arguments is out of range. Previously these
  functions returned NULL silently.

- Splitting the code in the global function make_truncated_value_warning()
  into a number of methods THD::raise_warning_xxxx().
  This was needed to reuse the logic that chooses between:
  * ER_TRUNCATED_WRONG_VALUE
  * ER_WRONG_VALUE
  * ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
  for non-temporal data types (Sec6).

- Removing:
  * Item::get_seconds()
  * number_to_time_with_warn()
  as this code now resides inside methods of Sec6.

- Cleanup (changes that are not directly related to the fix):
  * Removing calls for field_name_or_null() and passing NULL instead
    in Item_func_hybrid_field_type::get_date_from_{int|real}_op,
    because Item_func_hybrid_field_type::field_name_or_null()
    always returns NULL
  * Replacing a number of calls for make_truncated_value_warning()
    to calls for THD::raise_warning_xxx(). In these places
    we know that the execution went through a certain
    branch of make_truncated_value_warning(),
    (e.g. the exact error code is known, or field name is always NULL,
     or field name is always not-NULL). So calls for the entire
    make_truncated_value_warning() after splitting are not necessary.
This commit is contained in:
Alexander Barkov
2018-08-09 06:31:05 +04:00
parent a12e6c5ba4
commit 8524bb6872
15 changed files with 475 additions and 292 deletions

View File

@ -120,14 +120,6 @@ void make_truncated_value_warning(THD *thd,
timestamp_type time_type,
const char *field_name);
static inline void make_truncated_value_warning(THD *thd,
Sql_condition::enum_warning_level level, const char *str_val, size_t str_length, timestamp_type time_type,
const char *field_name)
{
const ErrConvString str(str_val, str_length, &my_charset_bin);
make_truncated_value_warning(thd, level, &str, time_type, field_name);
}
extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type,
const char *format_str,
uint format_length);