| Bug #6147 | Traditional: Assigning a string to a numeric column has unexpected results | ||
|---|---|---|---|
| Submitted: | 18 Oct 2004 22:03 | Modified: | 4 Oct 2006 3:30 |
| Reporter: | Trudy Pelzer | ||
| Status: | Closed | ||
| Category: | Server: General | Severity: | S3 (Non-critical) |
| Version: | 5.0.2-alpha-debug | OS: | Linux (SuSE 9.1) |
| Assigned to: | Alexander Barkov | Target Version: | |
[18 Oct 2004 22:03]
Trudy Pelzer
[19 Oct 2004 2:41]
Miguel Solorzano
Verified on latest Bk source.
[7 Apr 2005 1:02]
Trudy Pelzer
More information on this issue.
The problem appears to be connected to how MySQL does rounding
on INSERT. The rounding should be based on the data type of the
target, and is being done correctly unless (a) the source is a string that
is being converted to a number and (b) the target is an integer:
mysql> create table t (i int, f float, d0 decimal, d1 decimal(3,1));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t values (2.44,2.44,2.44,2.44);
Query OK, 1 row affected, 2 warnings (0.01 sec)
mysql> insert into t values (2.55,2.55,2.55,2.55);
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> insert into t values (2.66,2.66,2.66,2.66);
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> select * from t;
+------+------+------+------+
| i | f | d0 | d1 |
+------+------+------+------+
| 2 | 2.44 | 2 | 2.4 |
| 3 | 2.55 | 3 | 2.6 |
| 3 | 2.66 | 3 | 2.7 |
+------+------+------+------+
3 rows in set (0.00 sec)
--As expected; exact numeric source gets rounded based on data type of
target (round half-up for i, d0, d1; no rounding for float)
mysql> insert into t values ('2.44','2.44','2.44','2.44');
Query OK, 1 row affected, 3 warnings (0.00 sec)
mysql> insert into t values ('2.55','2.55','2.55','2.55');
Query OK, 1 row affected, 3 warnings (0.00 sec)
mysql> insert into t values ('2.66','2.66','2.66','2.66');
Query OK, 1 row affected, 3 warnings (0.00 sec)
mysql> select * from t;
+------+------+------+------+
| i | f | d0 | d1 |
+------+------+------+------+
| 2 | 2.44 | 2 | 2.4 |
| 3 | 2.55 | 3 | 2.6 |
| 3 | 2.66 | 3 | 2.7 |
| 2 | 2.44 | 2 | 2.4 |
| 2 | 2.55 | 3 | 2.6 |
| 2 | 2.66 | 3 | 2.7 |
+------+------+------+------+
6 rows in set (0.00 sec)
-- Not as expected; approximate numeric source should get rounded based on data
type of target. Float decimal, and decimal(3,1) columns are treated correctly; integer
column is treated incorrectly, it should result in 2,3,3. Conclusion: bug in INSERT
for integers when source is approximate numeric *if* source is approximate numeric
because it's a string
mysql> insert into t values (2.44e0,2.44e0,2.44e0,2.44e0);
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> insert into t values (2.55e0,2.55e0,2.55e0,2.55e0);
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> insert into t values (2.66e0,2.66e0,2.66e0,2.66e0);
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> select * from t;
+------+------+------+------+
| i | f | d0 | d1 |
+------+------+------+------+
| 2 | 2.44 | 2 | 2.4 |
| 3 | 2.55 | 3 | 2.6 |
| 3 | 2.66 | 3 | 2.7 |
| 2 | 2.44 | 2 | 2.4 |
| 2 | 2.55 | 3 | 2.6 |
| 2 | 2.66 | 3 | 2.7 |
| 2 | 2.44 | 2 | 2.4 |
| 3 | 2.55 | 3 | 2.6 |
| 3 | 2.66 | 3 | 2.7 |
+------+------+------+------+
9 rows in set (0.00 sec)
-- As expected; approximate numeric source being rounded based on data type of target.
Note that when the approximate numeric source is a numeric literal rather than a string,
the rounding into an integer target is correct.
mysql> insert into t values ('2.44e0','2.44e0','2.44e0','2.44e0');
Query OK, 1 row affected, 3 warnings (0.00 sec)
mysql> insert into t values ('2.55e0','2.55e0','2.55e0','2.55e0');
Query OK, 1 row affected, 3 warnings (0.00 sec)
mysql> insert into t values ('2.66e0','2.66e0','2.66e0','2.66e0');
Query OK, 1 row affected, 3 warnings (0.00 sec)
mysql> select * from t;
+------+------+------+------+
| i | f | d0 | d1 |
+------+------+------+------+
| 2 | 2.44 | 2 | 2.4 |
| 3 | 2.55 | 3 | 2.6 |
| 3 | 2.66 | 3 | 2.7 |
| 2 | 2.44 | 2 | 2.4 |
| 2 | 2.55 | 3 | 2.6 |
| 2 | 2.66 | 3 | 2.7 |
| 2 | 2.44 | 2 | 2.4 |
| 3 | 2.55 | 3 | 2.6 |
| 3 | 2.66 | 3 | 2.7 |
| 2 | 2.44 | 2 | 2.4 |
| 2 | 2.55 | 3 | 2.6 |
| 2 | 2.66 | 3 | 2.7 |
+------+------+------+------+
12 rows in set (0.00 sec)
-- Not as expected; again, approximate numeric source into integer target should be
rounded based on data type of target (correct result is 2,3,3), all other targets show
correct result. Note again the fact that it's because the source is a string that the
integer problem occurs.
[10 Apr 2005 19:57]
Paul DuBois
Additional information regarding incorrect assignment
of numeric values specified as strings when inserted
into integer columns.
I believe the results can be explained as follows: If MySQL
is inserting into an INT column, and the source is a string,
MySQL tries to convert it to a number but stops at the decimal
point. (Probably this is more general, like "stops at first non-digit"
but it does appear to stop at the decimal point.)
Test script:
drop table if exists t;
create table t (i int, d decimal);
insert into t values(2.55,2.55);
insert into t values(2.55e0,2.55e0);
insert into t values(2.55e1,2.55e1);
insert into t values('2.55','2.55');
insert into t values('2.55e0','2.55e0');
insert into t values('2.55e1','2.55e1');
insert into t values('2.55e2','2.55e2');
select * from t;
The last few rows insert strings, so they require
string-to-number conversion. If that conversion
is always really to double, the results for both
columns should, I believe, be the same. But
here's the result:
+------+------+
| i | d |
+------+------+
| 3 | 3 |
| 3 | 3 |
| 26 | 26 |
| 2 | 3 |
| 2 | 3 |
| 2 | 26 |
| 2 | 255 |
+------+------+
Note the INT column results. It appears that when
the target column is an integer, the
string-to-number conversion is not "to double" but
"until the first non-digit" or something. The
conversion appears to stop at the decimal point
because it entirely ignores the exponent.
The problem is demonstrated most clearly by the
values expressed as strings are numbers in
scientific notation. But the conversion problem
is more general in that, for values with any
fractional part, the fractional part will be
truncated, not rounded.
[29 Jan 2006 23:30]
Alexej Kubarev
I can verify this in 5.0.18 on several different platforms
Several scripts stoped working after migration from 4.1 to 5.0.
It seems to me that this bug will actually stop migration of many hosts to the new
version.
For instance a very popular Invision Power Board script(latest version) will not even
install properly on 5.0.18 because of this problem.
Assigning an empty string to an int column is the problem: example query is:
INSERT INTO column (id, something) VALUES ('','some data')
where id is an int.
Beats me why does this happend but i know for sure that the problem is fixed as soon as i
change type of the "id" column to something like varchar
[18 Mar 2006 12:33]
Jim Winstead
discussed briefly with monty, and he has suggested making the string-to-integer conversion routines (like strntoll10, or something like that) handle doing the rounding, rather than any sort of string->decimal->integer conversion.
[5 Jun 2006 14:12]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/7268
[20 Jul 2006 10:42]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/9366
[2 Oct 2006 11:19]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/12925 ChangeSet@1.2286, 2006-10-02 14:17:41+05:00, bar@mysql.com +1 -0 bug#6147 - fixing ndb test results (forgot to include into the main commit)
[2 Oct 2006 11:20]
Alexander Barkov
Pushed into 5.0-rpl, currently marked as 5.0.26
[3 Oct 2006 22:03]
Chad MILLER
Available in 5.0.26.
[3 Oct 2006 22:11]
Chad MILLER
Available in 5.1.12-beta.
[4 Oct 2006 3:30]
Paul DuBois
Noted in 5.0.26, 5.1.12 changelogs. With TRADITIONAL SQL mode, assignment of out-of-bound values and rounding of assigned values was done correctly, but assignment of the same numbers represented as strings sometimes was handled differently.
