diff options
-rw-r--r-- | mysql-test/r/func_str.result | 36 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 39 | ||||
-rw-r--r-- | strings/dtoa.c | 49 |
3 files changed, 111 insertions, 13 deletions
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index abf76a533b3..adaa2df3a61 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2826,5 +2826,41 @@ SELECT ((0xf3) * (rpad(1.0,2048,1)) << (0xcc)); ((0xf3) * (rpad(1.0,2048,1)) << (0xcc)) 0 # +# Bug#13359121 LARGE NUMBERS, /STRINGS/DTOA.C:662: +# BALLOC: ASSERTION `K <= 15' FAILED. +# Bug#12985021 SIMPLE QUERY WITH DECIMAL NUMBERS TAKE AN +# EXTRAORDINARY LONG TIME TO EXECUTE +SELECT @tmp_max:= @@global.max_allowed_packet; +@tmp_max:= @@global.max_allowed_packet +1048576 +SET @@global.max_allowed_packet=1024*1024*1024; +SELECT @@global.max_allowed_packet; +@@global.max_allowed_packet +1073741824 +do +format(rpad('111111111.1', +1111111, +'999999999999999999999999999999999999999999'),0,'be_BY') +; +DO +round( +concat( ( +coalesce( ( +linefromwkb('2147483648', +-b'1111111111111111111111111111111111111111111')), +( convert('[.DC2.]',decimal(30,30)) ), +bit_count('') +) ), +( lpad( ( elt('01','}:K5')), +sha1('P'), +( ( select '-9223372036854775808.1' > all (select ''))) +) +) +) +); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '[.DC2.]' +SET @@global.max_allowed_packet:= @tmp_max; +# # End of 5.5 tests # diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 083ed396527..27e196e5b0c 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1459,6 +1459,45 @@ SELECT stddev_samp(rpad(1.0,2048,1)); SELECT ((127.1) not in ((rpad(1.0,2048,1)),(''),(-1.1))); SELECT ((0xf3) * (rpad(1.0,2048,1)) << (0xcc)); +--echo # +--echo # Bug#13359121 LARGE NUMBERS, /STRINGS/DTOA.C:662: +--echo # BALLOC: ASSERTION `K <= 15' FAILED. +--echo # Bug#12985021 SIMPLE QUERY WITH DECIMAL NUMBERS TAKE AN +--echo # EXTRAORDINARY LONG TIME TO EXECUTE + +SELECT @tmp_max:= @@global.max_allowed_packet; +SET @@global.max_allowed_packet=1024*1024*1024; +# switching connection to allow the new max_allowed_packet take effect +--connect (newconn, localhost, root,,) + +SELECT @@global.max_allowed_packet; + +do +format(rpad('111111111.1', + 1111111, + '999999999999999999999999999999999999999999'),0,'be_BY') +; + +DO +round( + concat( ( + coalesce( ( + linefromwkb('2147483648', + -b'1111111111111111111111111111111111111111111')), + ( convert('[.DC2.]',decimal(30,30)) ), + bit_count('') + ) ), + ( lpad( ( elt('01','}:K5')), + sha1('P'), + ( ( select '-9223372036854775808.1' > all (select ''))) + ) + ) + ) +); + +--connection default +SET @@global.max_allowed_packet:= @tmp_max; +--disconnect newconn --echo # --echo # End of 5.5 tests diff --git a/strings/dtoa.c b/strings/dtoa.c index f7c38b2420d..2f4749ac171 100644 --- a/strings/dtoa.c +++ b/strings/dtoa.c @@ -783,7 +783,20 @@ static Bigint *multadd(Bigint *b, int m, int a, Stack_alloc *alloc) return b; } - +/** + Converts a string to Bigint. + + Now we have nd0 digits, starting at s, followed by a + decimal point, followed by nd-nd0 digits. + Unless nd0 == nd, in which case we have a number of the form: + ".xxxxxx" or "xxxxxx." + + @param s Input string, already partially parsed by my_strtod_int(). + @param nd0 Number of digits before decimal point. + @param nd Total number of digits. + @param y9 Pre-computed value of the first nine digits. + @param alloc Stack allocator for Bigints. + */ static Bigint *s2b(const char *s, int nd0, int nd, ULong y9, Stack_alloc *alloc) { Bigint *b; @@ -803,10 +816,11 @@ static Bigint *s2b(const char *s, int nd0, int nd, ULong y9, Stack_alloc *alloc) do b= multadd(b, 10, *s++ - '0', alloc); while (++i < nd0); - s++; + s++; /* skip '.' */ } else s+= 10; + /* now do the fractional part */ for(; i < nd; i++) b= multadd(b, 10, *s++ - '0', alloc); return b; @@ -1416,20 +1430,29 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s for (; s < end && c >= '0' && c <= '9'; c = *++s) { have_dig: - nz++; - if (c-= '0') + /* + Here we are parsing the fractional part. + We can stop counting digits after a while: the extra digits + will not contribute to the actual result produced by s2b(). + We have to continue scanning, in case there is an exponent part. + */ + if (nd < 2 * DBL_DIG) { - nf+= nz; - for (i= 1; i < nz; i++) + nz++; + if (c-= '0') + { + nf+= nz; + for (i= 1; i < nz; i++) + if (nd++ < 9) + y*= 10; + else if (nd <= DBL_DIG + 1) + z*= 10; if (nd++ < 9) - y*= 10; + y= 10*y + c; else if (nd <= DBL_DIG + 1) - z*= 10; - if (nd++ < 9) - y= 10*y + c; - else if (nd <= DBL_DIG + 1) - z= 10*z + c; - nz= 0; + z= 10*z + c; + nz= 0; + } } } } |