List:Commits« Previous MessageNext Message »
From:Alexey Kopytov Date:December 1 2007 7:06am
Subject:bk commit into 5.0 tree (kaa:1.2527) BUG#26788
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of kaa. When kaa does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-12-01 10:05:59+03:00, kaa@polly.(none) +6 -0
  Fix for bug #26788 "mysqld (debug) aborts when inserting specific
  numbers into char fields" and bug #12860 "Difference in zero padding of
  exponent between Unix and Windows"
  
  Rewrote the code that determines what 'precision' argument should be
  passed to sprintf() to fit the string representation of the input number
  into the field.
  We get finer control over conversion by pre-calculating the exponent, so
  we are able to determine which conversion format, 'e' or 'f', will be
  used by sprintf().
  We also remove the leading zero from the exponent on Windows to make it
  compatible with the sprintf() output on other platforms.

  mysql-test/r/insert.result@stripped, 2007-12-01 10:05:54+03:00, kaa@polly.(none) +120 -0
    Added test cases for bug #26788 and bug #31152.

  mysql-test/t/cast.test@stripped, 2007-12-01 10:05:54+03:00, kaa@polly.(none) +0 -2
    Removed --replace_result, since the result is now correct on Windows.

  mysql-test/t/insert.test@stripped, 2007-12-01 10:05:54+03:00, kaa@polly.(none) +81 -0
    Added test cases for bug #26788 and bug #31152.

  mysql-test/t/type_float.test@stripped, 2007-12-01 10:05:54+03:00, kaa@polly.(none) +0 -5
    Removed --replace_result, since the result is now correct on Windows.

  mysql-test/t/variables.test@stripped, 2007-12-01 10:05:54+03:00, kaa@polly.(none) +0 -2
    Removed --replace_result, since the result is now correct on Windows.

  sql/field.cc@stripped, 2007-12-01 10:05:54+03:00, kaa@polly.(none) +60 -14
    Rewrote the code that determines what 'precision' argument should be
    passed to sprintf() to fit the string representation of the input number
    into the field.
    We get finer control over conversion by pre-calculating the exponent, so
    we are able to determine which conversion format, 'e' or 'f', will be
    used by sprintf().

diff -Nrup a/mysql-test/r/insert.result b/mysql-test/r/insert.result
--- a/mysql-test/r/insert.result	2007-05-30 16:04:02 +04:00
+++ b/mysql-test/r/insert.result	2007-12-01 10:05:54 +03:00
@@ -461,4 +461,124 @@ i
 2
 2
 DROP TABLE t1, t2;
+CREATE TABLE t1 (
+a char(20) NOT NULL,
+b char(7) DEFAULT NULL,
+c char(4) DEFAULT NULL
+);
+INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0);
+INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05);
+Warnings:
+Warning	1265	Data truncated for column 'c' at row 1
+INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04);
+INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01);
+INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01);
+INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05);
+INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10);
+INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15);
+INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0);
+INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78);
+INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94);
+INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203);
+INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175);
+INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0);
+INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0);
+INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0);
+Warnings:
+Warning	1265	Data truncated for column 'c' at row 1
+INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3);
+Warnings:
+Warning	1265	Data truncated for column 'c' at row 1
+INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2);
+Warnings:
+Warning	1265	Data truncated for column 'c' at row 1
+INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0);
+INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0);
+Warnings:
+Warning	1265	Data truncated for column 'c' at row 1
+SELECT * FROM t1;
+a	b	c
+9.999999000000000748	10	10
+1.225e-05	1.2e-05	1e-0
+0.0001225	0.00012	NULL
+0.122499999999999998	0.1225	NULL
+0.122587699999999994	0.12259	NULL
+12.25	12.25	NULL
+12.25	12.25	12.2
+122500	122500	NULL
+12250000000	1.2e+10	NULL
+1225000000000000	1.2e+15	NULL
+5000000	5000000	NULL
+1.25e+78	1.2e+78	NULL
+1.25e-94	1.2e-94	NULL
+1.25e+203	1e+203	NULL
+1.25e-175	1e-175	NULL
+1.225000000000000089	NULL	1.23
+1.370000000000000107	NULL	1.37
+-1.37	NULL	-1.3
+0.00187	NULL	0.00
+-0.0187	NULL	-0.0
+5000	NULL	5000
+-5000	NULL	-500
+DROP TABLE t1;
+CREATE TABLE t1 (
+a char(20) NOT NULL,
+b char(7) DEFAULT NULL,
+c char(5)
+);
+INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0);
+INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05);
+INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04);
+INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01);
+INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01);
+INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05);
+INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10);
+INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15);
+INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0);
+INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78);
+INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94);
+INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203);
+INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175);
+INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0);
+INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0);
+INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0);
+INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3);
+INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2);
+Warnings:
+Warning	1265	Data truncated for column 'c' at row 1
+INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0);
+INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0);
+SELECT * FROM t1;
+a	b	c
+9.999999000000000748	10	9.999
+1.225e-05	1.2e-05	1e-05
+0.0001225	0.00012	NULL
+0.122499999999999998	0.1225	NULL
+0.122587699999999994	0.12259	NULL
+12.25	12.25	NULL
+12.25	12.25	12.25
+122500	122500	NULL
+12250000000	1.2e+10	NULL
+1225000000000000	1.2e+15	NULL
+5000000	5000000	NULL
+1.25e+78	1.2e+78	NULL
+1.25e-94	1.2e-94	NULL
+1.25e+203	1e+203	NULL
+1.25e-175	1e-175	NULL
+1.225000000000000089	NULL	1.225
+1.370000000000000107	NULL	1.37
+-1.37	NULL	-1.37
+0.00187	NULL	0.002
+-0.0187	NULL	-0.01
+5000	NULL	5000
+-5000	NULL	-5000
+DROP TABLE t1;
+CREATE TABLE t (a CHAR(10),b INT);
+INSERT INTO t VALUES (),(),();
+INSERT INTO t(a) SELECT rand() FROM t;
+DROP TABLE t;
 End of 5.0 tests.
