diff options
-rw-r--r-- | mysql-test/r/type_newdecimal-big.result | 11 | ||||
-rw-r--r-- | mysql-test/r/type_newdecimal.result | 56 | ||||
-rw-r--r-- | mysql-test/t/type_newdecimal-big.test | 31 | ||||
-rw-r--r-- | mysql-test/t/type_newdecimal.test | 64 | ||||
-rw-r--r-- | sql/field.cc | 5 | ||||
-rw-r--r-- | sql/my_decimal.cc | 19 | ||||
-rw-r--r-- | strings/decimal.c | 14 |
7 files changed, 92 insertions, 108 deletions
diff --git a/mysql-test/r/type_newdecimal-big.result b/mysql-test/r/type_newdecimal-big.result new file mode 100644 index 00000000000..e95f2f3f781 --- /dev/null +++ b/mysql-test/r/type_newdecimal-big.result @@ -0,0 +1,11 @@ +drop procedure if exists sp1; +create procedure sp1 () begin +declare v1, v2, v3, v4 decimal(16,12); declare v5 int; +set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; +while v5 < 100000 do +set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; +end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// +call sp1()// +v1 v2 v3 * 0.000000000001 v4 * 0.000000000001 +1.000000100000 1.999999900000 1.000000100000 1.999999900000 +drop procedure sp1; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 7d7fe7efa35..938dccc864c 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -678,16 +678,6 @@ select -18.3=18.3; select 0.8 = 0.7 + 0.1; 0.8 = 0.7 + 0.1 1 -create procedure p1 () begin -declare v1, v2, v3, v4 decimal(16,12); declare v5 int; -set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; -while v5 < 100000 do -set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; -end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// -call p1()// -v1 v2 v3 * 0.000000000001 v4 * 0.000000000001 -1.000000100000 1.999999900000 1.000000100000 1.999999900000 -drop procedure p1; drop table if exists t1; Warnings: Note 1051 Unknown table 't1' @@ -1267,34 +1257,6 @@ CAST(my_varchar AS DECIMAL(65,30)) my_varchar 0.011754943450000000000000000000 1.175494345e-2 0.117549434500000000000000000000 1.175494345e-1 UPDATE t1 SET my_decimal = my_float; -Warnings: -Note 1265 Data truncated for column 'my_decimal' at row 1 -Note 1265 Data truncated for column 'my_decimal' at row 2 -Note 1265 Data truncated for column 'my_decimal' at row 3 -Note 1265 Data truncated for column 'my_decimal' at row 4 -Note 1265 Data truncated for column 'my_decimal' at row 5 -Note 1265 Data truncated for column 'my_decimal' at row 6 -Note 1265 Data truncated for column 'my_decimal' at row 7 -Note 1265 Data truncated for column 'my_decimal' at row 8 -Note 1265 Data truncated for column 'my_decimal' at row 9 -Note 1265 Data truncated for column 'my_decimal' at row 10 -Note 1265 Data truncated for column 'my_decimal' at row 11 -Note 1265 Data truncated for column 'my_decimal' at row 12 -Note 1265 Data truncated for column 'my_decimal' at row 13 -Note 1265 Data truncated for column 'my_decimal' at row 14 -Note 1265 Data truncated for column 'my_decimal' at row 15 -Note 1265 Data truncated for column 'my_decimal' at row 16 -Note 1265 Data truncated for column 'my_decimal' at row 17 -Note 1265 Data truncated for column 'my_decimal' at row 19 -Note 1265 Data truncated for column 'my_decimal' at row 20 -Note 1265 Data truncated for column 'my_decimal' at row 21 -Note 1265 Data truncated for column 'my_decimal' at row 22 -Note 1265 Data truncated for column 'my_decimal' at row 23 -Note 1265 Data truncated for column 'my_decimal' at row 26 -Note 1265 Data truncated for column 'my_decimal' at row 27 -Note 1265 Data truncated for column 'my_decimal' at row 30 -Note 1265 Data truncated for column 'my_decimal' at row 31 -Note 1265 Data truncated for column 'my_decimal' at row 32 SELECT my_decimal, my_float FROM t1; my_decimal my_float 0.000000000000000000000000000000 1.17549e-32 @@ -1330,24 +1292,6 @@ my_decimal my_float 0.011754943057894710000000000000 0.0117549 0.117549434304237400000000000000 0.117549 UPDATE t1 SET my_decimal = my_double; -Warnings: -Note 1265 Data truncated for column 'my_decimal' at row 1 -Note 1265 Data truncated for column 'my_decimal' at row 2 -Note 1265 Data truncated for column 'my_decimal' at row 3 -Note 1265 Data truncated for column 'my_decimal' at row 4 -Note 1265 Data truncated for column 'my_decimal' at row 5 -Note 1265 Data truncated for column 'my_decimal' at row 6 -Note 1265 Data truncated for column 'my_decimal' at row 7 -Note 1265 Data truncated for column 'my_decimal' at row 8 -Note 1265 Data truncated for column 'my_decimal' at row 9 -Note 1265 Data truncated for column 'my_decimal' at row 10 -Note 1265 Data truncated for column 'my_decimal' at row 11 -Note 1265 Data truncated for column 'my_decimal' at row 13 -Note 1265 Data truncated for column 'my_decimal' at row 14 -Note 1265 Data truncated for column 'my_decimal' at row 16 -Note 1265 Data truncated for column 'my_decimal' at row 18 -Note 1265 Data truncated for column 'my_decimal' at row 20 -Note 1265 Data truncated for column 'my_decimal' at row 31 SELECT my_decimal, my_double FROM t1; my_decimal my_double 0.000000000000000000000000000000 1.175494345e-32 diff --git a/mysql-test/t/type_newdecimal-big.test b/mysql-test/t/type_newdecimal-big.test new file mode 100644 index 00000000000..e200017f2ba --- /dev/null +++ b/mysql-test/t/type_newdecimal-big.test @@ -0,0 +1,31 @@ +--source include/big_test.inc + +--disable_warnings +drop procedure if exists sp1; +--enable_warnings + +# +#-- 2. Adding (one millionth) one million times should be the same as +#-- adding 1. So a stored procedure with many iterations will show if +#-- small errors accumulate. +# + +delimiter //; +# +create procedure sp1 () begin + declare v1, v2, v3, v4 decimal(16,12); declare v5 int; + set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; + while v5 < 100000 do + set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; + end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// +# +call sp1()// +#-- should return +# -- v1=1.0000001 +# -- v2=1.999999900000 +# -- v3=1.0000001 +# -- v4=1.999999900000 +# +delimiter ;// +# +drop procedure sp1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index ad71ffa02e5..e2fe9767432 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -473,7 +473,7 @@ drop table wl1612_4; # #-- Additional tests for WL#1612 Precision math # -#-- 1. Comparisons should show that a number is +#-- Comparisons should show that a number is #-- exactly equal to its value as displayed. # set sql_mode=''; @@ -487,34 +487,9 @@ select 18.3=18.3; select -18.3=18.3; # select 0.8 = 0.7 + 0.1; + # -#-- 2. Adding (one millionth) one million times should be the same as -#-- adding 1. So a stored procedure with many iterations will show if -#-- small errors accumulate. -# -#drop procedure p1; -# -delimiter //; -# -create procedure p1 () begin - declare v1, v2, v3, v4 decimal(16,12); declare v5 int; - set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; - while v5 < 100000 do - set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; - end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// -# -call p1()// -#-- should return -# -- v1=1.0000001 -# -- v2=1.999999900000 -# -- v3=1.0000001 -# -- v4=1.999999900000 -# -delimiter ;// -# -drop procedure p1; -# -#-- 3. It should be possible to define a column +#-- It should be possible to define a column #-- with up to 38 digits precision either before #-- or after the decimal point. Any number which #-- is inserted, if it's within the range, should @@ -565,7 +540,7 @@ select * from t1; # drop table t1; # -#-- 4. The usual arithmetic operators / * + - should work. +#-- The usual arithmetic operators / * + - should work. # #select 77777777777777777777777777777777777777 / 7777777777777777777777777777777777777 = 10; #-- should return 0 (false). @@ -668,7 +643,7 @@ select truncate(99999999999999999999999999999999999999,-31); #drop procedure p1; #drop table t1; # -#-- 7. When I say DECIMAL(x) I should be able to store x digits. +#-- When I say DECIMAL(x) I should be able to store x digits. #-- If I can't, there should be an error at CREATE time. # #drop table if exists t1; @@ -676,7 +651,8 @@ select truncate(99999999999999999999999999999999999999,-31); #create table t1 (col1 decimal(254)); #-- should return SQLSTATE 22003 numeric value out of range # -#-- 8. When I say DECIMAL(x,y) there should be no silent change of precision or scale. +#-- When I say DECIMAL(x,y) there should be no silent change of precision or +#-- scale. # #drop table if exists t1; # @@ -694,7 +670,7 @@ select truncate(99999999999999999999999999999999999999,-31); # #drop table t1; # -#-- 9. From WL#1612 "The future" point 2.: +#-- From WL#1612 "The future" point 2.: #-- The standard requires that we treat numbers like "0.5" as #-- DECIMAL or NUMERIC, not as floating-point. # @@ -715,7 +691,7 @@ show create table t1; # drop table t1; # -#-- 10. From WL#1612, "The future", point 3.: We have to start rounding correctly. +#-- From WL#1612, "The future", point 3.: We have to start rounding correctly. # select round(1.5),round(2.5); #-- should return: @@ -725,13 +701,13 @@ select round(1.5),round(2.5); #| 2 | 3 | #+------------+------------+ # -#-- 11. From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00. +#-- From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00. #-- If operand#1 has scale X and operand#2 has scale Y, then result should have scale (X+Y). # select 0.07 * 0.07; #-- should return 0.0049 # -#-- 12. From WL#1612, "The future", point 5.: Division by zero is an error. +#-- From WL#1612, "The future", point 5.: Division by zero is an error. # set sql_mode='traditional'; # @@ -752,7 +728,7 @@ select 1 / 0; #+-------+ #1 row in set, 1 warning (0.00 sec) # -#-- 13. From WL#1612 "The future" point 6.: Overflow is an error. +#-- From WL#1612 "The future" point 6.: Overflow is an error. # #set sql_mode=''; # @@ -793,7 +769,8 @@ select 1 / 0; #drop table t2; #drop table t1; # -#-- 15. From WL#1612 "The future" point 8.: Stop storing leading "+" signs and leading "0"s. +#-- From WL#1612 "The future" point 8.: Stop storing leading "+" signs and +# leading "0"s. # #drop table if exists t1; # @@ -805,7 +782,7 @@ select 1 / 0; # #drop table t1; # -#-- 16. From WL#1612, The future" point 9.: +#-- From WL#1612, The future" point 9.: #-- Accept the data type and precision and scale as the user #-- asks, or return an error, but don't change to something else. # @@ -817,7 +794,7 @@ select 1 / 0; # #drop table t1; # -#-- 17. The scripts in the following bugs should work: +#-- The scripts in the following bugs should work: # #BUG#559 Maximum precision for DECIMAL column ... @@ -833,7 +810,7 @@ select 1 / 0; #BUG#6048 Stored procedure causes operating system reboot #BUG#6053 DOUBLE PRECISION literal --- 18. Tests from 'traditional' mode tests +-- Tests from 'traditional' mode tests # set sql_mode='ansi,traditional'; # @@ -1077,10 +1054,17 @@ SELECT CAST(my_float AS DECIMAL(65,30)), my_float FROM t1; SELECT CAST(my_double AS DECIMAL(65,30)), my_double FROM t1; SELECT CAST(my_varchar AS DECIMAL(65,30)), my_varchar FROM t1; +# We have to disable warnings here as the test in +# Field_new_decimal::store(double): +# if (nr2 != nr) +# fails randomly depending on compiler options + +--disable_warnings UPDATE t1 SET my_decimal = my_float; SELECT my_decimal, my_float FROM t1; UPDATE t1 SET my_decimal = my_double; SELECT my_decimal, my_double FROM t1; +--enable_warnings UPDATE t1 SET my_decimal = my_varchar; SELECT my_decimal, my_varchar FROM t1; diff --git a/sql/field.cc b/sql/field.cc index 55d6bf7e3a2..dbc8d2a49d7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2384,7 +2384,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) #ifndef DBUG_OFF { char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; - DBUG_PRINT("info", ("saving with precision %d, scale: %d, value %s", + DBUG_PRINT("info", ("saving with precision %d scale: %d value %s", (int)precision, (int)dec, dbug_decimal_as_string(dbug_buff, decimal_value))); } @@ -2399,7 +2399,8 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec); error= 1; } - DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, bin_size);); + DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, + bin_size);); DBUG_RETURN(error); } diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 1bd16940b47..89607129026 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -193,16 +193,23 @@ int str2my_decimal(uint mask, const char *from, uint length, #ifndef DBUG_OFF /* routines for debugging print */ +#define DIG_PER_DEC1 9 +#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) + /* print decimal */ void print_decimal(const my_decimal *dec) { - fprintf(DBUG_FILE, - "\nDecimal: sign: %d intg: %d frac: %d \n\ -%09d,%09d,%09d,%09d,%09d,%09d,%09d,%09d\n", - dec->sign(), dec->intg, dec->frac, - dec->buf[0], dec->buf[1], dec->buf[2], dec->buf[3], - dec->buf[4], dec->buf[5], dec->buf[6], dec->buf[7]); + int i, end; + char buff[512], *pos; + pos= buff; + pos+= my_sprintf(buff, (buff, "Decimal: sign: %d intg: %d frac: %d { ", + dec->sign(), dec->intg, dec->frac)); + end= ROUND_UP(dec->frac)+ROUND_UP(dec->intg)-1; + for (i=0; i < end; i++) + pos+= my_sprintf(pos, (pos, "%09d, ", dec->buf[i])); + pos+= my_sprintf(pos, (pos, "%09d }\n", dec->buf[i])); + fputs(buff, DBUG_FILE); } diff --git a/strings/decimal.c b/strings/decimal.c index 0c1f03016e0..9cf4a281be2 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -972,12 +972,18 @@ int decimal2double(decimal_t *from, double *to) int double2decimal(double from, decimal_t *to) { /* TODO: fix it, when we'll have dtoa */ - char s[400], *end; - sprintf(s, "%.16G", from); - end= strend(s); - return string2decimal(s, to, &end); + char buff[400], *end; + int length, res; + DBUG_ENTER("double2decimal"); + length= my_sprintf(buff, (buff, "%.16G", from)); + DBUG_PRINT("info",("from: %g from_as_str: %s", from, buff)); + end= buff+length; + res= string2decimal(buff, to, &end); + DBUG_PRINT("exit", ("res: %d", res)); + DBUG_RETURN(res); } + static int ull2dec(ulonglong from, decimal_t *to) { int intg1, error=E_DEC_OK; |