diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-03-18 08:44:24 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-03-18 08:44:24 +0100 |
commit | 8f607aae127439e132dae00b2750727162f4d564 (patch) | |
tree | 2a470ac1ca3ad8c0f9e782d9ed0edcaadf112538 | |
parent | 3827d70a0edb9b88f30dd64a2d7ee2853524dd4e (diff) | |
download | mariadb-git-8f607aae127439e132dae00b2750727162f4d564.tar.gz |
MDEV-4283 Assertion `scale <= precision' fails in strings/decimal.c
with decimals=NOT_FIXED_DEC it is possible to have 'decimals' larger
than 'max_length', it's not an error for temporal functions.
But when Item_func_numhybrid converts the value to DECIMAL_RESULT,
it must limit 'decimals' to be a valid scale of a decimal number.
-rw-r--r-- | mysql-test/r/temporal_scale_4283.result | 12 | ||||
-rw-r--r-- | mysql-test/t/temporal_scale_4283.test | 13 | ||||
-rw-r--r-- | sql/item_func.cc | 4 | ||||
-rw-r--r-- | sql/item_func.h | 7 |
4 files changed, 35 insertions, 1 deletions
diff --git a/mysql-test/r/temporal_scale_4283.result b/mysql-test/r/temporal_scale_4283.result new file mode 100644 index 00000000000..685a6192a97 --- /dev/null +++ b/mysql-test/r/temporal_scale_4283.result @@ -0,0 +1,12 @@ +create table t1 (a int); +insert into t1 values (4),(8); +select distinct 100 mod timestampadd( week, a, '2002-05-20' ) from t1; +100 mod timestampadd( week, a, '2002-05-20' ) +100 +drop table t1; +create table t1 (i int); +insert into t1 values (2),(4); +select distinct convert_tz( '2001-03-21', 'utc', 'met' ) mod i from t1; +convert_tz( '2001-03-21', 'utc', 'met' ) mod i +0 +drop table t1; diff --git a/mysql-test/t/temporal_scale_4283.test b/mysql-test/t/temporal_scale_4283.test new file mode 100644 index 00000000000..d79ca7caa54 --- /dev/null +++ b/mysql-test/t/temporal_scale_4283.test @@ -0,0 +1,13 @@ +# +# MDEV-4283 Assertion `scale <= precision' fails in strings/decimal.c +# +create table t1 (a int); +insert into t1 values (4),(8); +select distinct 100 mod timestampadd( week, a, '2002-05-20' ) from t1; +drop table t1; + +create table t1 (i int); +insert into t1 values (2),(4); +select distinct convert_tz( '2001-03-21', 'utc', 'met' ) mod i from t1; +drop table t1; + diff --git a/sql/item_func.cc b/sql/item_func.cc index f3a5c08d621..120e3d73a34 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -742,13 +742,14 @@ void Item_num_op::find_num_type(void) { hybrid_type= DECIMAL_RESULT; result_precision(); + fix_decimals(); } else { DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT); - decimals= 0; hybrid_type=INT_RESULT; result_precision(); + decimals= 0; } DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT ? "REAL_RESULT" : @@ -1492,6 +1493,7 @@ void Item_func_div::fix_length_and_dec() break; case DECIMAL_RESULT: result_precision(); + fix_decimals(); break; case STRING_RESULT: case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index 2db8ab76ffe..6cd036920f8 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -348,6 +348,13 @@ public: void fix_num_length_and_dec(); virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */ + inline void fix_decimals() + { + DBUG_ASSERT(result_type() == DECIMAL_RESULT); + if (decimals == NOT_FIXED_DEC) + set_if_smaller(decimals, max_length - 1); + } + double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); |