summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhf@deer.(none) <>2005-10-15 21:57:32 +0500
committerhf@deer.(none) <>2005-10-15 21:57:32 +0500
commit3f76925d0670544b0e0be82fd7ef1ab39c285f7f (patch)
treed4f623548567a998d3362e8b80be5f13d0de8c08
parenta5c5b2c65841827444ffe8878b900e6d2b3f5781 (diff)
downloadmariadb-git-3f76925d0670544b0e0be82fd7ef1ab39c285f7f.tar.gz
Fix for bug #13573 (wrong data inserted for too big decimals)
-rw-r--r--mysql-test/r/type_newdecimal.result28
-rw-r--r--mysql-test/t/type_newdecimal.test15
-rw-r--r--sql/item_func.cc12
-rw-r--r--sql/my_decimal.cc2
-rw-r--r--sql/my_decimal.h60
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*/