List:Commits« Previous MessageNext Message »
From:Sergei Golubchik Date:July 26 2007 12:19pm
Subject:Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860
View as plain text  
Hi!

The review below is incomplete, I didn't review dtoa.c itself.
Still there're some problems, see below.

On Jul 10, Alexey Kopytov wrote:
> ChangeSet@stripped, 2007-07-10 17:37:30+04:00, kaa@stripped +43 -0
>   WL #2934 "Make/find library for doing float/double to string conversions and vice
> versa"
>   Initial import of the dtoa.c code and custom wrappers around it to allow its usage
> from the server code.
>   
>   This patch also fixes the following bugs:
>   - bug #12860 "Difference in zero padding of exponent between Unix and Windows"
>   - bug #21497 "DOUBLE truncated to unusable value"
>   - bug #26788 "mysqld (debug) aborts when inserting specific numbers into char
> fields"
>   - bug #24541 "Data truncated..." on decimal type columns without any good reason"

All my comments could be sorted in a few categories:

1. few minor suggestions how to clarify/simplify the code
2. few unfortunate places (in mysql-test) where old code was giving more
   adequate results. It would be nice if these cases of excessive
   precision could be fixed.
3. few places where old code was correct and the new is not (incl. a
   direct violation of SQL standard) - it's a bug that must be fixed.
4. a number-to-decimal conversion that was bad in the old code too,
   but could be improved in this patch.

The main issue is #3.

> --- 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 ?

> +  (+ 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

> +
>  
>  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 ?

>    if (length > field_length)
>    {
> @@ -3847,64 +3831,16 @@ String *Field_float::val_str(String *val
>    char *to=(char*) val_buffer->ptr();
>  
>    if (dec >= NOT_FIXED_DEC)
> -  {
> -    sprintf(to,"%-*.*g",(int) field_length,FLT_DIG,nr);
> -    to=strcend(to,' ');
> -    *to=0;
> -  }
> +    my_gcvt(nr, MY_GCVT_ARG_FLOAT, to_length - 1, to, &to);
>    else
>    {
> +    /*
> +      We are safe here because the buffer length is >= 70, and
> +      fabs(float) < 10^39, dec < NOT_FIXED_DEC. So the resulting string
> +      will be not longer than 69 chars + terminating '\0'.
> +    */

good comment, thanks

> +    my_fcvt(nr, dec, to, &to);
> +  }
> -#ifdef HAVE_FCONVERT
> -    char buff[70],*pos=buff;
> -    int decpt,sign,tmp_dec=dec;
> -
> -    VOID(sfconvert(&nr,tmp_dec,&decpt,&sign,buff));
> -    if (sign)
> -    {
> -      *to++='-';
> -    }
> -    if (decpt < 0)
> -    {					/* val_buffer is < 0 */
> -      *to++='0';
> -      if (!tmp_dec)
> @@ -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.
2. wouldn't it be better to do it after checks for max_value, not before ?

>    }
>    
>    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.

> +  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 ?

> +
>  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

>  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

>  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	Extra
>  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 ?

>  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

> ---replace_result (-1.79769313486232e+308) (RES) (NULL) (RES)
> +--replace_result (-1.7976931348623157e308) (RES) (NULL) (RES)
>  --exec $MYSQL_DUMP --compact test t1
>  DROP TABLE t1;
>  
> --- 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.

>  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.) 

>  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.

> +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

>  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

>  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 ?

>  SELECT CAST(my_double  AS DECIMAL(65,30)), my_double FROM t1;
>  CAST(my_double  AS DECIMAL(65,30))	my_double
 
Regards / Mit vielen Grüssen,
Sergei

-- 
   __  ___     ___ ____  __
  /  |/  /_ __/ __/ __ \/ /   Sergei Golubchik <serg@stripped>
 / /|_/ / // /\ \/ /_/ / /__  Principal Software Developer
/_/  /_/\_, /___/\___\_\___/  MySQL GmbH, Radlkoferstr. 2, D-81373 München
       <___/                  Geschäftsführer: Kaj Arnö - HRB
München 162140
Thread
bk commit into 5.1 tree (kaa:1.2521) BUG#12860Alexey Kopytov10 Jul
  • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Sergei Golubchik26 Jul
    • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Alexey Kopytov10 Sep
      • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Sergei Golubchik1 Oct
        • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Alexey Kopytov29 Nov