diff -Nrup a/mysql-test/t/cast.test b/mysql-test/t/cast.test
--- a/mysql-test/t/cast.test	2007-07-20 00:05:09 +04:00
+++ b/mysql-test/t/cast.test	2007-12-01 10:05:54 +03:00
@@ -177,8 +177,6 @@ select cast(1.0e+300 as signed int);
 CREATE TABLE t1 (f1 double);
 INSERT INTO t1 SET f1 = -1.0e+30 ;
 INSERT INTO t1 SET f1 = +1.0e+30 ;
-# Expected result is +-1e+30, but Windows returns +-1e+030.
---replace_result 1e+030 1e+30
 SELECT f1 AS double_val, CAST(f1 AS SIGNED INT) AS cast_val FROM t1;
 DROP TABLE t1;					   
 
diff -Nrup a/mysql-test/t/insert.test b/mysql-test/t/insert.test
--- a/mysql-test/t/insert.test	2007-05-16 09:51:03 +04:00
+++ b/mysql-test/t/insert.test	2007-12-01 10:05:54 +03:00
@@ -353,5 +353,86 @@ SELECT * FROM t2;
 
 DROP TABLE t1, t2;
 
+#
+# Bug #26788: mysqld (debug) aborts when inserting specific numbers into char
+#             fields
+#
+
+CREATE TABLE t1 (
+  a char(20) NOT NULL,
+  b char(7) DEFAULT NULL,
+  c char(4) DEFAULT NULL
+);
+
+INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0);
+INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05);
+INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04);
+INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01);
+INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01);
+INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05);
+INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10);
+INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15);
+INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0);
+INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78);
+INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94);
+INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203);
+INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175);
+INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0);
+INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0);
+INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0);
+INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3);
+INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2);
+INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0);
+INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0);
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+  a char(20) NOT NULL,
+  b char(7) DEFAULT NULL,
+  c char(5)
+);
+
+
+INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0);
+INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05);
+INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04);
+INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01);
+INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01);
+INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01);
+INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05);
+INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10);
+INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15);
+INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0);
+INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78);
+INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94);
+INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203);
+INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175);
+INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0);
+INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0);
+INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0);
+INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3);
+INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2);
+INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0);
+INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0);
+
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+#
+# Bug #31152: assertion in Field_str::store(double)
+#
+
+CREATE TABLE t (a CHAR(10),b INT);
+INSERT INTO t VALUES (),(),();
+INSERT INTO t(a) SELECT rand() FROM t;
+DROP TABLE t;
+
 --echo End of 5.0 tests.
 
diff -Nrup a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
--- a/mysql-test/t/type_float.test	2007-05-28 12:44:57 +04:00
+++ b/mysql-test/t/type_float.test	2007-12-01 10:05:54 +03:00
@@ -116,15 +116,10 @@ drop table if exists t1;
 # Check conversion of floats to character field (Bug #7774)
 create table t1 (c char(20));
 insert into t1 values (5e-28);
-# Expected result is "5e-28", but windows returns "5e-028"
---replace_result 5e-028 5e-28
 select * from t1;
 drop table t1;
 create table t1 (c char(6));
 insert into t1 values (2e5),(2e6),(2e-4),(2e-5);
