diff options
author | hf@deer.(none) <> | 2005-10-15 21:57:32 +0500 |
---|---|---|
committer | hf@deer.(none) <> | 2005-10-15 21:57:32 +0500 |
commit | 3f76925d0670544b0e0be82fd7ef1ab39c285f7f (patch) | |
tree | d4f623548567a998d3362e8b80be5f13d0de8c08 | |
parent | a5c5b2c65841827444ffe8878b900e6d2b3f5781 (diff) | |
download | mariadb-git-3f76925d0670544b0e0be82fd7ef1ab39c285f7f.tar.gz |
Fix for bug #13573 (wrong data inserted for too big decimals)
-rw-r--r-- | mysql-test/r/type_newdecimal.result | 28 | ||||
-rw-r--r-- | mysql-test/t/type_newdecimal.test | 15 | ||||
-rw-r--r-- | sql/item_func.cc | 12 | ||||
-rw-r--r-- | sql/my_decimal.cc | 2 | ||||
-rw-r--r-- | sql/my_decimal.h | 60 |
5 files changed, 91 insertions, 26 deletions
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index be5e29ab662..a99e60e5780 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -846,15 +846,14 @@ select 0/0; NULL select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x; x -999999999999999999999999999999999999999999999999999999999999999999999999999999999 +99999999999999999999999999999999999999999999999999999999999999999 Warnings: Error 1292 Truncated incorrect DECIMAL value: '' select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x; x -NULL +100000000000000000000000000000000000000000000000000000000000000000 Warnings: Error 1292 Truncated incorrect DECIMAL value: '' -Error 1292 Truncated incorrect DECIMAL value: '' select 0.190287977636363637 + 0.040372670 * 0 - 0; 0.190287977636363637 + 0.040372670 * 0 - 0 0.190287977636363637 @@ -1019,3 +1018,26 @@ drop procedure wg2; select cast(@non_existing_user_var/2 as DECIMAL); cast(@non_existing_user_var/2 as DECIMAL) NULL +create table t1 (c1 decimal(64)); +insert into t1 values( +89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000); +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +insert into t1 values( +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +insert into t1 values(1e100); +Warnings: +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +select * from t1; +c1 +9999999999999999999999999999999999999999999999999999999999999999 +9999999999999999999999999999999999999999999999999999999999999999 +9999999999999999999999999999999999999999999999999999999999999999 +drop table t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 3f04aa931d2..bfebef6207a 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1044,3 +1044,18 @@ drop procedure wg2; # select cast(@non_existing_user_var/2 as DECIMAL); + + +# +# Bug #13573 (Wrong data inserted for too big values) +# + +create table t1 (c1 decimal(64)); +insert into t1 values( +89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000); +insert into t1 values( +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); +insert into t1 values(1e100); +select * from t1; +drop table t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index 491243e9de7..9e92049dea4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -972,8 +972,8 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) return 0; val2= args[1]->val_decimal(&value2); if (!(null_value= (args[1]->null_value || - my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1, - val2) > 1))) + (my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1, + val2) > 3)))) return decimal_value; return 0; } @@ -1045,8 +1045,8 @@ my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value) return 0; val2= args[1]->val_decimal(&value2); if (!(null_value= (args[1]->null_value || - my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1, - val2) > 1))) + (my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1, + val2) > 3)))) return decimal_value; return 0; } @@ -1083,8 +1083,8 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value) return 0; val2= args[1]->val_decimal(&value2); if (!(null_value= (args[1]->null_value || - my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1, - val2) > 1))) + (my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1, + val2) > 3)))) return decimal_value; return 0; } diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index f188d27ff78..1bd16940b47 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -185,7 +185,7 @@ int str2my_decimal(uint mask, const char *from, uint length, } } } - check_result(mask, err); + check_result_and_overflow(mask, err, decimal_value); return err; } diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b65e6aedaa2..b02abacf0a3 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -126,6 +126,19 @@ inline int decimal_operation_results(int result) } #endif /*MYSQL_CLIENT*/ +inline +void max_my_decimal(my_decimal *to, int precision, int frac) +{ + DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&& + (frac <= DECIMAL_MAX_SCALE)); + max_decimal(precision, frac, (decimal_t*) to); +} + +inline void max_internal_decimal(my_decimal *to) +{ + max_my_decimal(to, DECIMAL_MAX_PRECISION, 0); +} + inline int check_result(uint mask, int result) { if (result & mask) @@ -133,6 +146,18 @@ inline int check_result(uint mask, int result) return result; } +inline int check_result_and_overflow(uint mask, int result, my_decimal *val) +{ + if (check_result(mask, result) & E_DEC_OVERFLOW) + { + bool sign= val->sign(); + val->fix_buffer_pointer(); + max_internal_decimal(val); + val->sign(sign); + } + return result; +} + inline uint my_decimal_length_to_precision(uint length, uint scale, bool unsigned_flag) { @@ -256,7 +281,8 @@ int my_decimal2double(uint mask, const my_decimal *d, double *result) inline int str2my_decimal(uint mask, const char *str, my_decimal *d, char **end) { - return check_result(mask, string2decimal(str, (decimal_t*) d, end)); + return check_result_and_overflow(mask, string2decimal(str,(decimal_t*)d,end), + d); } @@ -274,7 +300,7 @@ int string2my_decimal(uint mask, const String *str, my_decimal *d) inline int double2my_decimal(uint mask, double val, my_decimal *d) { - return check_result(mask, double2decimal(val, (decimal_t*) d)); + return check_result_and_overflow(mask, double2decimal(val, (decimal_t*)d), d); } @@ -303,7 +329,9 @@ inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_add((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_add((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -311,7 +339,9 @@ inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_sub((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_sub((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -319,7 +349,9 @@ inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mul((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_mul((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -327,8 +359,10 @@ inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc) { - return check_result(mask, decimal_div((decimal_t*) a, (decimal_t*) b, res, - div_scale_inc)); + return check_result_and_overflow(mask, + decimal_div((decimal_t*)a,(decimal_t*)b,res, + div_scale_inc), + res); } @@ -336,7 +370,9 @@ inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b) { - return check_result(mask, decimal_mod((decimal_t*) a, (decimal_t*) b, res)); + return check_result_and_overflow(mask, + decimal_mod((decimal_t*)a,(decimal_t*)b,res), + res); } @@ -347,13 +383,5 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b) return decimal_cmp((decimal_t*) a, (decimal_t*) b); } -inline -void max_my_decimal(my_decimal *to, int precision, int frac) -{ - DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&& - (frac <= DECIMAL_MAX_SCALE)); - max_decimal(precision, frac, (decimal_t*) to); -} - #endif /*my_decimal_h*/ |