Bug #61413 | UNSIGNED value is out of range | ||
---|---|---|---|
Submitted: | 5 Jun 2011 18:41 | Modified: | 11 Aug 2011 20:01 |
Reporter: | Peter Laursen (Basic Quality Contributor) | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: Data Types | Severity: | S3 (Non-critical) |
Version: | 5.5.13 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | qc |
[5 Jun 2011 18:41]
Peter Laursen
[6 Jun 2011 4:52]
Valeriy Kravchuk
I do not see any different behavior here. Multiplication is also done left to right, and all that matters is sign of the value at each stage of evaluation. If value becomes negative you get error. Compare: mysql> select id*(-2)*(-2) from a; ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`test`.`a`.`id` * -(2))' mysql> select id*((-2)*(-2)) from a; +----------------+ | id*((-2)*(-2)) | +----------------+ | 4 | +----------------+ 1 row in set (0.00 sec) Note also that there is yet another way to get the reasonable value, cast(): mysql> select cast(id as signed)*(-2)*(-2) from a; +------------------------------+ | cast(id as signed)*(-2)*(-2) | +------------------------------+ | 4 | +------------------------------+ 1 row in set (0.00 sec)
[6 Jun 2011 8:18]
MySQL Verification Team
is there anything on this page that should be further clarified? http://dev.mysql.com/doc/refman/5.5/en/out-of-range-and-overflow.html
[6 Jun 2011 12:28]
Peter Laursen
I am an idiot of course. Multipying 2 positive and one negative number will always result in a negative value no matter operands' order. What remains is this: SELECT CAST(1 AS UNSIGNED) - 2 + 2; -- Error Code : 1690 SELECT CAST(1 AS UNSIGNED) + 2 - 2; -- returns 1 In 5.1 the first statment was able to deliver perfect (and not overflowing) result and CAST to SIGNED will discard half of the storable range in the output in case the argument is a BIGINT. Am I right in this? I do not see why the check for this error condition needs to be done on *intermediate results* of a calculation. Doing the check with the *final result* only would be better I think (for backwards compability and in order to make it possible to have the full range of a BIGINT UNSIGNED returned). If not possible or desirable to change this I think this page http://dev.mysql.com/doc/refman/5.5/en/server-sql-mode.html#sqlmode_no_unsigned_subtractio... should clarify that the error condition may be raised if an intermediate result of a calculation overflows.
[6 Jun 2011 13:05]
Peter Laursen
Test case showing how large BIGINT UNSIGNED cannot be returned to client if CAST to SIGNED is used. DROP TABLE IF EXISTS tt; CREATE TABLE tt (num BIGINT UNSIGNED); INSERT INTO tt VALUES (18446744073709551615); -- 'MAXBIGINT' value inserted SELECT * FROM tt; SELECT CAST(num AS UNSIGNED) FROM tt; -- 18446744073709551615 SELECT CAST(num AS UNSIGNED) -2 + 2 FROM tt; -- 18446744073709551615 SELECT CAST(num AS UNSIGNED) +2 - 2 FROM tt; -- Error Code : 1690 -- this is what we already discussed. SELECT CAST(num AS SIGNED) FROM tt; -- (-1) SELECT CAST(num AS SIGNED) -2 + 2 FROM tt; -- (-1) SELECT CAST(num AS SIGNED) +2 - 2 FROM tt; -- (-1) -- CAST to UNSIGNED destroys the large value stored. How can I safely do such simple calculations and have correct results with a large stored BIGINT UNSIGNED?
[6 Jun 2011 13:08]
Valeriy Kravchuk
Hint: mysql> select cast(-1 as unsigned); +----------------------+ | cast(-1 as unsigned) | +----------------------+ | 18446744073709551615 | +----------------------+ 1 row in set (0.00 sec)
[6 Jun 2011 13:22]
Peter Laursen
Will it always be safe to CAST to SIGNED with an arithmetic operation and next 'CAST back' to UNSIGNED? If not to operate safely on large BIGIN UNSIGNED values it looks to me that the application will need to 'mirror' the calcualtion in order to apply a function order of operands. Then we may as well drop the calculation if the server and calculate in the client. We are human users sitting in front of a monitor with a simple test case that we can have in our heads. In real world it would be applications that face this issue. It cannot choose as intelligently as you (and even not as stupid as I).
[11 Aug 2011 20:01]
Sveta Smirnova
Thank you for the feedback. > Will it always be safe to CAST to SIGNED with an arithmetic operation and next 'CAST back' to UNSIGNED? Not, it would not: if UNSIGNED value is larger than SIGNED you will get overflow issue again. But having data storage limitation we always can choose a compromise. You can also try sql mode NO_UNSIGNED_SUBTRACTION as described at http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html