From 9ff0c9f730a79d4dab4303163d45c919f612cc37 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 20 Mar 2014 09:50:45 +0100 Subject: MDEV-5858 MySQL Bug#12744991 - DECIMAL_ROUND(X,D) GIVES WRONG RESULTS WHEN D == N*(-9) don't use mysql-5.6 change. correct fix: zero-out rounded tail after the number was shifted because of the carry digit (otherwise the carry digit will be zeroed out too). --- mysql-test/r/func_math.result | 15 +++++++++++++++ mysql-test/t/func_math.test | 9 +++++++++ strings/decimal.c | 37 +++++++++++++++++++------------------ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 23a1f1bc4b3..3631af8a22f 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -728,6 +728,21 @@ select (1.175494351E-37 div 1.7976931348623157E+308); Warnings: Warning 1916 Got overflow when converting '' to DECIMAL. Value truncated. # +# Bug#12744991 - DECIMAL_ROUND(X,D) GIVES WRONG RESULTS WHEN D == N*(-9) +# +select round(999999999, -9); +round(999999999, -9) +1000000000 +select round(999999999.0, -9); +round(999999999.0, -9) +1000000000 +select round(999999999999999999, -18); +round(999999999999999999, -18) +1000000000000000000 +select round(999999999999999999.0, -18); +round(999999999999999999.0, -18) +1000000000000000000 +# # Bug#12537160 ASSERTION FAILED: # STOP0 <= &TO->BUF[TO->LEN] WITH LARGE NUMBER. # diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 92ef362c32c..2998742dbcc 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -538,6 +538,15 @@ SELECT 1 div null; --echo # select (1.175494351E-37 div 1.7976931348623157E+308); +--echo # +--echo # Bug#12744991 - DECIMAL_ROUND(X,D) GIVES WRONG RESULTS WHEN D == N*(-9) +--echo # + +select round(999999999, -9); +select round(999999999.0, -9); +select round(999999999999999999, -18); +select round(999999999999999999.0, -18); + --echo # --echo # Bug#12537160 ASSERTION FAILED: --echo # STOP0 <= &TO->BUF[TO->LEN] WITH LARGE NUMBER. diff --git a/strings/decimal.c b/strings/decimal.c index 2156e095315..1b6ffbb110b 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1594,24 +1594,6 @@ decimal_round(const decimal_t *from, decimal_t *to, int scale, x+=10; *buf1=powers10[pos]*(x-y); } - /* - In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside - the buffer are as follows. - - Before <1, 5e8> - After <2, 5e8> - - Hence we need to set the 2nd field to 0. - The same holds if we round 1.5e-9 to 2e-9. - */ - if (frac0 < frac1) - { - dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0); - dec1 *end= to->buf + len; - - while (buf < end) - *buf++=0; - } if (*buf1 >= DIG_BASE) { carry=1; @@ -1633,6 +1615,7 @@ decimal_round(const decimal_t *from, decimal_t *to, int scale, } *buf1=1; to->intg++; + intg0++; } } else @@ -1654,6 +1637,24 @@ decimal_round(const decimal_t *from, decimal_t *to, int scale, } } } + /* + In case we're rounding e.g. 1.5e9 to 2.0e9, the decimal_digit_t's inside + the buffer are as follows. + + Before <1, 5e8> + After <2, 5e8> + + Hence we need to set the 2nd field to 0. + The same holds if we round 1.5e-9 to 2e-9. + */ + if (frac0 < frac1) + { + dec1 *buf= to->buf + ((scale == 0 && intg0 == 0) ? 1 : intg0 + frac0); + dec1 *end= to->buf + len; + + while (buf < end) + *buf++=0; + } /* Here we check 999.9 -> 1000 case when we need to increase intg */ first_dig= to->intg % DIG_PER_DEC1; -- cgit v1.2.1