diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 6dc608a9289..66a1a26ee95 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -344,3 +344,6 @@ select cast(s1 as decimal(7,2)) from t1; cast(s1 as decimal(7,2)) 111111.00 drop table t1; +select cast(NULL as decimal(6)) as t1; +t1 +NULL diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index cafecd6000d..e7faf486ef0 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -168,3 +168,9 @@ create table t1(s1 time); insert into t1 values ('11:11:11'); select cast(s1 as decimal(7,2)) from t1; drop table t1; + +# +# Bug @10237 (CAST(NULL DECIMAL) crashes server) +# +select cast(NULL as decimal(6)) as t1; + diff --git a/sql/item_func.cc b/sql/item_func.cc index e9f35f5a2e8..4dc7e55f195 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1022,7 +1022,8 @@ longlong Item_func_unsigned::val_int() String *Item_decimal_typecast::val_str(String *str) { my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); - my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, &tmp_buf); + if (null_value) + return NULL; my_decimal2string(E_DEC_FATAL_ERROR, &tmp_buf, 0, 0, 0, str); return str; } @@ -1032,6 +1033,8 @@ double Item_decimal_typecast::val_real() { my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); double res; + if (null_value) + return 0.0; my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res); return res; } @@ -1041,6 +1044,8 @@ longlong Item_decimal_typecast::val_int() { my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); longlong res; + if (null_value) + return 0; my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res); return res; } @@ -1049,6 +1054,8 @@ 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); + if ((null_value= args[0]->null_value)) + return NULL; my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec); return dec; } diff --git a/strings/decimal.c b/strings/decimal.c index 8d07a84ede1..de64933466d 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1563,7 +1563,13 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, break; if (buf1-- == to->buf) { - decimal_make_zero(to); + /* making 'zero' with the proper scale */ + dec1 *p0= to->buf + frac0 + 1; + to->intg=1; + to->frac= max(scale, 0); + to->sign= 0; + for (buf1= to->buf; buf1