Commit d682dc2e authored by Alexander Barkov's avatar Alexander Barkov

MDEV-8919 Wrong result for CAST(9999999999999999999.0)

parent cacdcfd0
......@@ -730,3 +730,57 @@ SET sql_mode=DEFAULT;
--echo #
SELECT CAST(11068046444225730969 AS SIGNED);
--echo #
--echo # MDEV-8919 Wrong result for CAST(9999999999999999999.0)
--echo #
SET sql_mode='';
SELECT CAST(9999999999999999999e0 AS UNSIGNED);
CREATE TABLE t1 (a BIGINT UNSIGNED);
INSERT INTO t1 VALUES (9999999999999999999e0);
SELECT * FROM t1;
DROP TABLE t1;
SELECT CAST(9999999999999999999.0 AS UNSIGNED);
CREATE TABLE t1 (a BIGINT UNSIGNED);
INSERT INTO t1 VALUES (9999999999999999999.0);
SELECT * FROM t1;
DROP TABLE t1;
SELECT CAST(-1.0 AS UNSIGNED);
CREATE TABLE t1 (a BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-1.0);
SELECT * FROM t1;
DROP TABLE t1;
SELECT CAST(-1e0 AS UNSIGNED);
CREATE TABLE t1 (a BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-1e0);
SELECT * FROM t1;
DROP TABLE t1;
SELECT CAST(-1e308 AS UNSIGNED);
CREATE TABLE t1 (a BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-1e308);
SELECT * FROM t1;
DROP TABLE t1;
SELECT CAST(TIME'-00:00:01.123' AS UNSIGNED);
CREATE TABLE t1 (a BIGINT UNSIGNED);
INSERT INTO t1 VALUES (TIME'-00:00:01.123');
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE UNSIGNED);
INSERT INTO t1 VALUES (1.9e19);
SELECT CAST(a AS SIGNED), CAST(MIN(a) AS SIGNED) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(30,1) UNSIGNED);
INSERT INTO t1 VALUES (1e19);
SELECT a, CAST(a AS SIGNED) FROM t1;
DROP TABLE t1;
SET sql_mode=DEFAULT;
......@@ -265,6 +265,40 @@ longlong Item::val_int_unsigned_typecast_from_str()
}
longlong Item::val_int_signed_typecast_from_real()
{
double nr= val_real();
if (null_value)
return 0;
Converter_double_to_longlong conv(nr, false);
if (conv.error())
{
THD *thd= current_thd;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DATA_OVERFLOW, ER_THD(thd, ER_DATA_OVERFLOW),
ErrConvDouble(nr).ptr(), "SIGNED BIGINT");
}
return conv.result();
}
longlong Item::val_int_unsigned_typecast_from_real()
{
double nr= val_real();
if (null_value)
return 0;
Converter_double_to_longlong conv(nr, true);
if (conv.error())
{
THD *thd= current_thd;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DATA_OVERFLOW, ER_THD(thd, ER_DATA_OVERFLOW),
ErrConvDouble(nr).ptr(), "UNSIGNED BIGINT");
}
return conv.result();
}
longlong Item::val_int_signed_typecast_from_int()
{
longlong value= val_int();
......
......@@ -1247,12 +1247,14 @@ class Item: public Value_source,
}
longlong val_int_unsigned_typecast_from_int();
longlong val_int_unsigned_typecast_from_str();
longlong val_int_unsigned_typecast_from_real();
/**
Get a value for CAST(x AS UNSIGNED).
Huge positive unsigned values are converted to negative complements.
*/
longlong val_int_signed_typecast_from_int();
longlong val_int_signed_typecast_from_real();
/*
This is just a shortcut to avoid the cast. You should still use
......
......@@ -4490,7 +4490,7 @@ void Type_handler_temporal_result::Item_get_date(THD *thd, Item *item,
longlong Type_handler_real_result::
Item_val_int_signed_typecast(Item *item) const
{
return item->val_int_signed_typecast_from_int();
return item->val_int_signed_typecast_from_real();
}
longlong Type_handler_int_result::
......@@ -4502,7 +4502,7 @@ longlong Type_handler_int_result::
longlong Type_handler_decimal_result::
Item_val_int_signed_typecast(Item *item) const
{
return item->val_int();
return VDec(item).to_longlong(false);
}
longlong Type_handler_temporal_result::
......@@ -4522,7 +4522,7 @@ longlong Type_handler_string_result::
longlong Type_handler_real_result::
Item_val_int_unsigned_typecast(Item *item) const
{
return item->val_int_unsigned_typecast_from_int();
return item->val_int_unsigned_typecast_from_real();
}
longlong Type_handler_int_result::
......@@ -4537,6 +4537,32 @@ longlong Type_handler_temporal_result::
return item->val_int_unsigned_typecast_from_int();
}
longlong Type_handler_time_common::
Item_val_int_unsigned_typecast(Item *item) const
{
/*
TODO: this should eventually be fixed to do rounding
when TIME_ROUND_FRACTIONAL is enabled, together with
Field_{tiny|short|long|longlong}::store_time_dec().
See MDEV-19502.
*/
THD *thd= current_thd;
Time tm(thd, item);
DBUG_ASSERT(!tm.is_valid_time() == item->null_value);
if (!tm.is_valid_time())
return 0;
longlong res= tm.to_longlong();
if (res < 0)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DATA_OVERFLOW, ER_THD(thd, ER_DATA_OVERFLOW),
ErrConvTime(tm.get_mysql_time()).ptr(),
"UNSIGNED BIGINT");
return 0;
}
return res;
}
longlong Type_handler_string_result::
Item_val_int_unsigned_typecast(Item *item) const
{
......
......@@ -5199,6 +5199,7 @@ class Type_handler_time_common: public Type_handler_temporal_result
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
String *print_item_value(THD *thd, Item *item, String *str) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment