Commit 4172d5e9 authored by Tor Didriksen's avatar Tor Didriksen

Bug#13359121 LARGE NUMBERS, /STRINGS/DTOA.C:662

Bug#12985021 SIMPLE QUERY WITH DECIMAL NUMBERS TAKE AN

When parsing the fractional part of a string which
is to be converted to double, we can stop after a few digits:
the extra digits will not contribute to the actual result anyways.


mysql-test/r/func_str.result:
  New tests.
mysql-test/t/func_str.test:
  New tests.
strings/dtoa.c:
  The problem was s2b() multiplying and adding hundreds-of-thousands
  of ever smaller fractions.
parent c7964159
......@@ -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
#
......@@ -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
......
......@@ -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,6 +1430,14 @@ 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:
/*
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)
{
nz++;
if (c-= '0')
{
......@@ -1433,6 +1455,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
}
}
}
}
dig_done:
e= 0;
if (s < end && (c == 'e' || c == 'E'))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment