Bug #46799 | Subtraction from unsigned integers wraps around | ||
---|---|---|---|
Submitted: | 19 Aug 2009 0:53 | Modified: | 19 Aug 2009 5:54 |
Reporter: | Peter Jeremy | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: Data Types | Severity: | S3 (Non-critical) |
Version: | 5.1.32-ndb-7.0.5-cluster-gpl-log | OS: | Solaris (5.10 Generic_139555-08) |
Assigned to: | CPU Architecture: | Any |
[19 Aug 2009 0:53]
Peter Jeremy
[19 Aug 2009 5:54]
Tonci Grgin
Hi Peter and thanks for your report. Verified just as described on OpenSolaris x64 host with MySQL server 5.1.31 using both MyISAM and InnoDB engines. Now, I do not see this as a bug at all. I think what happens is that MySQL server get's NAN from underlying HW (cause of integer overflow) and converts it to something appropriate throwing warning or error, depending on SQL_MODE, in the process. So, please use "STRICT_TRANS_TABLES" and your table will not get updated because of error, which is what I would have expected and how other RDBM's behave: mysql> set @@SQL_MODE="STRICT_TRANS_TABLES"; Query OK, 0 rows affected (0.00 sec) mysql> select @@SQL_MODE; +---------------------+ | @@SQL_MODE | +---------------------+ | STRICT_TRANS_TABLES | +---------------------+ 1 row in set (0.00 sec) ... mysql> update bug46799 set a=a-5, b=b-5, c=c-5, d=d-5, e=e-5; ERROR 1264 (22003): Out of range value for column 'a' at row 1 mysql> show warnings; +-------+------+--------------------------------------------+ | Level | Code | Message | +-------+------+--------------------------------------------+ | Error | 1264 | Out of range value for column 'a' at row 1 | | Error | 1264 | Out of range value for column 'b' at row 1 | | Error | 1264 | Out of range value for column 'c' at row 1 | | Error | 1264 | Out of range value for column 'd' at row 1 | +-------+------+--------------------------------------------+ 4 rows in set (0.00 sec) mysql> select * from bug46799; +------+------+------+------+------+ | a | b | c | d | e | +------+------+------+------+------+ | 1 | 1 | 1 | 1 | 1 | +------+------+------+------+------+ 1 row in set (0.00 sec)
[19 Aug 2009 6:45]
Susanne Ebrecht
What exactly happens here is described at the bottom of: http://dev.mysql.com/doc/refman/5.1/en/numeric-types.html <paste> Subtraction between integer values, where one is of type UNSIGNED, produces an unsigned result by default. If the result would otherwise have been negative, it becomes the maximum integer value. If the NO_UNSIGNED_SUBTRACTION SQL mode is enabled, the result is negative. ... If the result of such an operation is used to update an UNSIGNED integer column, the result is clipped to the maximum value for the column type, or clipped to 0 if NO_UNSIGNED_SUBTRACTION is enabled. If strict SQL mode is enabled, an error occurs and the column remains unchanged. </paste>