diff options
author | Alexander Barkov <bar@mariadb.com> | 2020-07-28 17:32:19 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2020-07-28 23:29:08 +0400 |
commit | 5b3b53ce36b9a05832af3a19ae8d846b6669a1f5 (patch) | |
tree | af8b06547a4466125138314a61db6e69ee743d78 /sql/item_func.cc | |
parent | 69cf6302f30e9bca7d2b0903c29fc1b26b09bcc7 (diff) | |
download | mariadb-git-5b3b53ce36b9a05832af3a19ae8d846b6669a1f5.tar.gz |
MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
Fixing functions CEILING and FLOOR to return
- TIME for TIME input
- DATETIME for DATETIME and TIMESTAMP input
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r-- | sql/item_func.cc | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 45a7b155481..424437ead07 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2218,8 +2218,7 @@ bool Item_func_int_val::fix_length_and_dec() { DBUG_ENTER("Item_func_int_val::fix_length_and_dec"); DBUG_PRINT("info", ("name %s", func_name())); - if (args[0]->cast_to_int_type_handler()-> - Item_func_int_val_fix_length_and_dec(this)) + if (args[0]->type_handler()->Item_func_int_val_fix_length_and_dec(this)) DBUG_RETURN(TRUE); DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr())); DBUG_RETURN(FALSE); @@ -2262,6 +2261,28 @@ my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value) } +bool Item_func_ceiling::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) +{ + Datetime::Options opt(thd, TIME_FRAC_TRUNCATE); + Datetime *tm= new (to) Datetime(thd, args[0], opt); + tm->ceiling(thd); + null_value= !tm->is_valid_datetime(); + DBUG_ASSERT(maybe_null || !null_value); + return null_value; +} + + +bool Item_func_ceiling::time_op(THD *thd, MYSQL_TIME *to) +{ + static const Time::Options_for_round opt; + Time *tm= new (to) Time(thd, args[0], opt); + tm->ceiling(); + null_value= !tm->is_valid_time(); + DBUG_ASSERT(maybe_null || !null_value); + return null_value; +} + + longlong Item_func_floor::int_op() { switch (args[0]->result_type()) { @@ -2302,6 +2323,28 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) } +bool Item_func_floor::date_op(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) +{ + // DATETIME is not negative, so FLOOR means just truncation + Datetime::Options opt(thd, TIME_FRAC_TRUNCATE); + Datetime *tm= new (to) Datetime(thd, args[0], opt, 0); + null_value= !tm->is_valid_datetime(); + DBUG_ASSERT(maybe_null || !null_value); + return null_value; +} + + +bool Item_func_floor::time_op(THD *thd, MYSQL_TIME *to) +{ + static const Time::Options_for_round opt; + Time *tm= new (to) Time(thd, args[0], opt); + tm->floor(); + null_value= !tm->is_valid_time(); + DBUG_ASSERT(maybe_null || !null_value); + return null_value; +} + + void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set) { int decimals_delta= args[0]->decimals - decimals_to_set; @@ -2540,9 +2583,7 @@ bool Item_func_round::time_op(THD *thd, MYSQL_TIME *to) { DBUG_ASSERT(args[0]->type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_TIME); - Time::Options opt(Time::default_flags_for_get_date(), - truncate ? TIME_FRAC_TRUNCATE : TIME_FRAC_ROUND, - Time::DATETIME_TO_TIME_DISALLOW); + Time::Options_for_round opt(truncate ? TIME_FRAC_TRUNCATE : TIME_FRAC_ROUND); Longlong_hybrid_null dec= args[1]->to_longlong_hybrid_null(); Time *tm= new (to) Time(thd, args[0], opt, dec.to_uint(TIME_SECOND_PART_DIGITS)); |