Hi Serg,
Thanks for the partial review, I've committed a new patch, please see my
comments below.
On Thursday 26 July 2007, Sergei Golubchik wrote:
>> --- 1.48/include/m_string.h 2007-06-05 19:31:37 +04:00
>> +++ 1.49/include/m_string.h 2007-07-10 17:37:18 +04:00
>> @@ -196,8 +193,22 @@ extern char *strstr(const char *, const
>> extern int is_prefix(const char *, const char *);
>>
>> /* Conversion routines */
>> +typedef enum {
>> + MY_GCVT_ARG_FLOAT,
>> + MY_GCVT_ARG_DOUBLE
>> +} my_gcvt_arg_type;
>> +
>> double my_strtod(const char *str, char **end, int *error);
>> double my_atof(const char *nptr);
>> +my_bool my_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
>> char **end); +my_bool my_fcvt(double x, int precision, char *to, char
>> **end);
>> +/*
>> + The longest string my_fcvt can return is 311 + "precision".
>> + Here we assume that we never cal my_fcvt() with precision >=
>> NOT_FIXED_DEC
>
>do you assert it ?
>
OK, assertion added in the new patch. I had to move NOT_FIXED_DEC from field.h
to m_string.h.
>> + (+ 1 byte for the terminating '\0').
>> +*/
>> +#define FLOATING_POINT_BUFFER 342
>
>it's be clearer if you'd write (311+NOT_FIXED_DEC) instead of 342
>
Done.
>> +
>>
>> extern char *llstr(longlong value,char *buff);
>> #ifndef HAVE_STRTOUL
>> --- 1.395/sql/field.cc 2007-06-14 15:43:23 +04:00
>> +++ 1.396/sql/field.cc 2007-07-10 17:37:21 +04:00
>> @@ -2122,16 +2122,11 @@ int Field_decimal::store(double nr)
>> reg4 uint i;
>> size_t length;
>> uchar fyllchar,*to;
>> - char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
>> + char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE], *end;
>>
>> fyllchar = zerofill ? (char) '0' : (char) ' ';
>> -#ifdef HAVE_SNPRINTF
>> - buff[sizeof(buff)-1]=0; // Safety
>> - snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr);
>> - length= strlen(buff);
>> -#else
>> - length= my_sprintf(buff,(buff,"%.*f",dec,nr));
>> -#endif
>> + my_fcvt(nr, dec, buff, &end);
>> + length= end - buff;
>
>I see you use this pattern very often. May be my_fcvt/my_gcvt should
>return the length instead of the end ?
>
Done. I've looked through all of my_fcvt()/my_gcvt() calls and in most cases
we need to know the length of converted string rather than pointer to the
last character. Also, we are interested in the status of conversion only in
one case. So I have changed my_fcvt()/my_gcvt() interfaces accordingly.
>> @@ -4077,8 +4013,12 @@ int Field_real::truncate(double *nr, dou
>> max_value*= log_10[order];
>> max_value-= 1.0 / log_10[dec];
>>
>> - double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec];
>> - res= floor(res) + tmp;
>> + /* Check for infinity so we don't get NaN in calculations */
>> + if (!my_isinf(res))
>> + {
>> + double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec];
>> + res= floor(res) + tmp;
>> + }
>
>1. it doesn't look like related to number-to-string conversion.
It is related in a way. Previous version of my_strtod() returned DBL_MAX in
case of overflows. dtoa's one returns Inf, which led to 'res' being NaN in
the above code.
>2. wouldn't it be better to do it after checks for max_value, not before ?
>
What for? We get rid of my_isinf() this way, but get additional comparison for
not_fixed.
>> }
>>
>> if (res < -max_value)
>> @@ -6036,35 +5921,13 @@ int Field_str::store(double nr)
>> int Field_str::store(double nr)
>> {
>> ASSERT_COLUMN_MARKED_FOR_WRITE;
>> - char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
>> + char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE], *end;
>> 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;
>> -
>> - length= (uint) my_sprintf(buff, (buff, "%-.*g",
>> - (use_scientific_notation ?
>> - max(0, (int)local_char_length-neg-5)
>> : - local_char_length),
>> - nr));
>> - /*
>> - +1 below is because "precision" in %g above means the
>> - max. number of significant digits, not the output width.
>> - Thus the width can be larger than number of significant digits by 1
>> - (for decimal point)
>> - the test for local_char_length < 5 is for extreme cases,
>> - like inserting 500.0 in char(1)
>> - */
>> - DBUG_ASSERT(local_char_length < 5 || length <= local_char_length+1);
>> +
>> + if (my_gcvt(nr, MY_GCVT_ARG_DOUBLE, local_char_length, buff, &end))
>> + report_data_too_long(this);
>
>This looks like a change in behavior. There was no ER_DATA_TOO_LONG
>here before. But ok, looks like we silently truncated the number before,
>so this is a good change.
>
Previously we relied on store(buff, length, charset) to issue a warning when
the number representation performed by sprintf() did not fit into the field.
Now, when my_gcvt() _never_ exceeds the specified width, we need to check for
conversion status.
>> + length= end - buff;
>> return store(buff, length, charset());
>> }
>>
>> --- 1.656/sql/mysqld.cc 2007-06-17 19:20:16 +04:00
>> +++ 1.657/sql/mysqld.cc 2007-07-10 17:37:22 +04:00
>> @@ -478,6 +478,40 @@ ulong expire_logs_days = 0;
>> ulong rpl_recovery_rank=0;
>> const char *log_output_str= "TABLE";
>>
>> +const double log_10[] = {
>> + 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
>> + 1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
>> + 1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
>> + 1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
>> + 1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
>> + 1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
>> + 1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
>> + 1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
>> + 1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
>> + 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
>> + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
>> + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
>> + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
>> + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
>> + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
>> + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
>> + 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
>> + 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
>> + 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
>> + 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
>> + 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
>> + 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
>> + 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
>> + 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
>> + 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
>> + 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
>> + 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
>> + 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
>> + 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
>> + 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
>> + 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
>> +};
>
>It doesn't need to be that big now, does it ?
>perhaps we can get rid of it completely ?
>
AFAIK, there is still one place where we need it, Field_real::truncate(). To
be exact, the more powers of 10 we have here, the more chances to avoid
the "tight loop" here:
uint order= field_length - dec;
uint step= array_elements(log_10) - 1;
max_value= 1.0;
for (; order > step; order-= step)
max_value*= log_10[step];
max_value*= log_10[order];
max_value-= 1.0 / log_10[dec];
>> +
>> time_t server_start_time;
>>
>> char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN],
>> system_time_zone[30]; --- 1.65/mysql-test/r/func_group.result 2007-05-29
>> 16:57:16 +04:00 +++ 1.66/mysql-test/r/func_group.result 2007-07-10
>> 17:37:18 +04:00 @@ -891,7 +891,7 @@ select 1e8 * sum(distinct df) from t1;
>> 330000000
>> select 1e8 * min(df) from t1;
>> 1e8 * min(df)
>> -110000000
>> +110000000.00000001
>
>explain this change, please
>
Two things:
1. Our decimal2double() conversion is imprecise due to 'naive' algorithm. It
would be better to just print the digits to a string buffer and then run
my_strtod() on it. Please let me know if you think this must be included into
the patch for WL#2934.
2. As a consequence of the above, we get 1.1000000000000001 when converting a
DECIMAL '1.1' to double. But String::set_real() previously involved
sprintf("%14g") for conversion, so it was just hiding the computational error
introduced by decimal2double().
>> create table t3 (ifl int);
>> insert into t3 values(1), (2);
>> select cast(min(ifl) as decimal(5,2)) from t3;
>> --- 1.41/mysql-test/r/func_math.result 2007-04-28 20:04:00 +04:00
>> +++ 1.42/mysql-test/r/func_math.result 2007-07-10 17:37:18 +04:00
>> @@ -44,7 +44,7 @@ Warnings:
>> Note 1003 select abs(-(10)) AS `abs(-10)`,sign(-(5)) AS
>> `sign(-5)`,sign(5) AS `sign(5)`,sign(0) AS `sign(0)` select
>> log(exp(10)),exp(log(sqrt(10))*2),log(-1),log(NULL),log(1,1),log(3,9),log(
>>-1,2),log(NULL,2);
>> log(exp(10)) exp(log(sqrt(10))*2) log(-1) log(NULL) log(1,1) log(3,9) log(
>>-1,2) log(NULL,2) -10 10 NULL NULL NULL 2 NULL NULL
>> +10 10.000000000000002 NULL NULL NULL 2 NULL NULL
>
>excessive precision again
>
Yes, because exp(log(sqrt(10))*2) is not binary equal to 10 due to
computational errors. Again, sprintf("%14") was just hiding this fact :)
>> explain extended select
>> log(exp(10)),exp(log(sqrt(10))*2),log(-1),log(NULL),log(1,1),log(3,9),log(
>>-1,2),log(NULL,2);
>> id select_type table type possible_keys key key_len ref rows filtered Extr
>>a 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
>> --- 1.34/mysql-test/r/insert.result 2007-05-31 13:19:10 +04:00
>> +++ 1.35/mysql-test/r/insert.result 2007-07-10 17:37:19 +04:00
>> @@ -159,6 +159,7 @@ set @value= "1e+1111111111a";
>> insert into t1
>> values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value
>>); Warnings:
>> Warning 1264 Out of range value for column 'f_double' at row 1
>> +Warning 1264 Out of range value for column 'f_double' at row 1
>
>why a duplicate warning ?
>
We get one from my_strtod() when it truncates "1e+1111111111a" to +Inf, and
another from if Field_real::truncate() which truncates +Inf to DBL_MAX.
>> Warning 1264 Out of range value for column 'f_float' at row 1
>> Warning 1264 Out of range value for column 'f_float' at row 1
>> Warning 1264 Out of range value for column 'f_double_7_2' at row 1
>> --- 1.145/mysql-test/t/mysqldump.test 2007-06-16 08:37:11 +04:00
>> +++ 1.146/mysql-test/t/mysqldump.test 2007-07-10 17:37:21 +04:00
>> @@ -38,7 +38,7 @@ CREATE TABLE t1 (a double);
>> INSERT INTO t1 VALUES ('-9e999999');
>> # The following replaces is here because some systems replaces the above
>> # double with '-inf' and others with MAX_DOUBLE
>
>is this comment above still true ?
>we don't rely on "system" dtoa anymore
>
It was not. Fixed in the new patch.
>> --- 1.61/mysql-test/r/ps_2myisam.result 2007-06-05 19:51:44 +04:00
>> +++ 1.62/mysql-test/r/ps_2myisam.result 2007-07-10 17:37:19 +04:00
>> @@ -2822,10 +2822,10 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c
>> 51 5 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0 51.0
>> 52 5 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0 52.0
>> 53 5 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0 53.0
>> -54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
>> +54 0 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
>
>This is probably a bad idea.
>when you cannot convert a number to a string in a too small buffer
>you return 0. Old code was truncating the string, which I believe was
>correct. It's like assigning a long string to a short buffer -
>a string should be truncated.
>
It looks like a "gray area" to me. The counter-argument would be that when
truncating a string the result is always a valid string. When truncating
string representations of a number, the result may not even be a valid string
representation of a number. Examples of the old behavior:
mysql> create table t1(f1 char(1));
Query OK, 0 rows affected (0.05 sec)
mysql> insert into t1 values(-0.1);
Query OK, 1 row affected, 1 warning (0.07 sec)
mysql> select * from t1;
+------+
| f1 |
+------+
| - |
+------+
1 row in set (0.00 sec)
mysql> alter table t1 modify f1 char(2);
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into t1 values(1e100);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t1;
+------+
| f1 |
+------+
| - |
| 1e |
+------+
2 rows in set (0.00 sec)
Though I don't know what the standard says about such cases.
>> 55 5 55 55 55 55 55 55 55 55 55 55
>> -56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
>> -57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
>> +56 0 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
>> +57 0 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
>> 60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
>> 61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
>> 62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
>> --- 1.36/mysql-test/t/strict.test 2007-06-04 14:14:18 +04:00
>> +++ 1.37/mysql-test/t/strict.test 2007-07-10 17:37:21 +04:00
>> @@ -812,7 +812,7 @@ DROP TABLE t1;
>> CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED);
>> INSERT INTO t1 VALUES (-2.2E-307,0),(2E-307,0),(+1.7E+308,+1.7E+308);
>> INSERT INTO t1 VALUES
>> ('-2.2E-307',0),('-2E-307',0),('+1.7E+308','+1.7E+308'); -# We don't give
>> warnings for underflow
>> +--error 1367
>
>No. The comment and the old code are correct - we don't give warnings for
>underflow. SQL standard says (2003 latest draft, part II, 5.3 <literal>):
>
> NOTE 73 - Thus the only syntax error for an <approximate numeric
> literal> is what is commonly known as "overflow"; there is no syntax
> error for specifying more significant digits than the
> SQL-implementation can represent internally, nor for specifying a
> value that has no exact equivalent in the SQL-implementation's
> internal representation. ("Underflow", i.e., specifying a nonzero
> value so close to 0 (zero) that the closest representation in the
> SQL-implementation's internal representation is 0E0, is a special
> case of the latter condition, and is not a syntax error.)
>
OK, I didn't know about that. Reverted in the new patch.
>> INSERT INTO t1 (col1) VALUES (-2.2E-330);
>> --error 1367,1264
>> INSERT INTO t1 (col1) VALUES (+1.7E+309);
>> --- 1.34/mysql-test/t/type_float.test 2007-05-28 12:49:39 +04:00
>> +++ 1.35/mysql-test/t/type_float.test 2007-07-10 17:37:21 +04:00
>> @@ -241,4 +241,35 @@ insert into t1 values (2e30), (-2e30);
>> select f1 + 0e0 from t1;
>> drop table t1;
>>
>> +#
>> +# Bug #12860 "Difference in zero padding of exponent between Unix and
>> Windows" +#
>> +
>> +create table t1 (c char(6));
>> +insert into t1 values (2e6),(2e-5);
>> +select * from t1;
>> +drop table t1;
>> +
>> +#
>> +# Bug #21497 "DOUBLE truncated to unusable value"
>> +#
>> +
>> +CREATE TABLE d1 (d DOUBLE);
>> +INSERT INTO d1 VALUES (1.7976931348623157E+308);
>> +SELECT * FROM d1;
>> +--error ER_ILLEGAL_VALUE_FOR_TYPE
>
>Wrong. See a quote from the standard above.
>
I'm not following you here. Isn't this an example of overflow, for which we
must have a syntax error?
>> +INSERT INTO d1 VALUES (1.79769313486232e+308);
>> +SELECT * FROM d1;
>> +DROP TABLE d1;
>> +
>> +#
>> +# Bug #26788 "mysqld (debug) aborts when inserting specific numbers into
>> char +# fields"
>> +#
>> +
>> +create table t1 (a char(20));
>> +insert into t1 values (1.225e-05);
>> +select a+0 from t1;
>> +drop table t1;
>> +
>> --echo End of 5.0 tests
>> --- 1.56/mysql-test/r/type_float.result 2007-05-28 14:22:16 +04:00
>> +++ 1.57/mysql-test/r/type_float.result 2007-07-10 17:37:20 +04:00
>> @@ -4,7 +4,7 @@ SELECT 10,10.0,10.,.1e+2,100.0e-1;
>> 10 10.0 10 10 10
>> SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
>> 6e-05 -6e-05 --6e-05 -6e-05+1.000000
>> -6e-05 -6e-05 6e-05 0.99994
>> +0.00006 -0.00006 0.00006 0.99994
>
>that's no test. Old test was testing scientific notation.
>increase the exponent here, to keep scientific notation in the result
>
Fixed in the new patch.
>> SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
>> 1e1 1.e1 1.0e1 1e+1 1.e+1 1.0e+1 1e-1 1.e-1 1.0e-1
>> 10 10 10 10 10 10 0.1 0.1 0.1
>> --- 1.53/mysql-test/t/type_newdecimal.test 2007-05-21 21:30:06 +04:00
>> +++ 1.54/mysql-test/t/type_newdecimal.test 2007-07-10 17:37:21 +04:00
>> @@ -711,13 +711,6 @@ select 0.07 * 0.07;
>> #
>> set sql_mode='traditional';
>> #
>> -select 1E-500 = 0;
>> -#-- should return 1 (true).
>> -#
>> -select 1 / 1E-500;
>> -#
>> -#-- should return SQLSTATE 22012 division by zero.
>> -#
>
>Nope. Keep them, 1e-500 is *not* a syntax error
>
OK, reverted in the new patch.
>> select 1 / 0;
>> #-- should return SQLSTATE 22012 division by zero.
>> #
>> --- 1.59/mysql-test/r/type_newdecimal.result 2007-05-21 21:31:05 +04:00
>> +++ 1.60/mysql-test/r/type_newdecimal.result 2007-07-10 17:37:20 +04:00
>> @@ -1175,21 +1167,21 @@ CAST(my_float AS DECIMAL(65,30)) my_fl
>> 0.000000000000000001175494374380 1.17549e-18
>> 0.000000000000000011754943743802 1.17549e-17
>> 0.000000000000000117549432474939 1.17549e-16
>> -0.000000000000001175494324749389 1.17549e-15
>> -0.000000000000011754943671010360 1.17549e-14
>> -0.000000000000117549429933840000 1.17549e-13
>> -0.000000000001175494380653563000 1.17549e-12
>> -0.000000000011754943372854760000 1.17549e-11
>> -0.000000000117549428524377200000 1.17549e-10
>> -0.000000001175494368510499000000 1.17549e-09
>> -0.000000011754943685104990000000 1.17549e-08
>> -0.000000117549433298336200000000 1.17549e-07
>> -0.000001175494389826781000000000 1.17549e-06
>> -0.000011754943443520460000000000 1.17549e-05
>> +0.000000000000001175494324749389 0.00000000000000117549
>> +0.000000000000011754943671010362 0.0000000000000117549
>> +0.000000000000117549429933840040 0.000000000000117549
>> +0.000000000001175494380653563400 0.00000000000117549
>> +0.000000000011754943372854765000 0.0000000000117549
>> +0.000000000117549428524377220000 0.000000000117549
>> +0.000000001175494368510499000000 0.00000000117549
>> +0.000000011754943685104990000000 0.0000000117549
>> +0.000000117549433298336230000000 0.000000117549
>> +0.000001175494389826781100000000 0.00000117549
>> +0.000011754943443520460000000000 0.0000117549
>> 0.000117549432616215200000000000 0.000117549
>> -0.001175494398921728000000000000 0.00117549
>> +0.001175494398921728100000000000 0.00117549
>> -0.011754943057894710000000000000 0.0117549
>> +0.011754943057894707000000000000 0.0117549
>> -0.117549434304237400000000000000 0.117549
>> +0.117549434304237370000000000000 0.117549
>
>Hm. Here we cast a *float* to a decimal. From the results
>it's clear that dtoa uses a double precision here.
>Could you fix it so that it would use correct precision ?
>
This is what WL #3977 is about. I have no idea how to fix this "locally". We
need float2decimal(), and then we need Field::val_float() and so on.
Best regards,
--
Alexey Kopytov, Software Developer
MySQL AB, www.mysql.com
Are you MySQL certified? www.mysql.com/certification