diff options
-rw-r--r-- | include/decimal.h | 1 | ||||
-rw-r--r-- | mysql-test/r/cast.result | 8 | ||||
-rw-r--r-- | mysql-test/r/type_newdecimal.result | 27 | ||||
-rw-r--r-- | mysql-test/r/view.result | 2 | ||||
-rw-r--r-- | mysql-test/t/type_newdecimal.test | 11 | ||||
-rw-r--r-- | sql/item_create.cc | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 23 | ||||
-rw-r--r-- | sql/my_decimal.h | 8 | ||||
-rw-r--r-- | strings/decimal.c | 8 |
9 files changed, 85 insertions, 5 deletions
diff --git a/include/decimal.h b/include/decimal.h index 2648e04c1cf..3b4cafbfd26 100644 --- a/include/decimal.h +++ b/include/decimal.h @@ -48,6 +48,7 @@ int decimal_bin_size(int precision, int scale); int decimal_result_size(decimal_t *from1, decimal_t *from2, char op, int param); +int decimal_intg(decimal_t *from); int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to); int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to); int decimal_cmp(decimal_t *from1, decimal_t *from2); diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 5e8f5dca711..eb2d83e7be4 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -103,7 +103,7 @@ Warnings: Warning 1292 Truncated incorrect DOUBLE value: 'a' select 10.0+cast('a' as decimal); 10.0+cast('a' as decimal) -10.00 +10.0 Warnings: Warning 1292 Truncated incorrect DECIMAL value: 'a' select 10E+0+'a'; @@ -368,7 +368,9 @@ create table t1(s1 time); insert into t1 values ('11:11:11'); select cast(s1 as decimal(7,2)) from t1; cast(s1 as decimal(7,2)) -111111.00 +99999.99 +Warnings: +Error 1264 Out of range value for column 'cast(s1 as decimal(7,2))' at row 1 drop table t1; CREATE TABLE t1 (v varchar(10), tt tinytext, t text, mt mediumtext, lt longtext); @@ -376,7 +378,7 @@ INSERT INTO t1 VALUES ('1.01', '2.02', '3.03', '4.04', '5.05'); SELECT CAST(v AS DECIMAL), CAST(tt AS DECIMAL), CAST(t AS DECIMAL), CAST(mt AS DECIMAL), CAST(lt AS DECIMAL) from t1; CAST(v AS DECIMAL) CAST(tt AS DECIMAL) CAST(t AS DECIMAL) CAST(mt AS DECIMAL) CAST(lt AS DECIMAL) -1.01 2.02 3.03 4.04 5.05 +1 2 3 4 5 DROP TABLE t1; select cast(NULL as decimal(6)) as t1; t1 diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 9755083ab1c..95da4be6830 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1418,3 +1418,30 @@ i2 count(distinct j) 1.0 2 2.0 2 drop table t1; +select cast(143.481 as decimal(4,1)); +cast(143.481 as decimal(4,1)) +143.5 +select cast(143.481 as decimal(4,0)); +cast(143.481 as decimal(4,0)) +143 +select cast(143.481 as decimal(2,1)); +cast(143.481 as decimal(2,1)) +9.9 +Warnings: +Error 1264 Out of range value for column 'cast(143.481 as decimal(2,1))' at row 1 +select cast(-3.4 as decimal(2,1)); +cast(-3.4 as decimal(2,1)) +-3.4 +select cast(99.6 as decimal(2,0)); +cast(99.6 as decimal(2,0)) +99 +Warnings: +Error 1264 Out of range value for column 'cast(99.6 as decimal(2,0))' at row 1 +select cast(-13.4 as decimal(2,1)); +cast(-13.4 as decimal(2,1)) +-9.9 +Warnings: +Error 1264 Out of range value for column 'cast(-13.4 as decimal(2,1))' at row 1 +select cast(98.6 as decimal(2,0)); +cast(98.6 as decimal(2,0)) +99 diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 2de47f44556..4ef13a0f307 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1787,7 +1787,7 @@ drop table t1; create view v1 as select cast(1 as decimal); select * from v1; cast(1 as decimal) -1.00 +1 drop view v1; create table t1(f1 int); create table t2(f2 int); diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 7afdb857ca2..e877c6d2948 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1115,3 +1115,14 @@ insert into t1 values (1,1), (1,2), (2,3), (2,4); select i, count(distinct j) from t1 group by i; select i+0.0 as i2, count(distinct j) from t1 group by i2; drop table t1; + +# +# Bug#16172 DECIMAL data type processed incorrectly +# +select cast(143.481 as decimal(4,1)); +select cast(143.481 as decimal(4,0)); +select cast(143.481 as decimal(2,1)); +select cast(-3.4 as decimal(2,1)); +select cast(99.6 as decimal(2,0)); +select cast(-13.4 as decimal(2,1)); +select cast(98.6 as decimal(2,0)); diff --git a/sql/item_create.cc b/sql/item_create.cc index 7147142d8a7..e02ba384717 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -463,7 +463,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, case ITEM_CAST_TIME: res= new Item_time_typecast(a); break; case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break; case ITEM_CAST_DECIMAL: - res= new Item_decimal_typecast(a, (len>0) ? len : 10, dec ? dec : 2); + res= new Item_decimal_typecast(a, (len > 0) ? len : 10, dec); break; case ITEM_CAST_CHAR: res= new Item_char_typecast(a, len, cs ? cs : diff --git a/sql/item_func.cc b/sql/item_func.cc index e901eaf8654..250dec6ae57 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -955,9 +955,32 @@ longlong Item_decimal_typecast::val_int() my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec) { my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf); + bool sign; if ((null_value= args[0]->null_value)) return NULL; my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec); + sign= dec->sign(); + if (unsigned_flag) + { + if (sign) + { + my_decimal_set_zero(dec); + goto err; + } + } + if (max_length - 2 - decimals < (uint) my_decimal_intg(dec)) + { + max_my_decimal(dec, max_length - 2, decimals); + dec->sign(sign); + goto err; + } + return dec; + +err: + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_WARN_DATA_OUT_OF_RANGE, + ER(ER_WARN_DATA_OUT_OF_RANGE), + name, 1); return dec; } diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b02abacf0a3..3ce8cfee75d 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -383,5 +383,13 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b) return decimal_cmp((decimal_t*) a, (decimal_t*) b); } + +inline +int my_decimal_intg(const my_decimal *a) +{ + return decimal_intg((decimal_t*) a); +} + + #endif /*my_decimal_h*/ diff --git a/strings/decimal.c b/strings/decimal.c index 736dc2e57c4..4ff2b5a693a 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1896,6 +1896,14 @@ static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to) return error; } +int decimal_intg(decimal_t *from) +{ + int res; + dec1 *tmp_res; + tmp_res= remove_leading_zeroes(from, &res); + return res; +} + int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to) { if (likely(from1->sign == from2->sign)) |