-# Expected result is "2e+06", but windows returns "2e+006"
-# Expected result is "2e-05", but windows returns "2e-005"
---replace_result 2e+006 2e+06 2e-005 2e-05
 select * from t1;
 drop table t1;
 
diff -Nrup a/mysql-test/t/variables.test b/mysql-test/t/variables.test
--- a/mysql-test/t/variables.test	2007-04-09 16:58:53 +04:00
+++ b/mysql-test/t/variables.test	2007-12-01 10:05:54 +03:00
@@ -51,8 +51,6 @@ select @test, @`test`, @TEST, @`TEST`, @
 set @select=2,@t5=1.23456;
 select @`select`,@not_used;
 set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL;
-# Expected result "1e-10", windows returns "1e-010"
---replace_result 1e-010 1e-10
 select @test_int,@test_double,@test_string,@test_string2,@select;
 set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello";
 select @test_int,@test_double,@test_string,@test_string2;
diff -Nrup a/sql/field.cc b/sql/field.cc
--- a/sql/field.cc	2007-08-06 15:57:26 +04:00
+++ b/sql/field.cc	2007-12-01 10:05:54 +03:00
@@ -5907,24 +5907,70 @@ int Field_str::store(double nr)
 {
   char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
   uint length;
-  bool use_scientific_notation= TRUE;
   uint local_char_length= field_length / charset()->mbmaxlen;
-  /*
-    Check fabs(nr) against longest value that can be stored in field,
-    which depends on whether the value is < 1 or not, and negative or not
-  */
   double anr= fabs(nr);
   int neg= (nr < 0.0) ? 1 : 0;
-  if (local_char_length > 4 && local_char_length < 32 &&
-      (anr < 1.0 ? anr > 1/(log_10[max(0,(int) local_char_length-neg-2)]) /* -2 for "0." */
-                 : anr < log_10[local_char_length-neg]-1))
-    use_scientific_notation= FALSE;
+  uint max_length;
+  int exp;
+  uint digits;
+  uint i;
+
+  /* Calculate the exponent from the 'e'-format conversion */
+  if (anr < 1.0 && anr > 0)
+  {
+    for (exp= 0; anr < 1e-100; exp-= 100, anr*= 1e100);
+    for (; anr < 1e-10; exp-= 10, anr*= 1e10);
+    for (i= 1; anr < 1 / log_10[i]; exp--, i++);
+    exp--;
+  }
+  else
+  {
+    for (exp= 0; anr > 1e100; exp+= 100, anr/= 1e100);
+    for (; anr > 1e10; exp+= 10, anr/= 1e10);
+    for (i= 1; anr > log_10[i]; exp++, i++);
+  }
+
+  max_length= local_char_length - neg;
 
-  length= (uint) my_sprintf(buff, (buff, "%-.*g",
-                                   (use_scientific_notation ?
-                                    max(0, (int)local_char_length-neg-5) :
-                                    local_char_length),
-                                   nr));
+  /*
+    Since in sprintf("%g") precision means the number of significant digits,
+    calculate the maximum number of significant digits if the 'f'-format
+    would be used (+1 for decimal point if the number has a fractional part).
+  */
+  digits= max(0, (int) max_length - (nr != trunc(nr)));
+  /*
+    If the exponent is negative, decrease digits by the number of leading zeros
+    after the decimal point that do not count as significant digits.
+  */
+  if (exp < 0)
+    digits= max(0, (int) digits + exp);
+  /*
+    'e'-format is used only if the exponent is less than -4 or greater than or
+    equal to the precision. In this case we need to adjust the number of
+    significant digits to take "e+NN" + decimal point into account (hence -5).
+    We also have to reserve one additional character if abs(exp) >= 100.
+  */
+  if (exp >= (int) digits || exp < -4)
+    digits= max(0, (int) (max_length - 5 - (exp >= 100 || exp <= -100)));
+  
+  length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr));
+
+#ifdef __WIN__
+  /*
+    Windows always zero-pads the exponent to 3 digits, we want to remove the
+    leading 0 to match the sprintf() output on other platforms.
+  */
+  if ((exp >= (int) digits || exp < -4) && exp > -100 && exp < 100)
+  {
+    DBUG_ASSERT(length >= 6); /* 1e+NNN */
+    uint tmp= length - 3;
+    buff[tmp]= buff[tmp + 1];
+    tmp++;
+    buff[tmp]= buff[tmp + 1];
+    length--;
+  }
+#endif
+  
   /*
     +1 below is because "precision" in %g above means the
     max. number of significant digits, not the output width.
Thread
bk commit into 5.0 tree (kaa:1.2527) BUG#26788Alexey Kopytov1 Dec