MDEV-28001 greatest/least with bigint unsigned maxium has unexpected results compared to 0

LEAST() and GREATEST() erroneously calcucalted the result as signed
for BIGINT UNSIGNED arguments.

Adding a new method for unsigned arguments:
  Item_func_min_max::val_uint_native()
This commit is contained in:
Alexander Barkov 2024-11-11 12:50:56 +04:00
parent 74184074a0
commit ae0cbfe934
5 changed files with 40 additions and 1 deletions

View file

@ -4338,5 +4338,14 @@ SELECT * FROM t0 WHERE LEAST(c0, NULL);
c0
DROP TABLE t0;
#
# MDEV-28001 greatest/least with bigint unsigned maxium has unexpected results compared to 0
#
CREATE TABLE t1 (a BIGINT UNSIGNED, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (18446744073709551615,0);
SELECT a,b, LEAST(a,b), GREATEST(a,b) FROM t1;
a b LEAST(a,b) GREATEST(a,b)
18446744073709551615 0 0 18446744073709551615
DROP TABLE t1;
#
# End of 10.5 tests
#

View file

@ -1137,6 +1137,14 @@ SELECT * FROM t0 WHERE GREATEST(c0, NULL);
SELECT * FROM t0 WHERE LEAST(c0, NULL);
DROP TABLE t0;
--echo #
--echo # MDEV-28001 greatest/least with bigint unsigned maxium has unexpected results compared to 0
--echo #
CREATE TABLE t1 (a BIGINT UNSIGNED, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (18446744073709551615,0);
SELECT a,b, LEAST(a,b), GREATEST(a,b) FROM t1;
DROP TABLE t1;
--echo #
--echo # End of 10.5 tests

View file

@ -3051,6 +3051,27 @@ longlong Item_func_min_max::val_int_native()
}
longlong Item_func_min_max::val_uint_native()
{
DBUG_ASSERT(fixed);
ulonglong value= 0;
for (uint i=0; i < arg_count ; i++)
{
if (i == 0)
value= (ulonglong) args[i]->val_int();
else
{
ulonglong tmp= (ulonglong) args[i]->val_int();
if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
value= tmp;
}
if ((null_value= args[i]->null_value))
return 0;
}
return (longlong) value;
}
my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec)
{
DBUG_ASSERT(fixed == 1);

View file

@ -2118,6 +2118,7 @@ public:
String *val_str_native(String *str);
double val_real_native();
longlong val_int_native();
longlong val_uint_native();
my_decimal *val_decimal_native(my_decimal *);
bool get_date_native(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
bool get_time_native(THD *thd, MYSQL_TIME *res);

View file

@ -6152,7 +6152,7 @@ longlong Type_handler_timestamp_common::
longlong Type_handler_numeric::
Item_func_min_max_val_int(Item_func_min_max *func) const
{
return func->val_int_native();
return is_unsigned() ? func->val_uint_native() : func->val_int_native();
}