diff --git a/mysql-test/main/cast.result b/mysql-test/main/cast.result index ca314573581..1dc6bbbf9e7 100644 --- a/mysql-test/main/cast.result +++ b/mysql-test/main/cast.result @@ -9,6 +9,7 @@ CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER) -1 Warnings: Note 1105 Cast to unsigned converted negative integer to it's positive complement +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement select CAST('10 ' as unsigned integer); CAST('10 ' as unsigned integer) 10 @@ -29,6 +30,8 @@ Note 1105 Cast to unsigned converted negative integer to it's positive complemen select ~5, cast(~5 as signed); ~5 cast(~5 as signed) 18446744073709551610 -6 +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement explain extended select ~5, cast(~5 as signed); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used @@ -37,6 +40,8 @@ Note 1003 select ~5 AS `~5`,cast(~5 as signed) AS `cast(~5 as signed)` select cast(18446744073709551615 as signed); cast(18446744073709551615 as signed) -1 +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement select cast(5 as unsigned) -6.0; cast(5 as unsigned) -6.0 -1.0 @@ -212,12 +217,16 @@ CAST(0xb3 as signed) select CAST(0x8fffffffffffffff as signed); CAST(0x8fffffffffffffff as signed) -8070450532247928833 +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement select CAST(0xffffffffffffffff as unsigned); CAST(0xffffffffffffffff as unsigned) 18446744073709551615 select CAST(0xfffffffffffffffe as signed); CAST(0xfffffffffffffffe as signed) -2 +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement select cast('-10a' as signed integer); cast('-10a' as signed integer) -10 @@ -554,6 +563,8 @@ cast(18446744073709551615 as unsigned) select cast(18446744073709551615 as signed); cast(18446744073709551615 as signed) -1 +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement select cast('18446744073709551615' as unsigned); cast('18446744073709551615' as unsigned) 18446744073709551615 @@ -1277,3 +1288,11 @@ END; $$ ERROR 22007: Truncated incorrect CHAR(1) value: '10:20:30' SET sql_mode=DEFAULT; +# +# MDEV-10307 CAST(11068046444225730969 AS SIGNED) does not return a warning +# +SELECT CAST(11068046444225730969 AS SIGNED); +CAST(11068046444225730969 AS SIGNED) +-7378697629483820647 +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement diff --git a/mysql-test/main/cast.test b/mysql-test/main/cast.test index b514dbb5b2d..f48d6d9f95f 100644 --- a/mysql-test/main/cast.test +++ b/mysql-test/main/cast.test @@ -724,3 +724,9 @@ $$ DELIMITER ;$$ SET sql_mode=DEFAULT; + +--echo # +--echo # MDEV-10307 CAST(11068046444225730969 AS SIGNED) does not return a warning +--echo # + +SELECT CAST(11068046444225730969 AS SIGNED); diff --git a/mysql-test/main/default.result b/mysql-test/main/default.result index 73417d0d64e..c214e529d72 100644 --- a/mysql-test/main/default.result +++ b/mysql-test/main/default.result @@ -2217,6 +2217,8 @@ t1 CREATE TABLE `t1` ( `b` bigint(20) DEFAULT (cast(`a` as signed)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 INSERT INTO t1 (a) VALUES (0xFFFFFFFFFFFFFFFF); +Warnings: +Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement SELECT * FROM t1; a b 18446744073709551615 -1 diff --git a/sql/item.cc b/sql/item.cc index faae5c5ad03..a9139ceb0b1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -333,6 +333,15 @@ longlong Item::val_int_unsigned_typecast_from_int() } +longlong Item::val_int_signed_typecast_from_int() +{ + longlong value= val_int(); + if (!null_value && unsigned_flag && value < 0) + push_note_converted_to_negative_complement(current_thd); + return value; +} + + String *Item::val_string_from_date(String *str) { MYSQL_TIME ltime; diff --git a/sql/item.h b/sql/item.h index c11a4fe56c0..4261ef64950 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1057,6 +1057,13 @@ public: longlong val_int_unsigned_typecast_from_decimal(); longlong val_int_unsigned_typecast_from_int(); longlong val_int_unsigned_typecast_from_str(); + + /** + Get a value for CAST(x AS UNSIGNED). + Huge positive unsigned values are converted to negative complements. + */ + longlong val_int_signed_typecast_from_int(); + /* This is just a shortcut to avoid the cast. You should still use unsigned_flag to check the sign of the item. diff --git a/sql/sql_type.cc b/sql/sql_type.cc index c2c853efa23..a40172967a7 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -3380,7 +3380,7 @@ longlong Type_handler_real_result:: longlong Type_handler_int_result:: Item_val_int_signed_typecast(Item *item) const { - return item->val_int(); + return item->val_int_signed_typecast_from_int(); } longlong Type_handler_decimal_result::