summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2020-07-28 17:32:19 +0400
committerAlexander Barkov <bar@mariadb.com>2020-07-28 23:29:08 +0400
commit5b3b53ce36b9a05832af3a19ae8d846b6669a1f5 (patch)
treeaf8b06547a4466125138314a61db6e69ee743d78 /sql/item_func.cc
parent69cf6302f30e9bca7d2b0903c29fc1b26b09bcc7 (diff)
downloadmariadb-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.cc51
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));