From: Date: July 3 2009 12:37pm Subject: bzr commit into mysql-5.1-bugteam branch (Alexey.Kopytov:2973) List-Archive: http://lists.mysql.com/commits/77875 Message-Id: <20090703103713.69E6C51AF@kaamos.local> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_8dkAK6Y7pvC4oasl2UBNww)" --Boundary_(ID_8dkAK6Y7pvC4oasl2UBNww) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///data/src/bzr/bugteam/bug45262/my51-bug45262/ based on revid:aelkin@stripped 2973 Alexey Kopytov 2009-07-03 [merge] Manual merge. modified: mysql-test/r/type_newdecimal.result mysql-test/t/type_newdecimal.test sql/item.cc sql/item_cmpfunc.cc sql/item_func.cc sql/item_func.h sql/item_sum.cc sql/my_decimal.h sql/sql_select.cc === modified file 'mysql-test/r/type_newdecimal.result' --- a/mysql-test/r/type_newdecimal.result 2008-11-18 09:52:03 +0000 +++ b/mysql-test/r/type_newdecimal.result 2009-07-03 10:36:04 +0000 @@ -1524,10 +1524,10 @@ Warnings: Warning 1264 Out of range value for column 'f1' at row 1 DESC t1; Field Type Null Key Default Extra -f1 decimal(59,30) NO 0.000000000000000000000000000000 +f1 decimal(65,30) NO 0.000000000000000000000000000000 SELECT f1 FROM t1; f1 -99999999999999999999999999999.999999999999999999999999999999 +99999999999999999999999999999999999.999999999999999999999999999999 DROP TABLE t1; select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * 1.01500000 * 1.01500000 * 0.99500000); @@ -1577,3 +1577,56 @@ Error 1264 Out of range value for column select cast(98.6 as decimal(2,0)); cast(98.6 as decimal(2,0)) 99 +# +# Bug #45262: Bad effects with CREATE TABLE and DECIMAL +# +CREATE TABLE t1 SELECT .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +Warnings: +Note 1265 Data truncated for column 'my_col' at row 1 +DESCRIBE t1; +Field Type Null Key Default Extra +my_col decimal(30,30) NO 0.000000000000000000000000000000 +SELECT my_col FROM t1; +my_col +0.123456789123456789123456789123 +DROP TABLE t1; +CREATE TABLE t1 SELECT 1 + .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +Warnings: +Note 1265 Data truncated for column 'my_col' at row 1 +DESCRIBE t1; +Field Type Null Key Default Extra +my_col decimal(65,30) NO 0.000000000000000000000000000000 +SELECT my_col FROM t1; +my_col +1.123456789123456789123456789123 +DROP TABLE t1; +CREATE TABLE t1 SELECT 1 * .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +Warnings: +Note 1265 Data truncated for column 'my_col' at row 1 +DESCRIBE t1; +Field Type Null Key Default Extra +my_col decimal(65,30) NO 0.000000000000000000000000000000 +SELECT my_col FROM t1; +my_col +0.123456789123456789123456789123 +DROP TABLE t1; +CREATE TABLE t1 SELECT 1 / .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +Warnings: +Note 1265 Data truncated for column 'my_col' at row 1 +DESCRIBE t1; +Field Type Null Key Default Extra +my_col decimal(65,4) YES NULL +SELECT my_col FROM t1; +my_col +8.1000 +DROP TABLE t1; +CREATE TABLE t1 SELECT 1 % .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +Warnings: +Note 1265 Data truncated for column 'my_col' at row 1 +DESCRIBE t1; +Field Type Null Key Default Extra +my_col decimal(65,30) YES NULL +SELECT my_col FROM t1; +my_col +0.012345687012345687012345687012 +DROP TABLE t1; === modified file 'mysql-test/t/type_newdecimal.test' --- a/mysql-test/t/type_newdecimal.test 2008-11-17 15:43:10 +0000 +++ b/mysql-test/t/type_newdecimal.test 2009-07-03 10:36:04 +0000 @@ -1257,3 +1257,32 @@ 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)); + +--echo # +--echo # Bug #45262: Bad effects with CREATE TABLE and DECIMAL +--echo # + +CREATE TABLE t1 SELECT .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +DESCRIBE t1; +SELECT my_col FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT 1 + .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +DESCRIBE t1; +SELECT my_col FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT 1 * .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +DESCRIBE t1; +SELECT my_col FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT 1 / .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +DESCRIBE t1; +SELECT my_col FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT 1 % .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS my_col; +DESCRIBE t1; +SELECT my_col FROM t1; +DROP TABLE t1; === modified file 'sql/item.cc' --- a/sql/item.cc 2009-06-17 14:56:44 +0000 +++ b/sql/item.cc 2009-07-03 10:36:04 +0000 @@ -2260,8 +2260,10 @@ Item_decimal::Item_decimal(const char *s name= (char*) str_arg; decimals= (uint8) decimal_value.frac; fixed= 1; - max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, - decimals, unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + + decimals, + decimals, + unsigned_flag); } Item_decimal::Item_decimal(longlong val, bool unsig) @@ -2269,8 +2271,10 @@ Item_decimal::Item_decimal(longlong val, int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value); decimals= (uint8) decimal_value.frac; fixed= 1; - max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, - decimals, unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + + decimals, + decimals, + unsigned_flag); } @@ -2279,8 +2283,10 @@ Item_decimal::Item_decimal(double val, i double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value); decimals= (uint8) decimal_value.frac; fixed= 1; - max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, - decimals, unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + + decimals, + decimals, + unsigned_flag); } @@ -2300,8 +2306,10 @@ Item_decimal::Item_decimal(my_decimal *v my_decimal2decimal(value_par, &decimal_value); decimals= (uint8) decimal_value.frac; fixed= 1; - max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, - decimals, unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + + decimals, + decimals, + unsigned_flag); } @@ -2311,8 +2319,8 @@ Item_decimal::Item_decimal(const uchar * &decimal_value, precision, scale); decimals= (uint8) decimal_value.frac; fixed= 1; - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, + unsigned_flag); } @@ -2367,8 +2375,10 @@ void Item_decimal::set_decimal_value(my_ my_decimal2decimal(value_par, &decimal_value); decimals= (uint8) decimal_value.frac; unsigned_flag= !decimal_value.sign(); - max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, - decimals, unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + + decimals, + decimals, + unsigned_flag); } @@ -2640,8 +2650,9 @@ void Item_param::set_decimal(const char str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end); state= DECIMAL_VALUE; decimals= decimal_value.frac; - max_length= my_decimal_precision_to_length(decimal_value.precision(), - decimals, unsigned_flag); + max_length= + my_decimal_precision_to_length_no_truncation(decimal_value.precision(), + decimals, unsigned_flag); maybe_null= 0; DBUG_VOID_RETURN; } @@ -2797,8 +2808,9 @@ bool Item_param::set_from_user_var(THD * my_decimal2decimal(ent_value, &decimal_value); state= DECIMAL_VALUE; decimals= ent_value->frac; - max_length= my_decimal_precision_to_length(ent_value->precision(), - decimals, unsigned_flag); + max_length= + my_decimal_precision_to_length_no_truncation(ent_value->precision(), + decimals, unsigned_flag); item_type= Item::DECIMAL_ITEM; break; } @@ -7290,8 +7302,9 @@ bool Item_type_holder::join_types(THD *t int item_prec = max(prev_decimal_int_part, item_int_part) + decimals; int precision= min(item_prec, DECIMAL_MAX_PRECISION); unsigned_flag&= item->unsigned_flag; - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, + decimals, + unsigned_flag); } switch (Field::result_merge_type(fld_type)) === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2009-06-09 16:44:26 +0000 +++ b/sql/item_cmpfunc.cc 2009-07-03 10:36:04 +0000 @@ -2760,8 +2760,9 @@ void Item_func_case::fix_length_and_dec( agg_num_lengths(args[i + 1]); if (else_expr_num != -1) agg_num_lengths(args[else_expr_num]); - max_length= my_decimal_precision_to_length(max_length + decimals, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(max_length + + decimals, decimals, + unsigned_flag); } } === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2009-06-09 16:44:26 +0000 +++ b/sql/item_func.cc 2009-07-03 10:36:04 +0000 @@ -452,11 +452,45 @@ Field *Item_func::tmp_table_field(TABLE return make_string_field(table); break; case DECIMAL_RESULT: - field= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(), - decimals, - unsigned_flag), - maybe_null, name, decimals, unsigned_flag); + { + uint8 dec= decimals; + uint8 intg= decimal_precision() - dec; + uint32 len= max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + + field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be chosen @@ -545,8 +579,8 @@ void Item_func::count_decimal_length() set_if_smaller(unsigned_flag, args[i]->unsigned_flag); } int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION); - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, + unsigned_flag); } @@ -1141,16 +1175,15 @@ void Item_func_additive_op::result_preci decimals= max(args[0]->decimals, args[1]->decimals); int arg1_int= args[0]->decimal_precision() - args[0]->decimals; int arg2_int= args[1]->decimal_precision() - args[1]->decimals; - int est_prec= max(arg1_int, arg2_int) + 1 + decimals; - int precision= min(est_prec, DECIMAL_MAX_PRECISION); + int precision= max(arg1_int, arg2_int) + 1 + decimals; /* Integer operations keep unsigned_flag if one of arguments is unsigned */ if (result_type() == INT_RESULT) unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag; else unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag; - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, + unsigned_flag); } @@ -1255,7 +1288,8 @@ void Item_func_mul::result_precision() decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE); uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision(); uint precision= min(est_prec, DECIMAL_MAX_PRECISION); - max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, + unsigned_flag); } @@ -1311,8 +1345,8 @@ void Item_func_div::result_precision() else unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag; decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE); - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, + unsigned_flag); } @@ -1999,8 +2033,9 @@ void Item_func_round::fix_length_and_dec precision-= decimals_delta - length_increase; decimals= min(decimals_to_set, DECIMAL_MAX_SCALE); - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, + decimals, + unsigned_flag); break; } default: @@ -2243,8 +2278,9 @@ void Item_func_min_max::fix_length_and_d } } else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT)) - max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(max_int_part + + decimals, decimals, + unsigned_flag); cached_field_type= agg_field_type(args, arg_count); } === modified file 'sql/item_func.h' --- a/sql/item_func.h 2009-05-21 20:22:46 +0000 +++ b/sql/item_func.h 2009-07-03 10:36:04 +0000 @@ -378,7 +378,8 @@ public: Item_decimal_typecast(Item *a, int len, int dec) :Item_func(a) { decimals= dec; - max_length= my_decimal_precision_to_length(len, dec, unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(len, dec, + unsigned_flag); } String *val_str(String *str); double val_real(); === modified file 'sql/item_sum.cc' --- a/sql/item_sum.cc 2009-06-15 15:57:06 +0000 +++ b/sql/item_sum.cc 2009-07-03 10:36:04 +0000 @@ -798,8 +798,9 @@ void Item_sum_sum::fix_length_and_dec() { /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */ int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS; - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, + decimals, + unsigned_flag); curr_dec_buff= 0; hybrid_type= DECIMAL_RESULT; my_decimal_set_zero(dec_buffs); @@ -1233,8 +1234,9 @@ void Item_sum_avg::fix_length_and_dec() { int precision= args[0]->decimal_precision() + prec_increment; decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE); - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, + decimals, + unsigned_flag); f_precision= min(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION); f_scale= args[0]->decimals; dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale); @@ -1439,8 +1441,9 @@ void Item_sum_variance::fix_length_and_d { int precision= args[0]->decimal_precision()*2 + prec_increment; decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE); - max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + max_length= my_decimal_precision_to_length_no_truncation(precision, + decimals, + unsigned_flag); break; } === modified file 'sql/my_decimal.h' --- a/sql/my_decimal.h 2008-05-20 07:38:17 +0000 +++ b/sql/my_decimal.h 2009-07-03 10:36:04 +0000 @@ -183,6 +183,19 @@ inline uint my_decimal_length_to_precisi (unsigned_flag || !length ? 0:1)); } +inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, + uint8 scale, + bool unsigned_flag) +{ + /* + When precision is 0 it means that original length was also 0. Thus + unsigned_flag is ignored in this case. + */ + DBUG_ASSERT(precision || !scale); + return (uint32)(precision + (scale > 0 ? 1 : 0) + + (unsigned_flag || !precision ? 0 : 1)); +} + inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, bool unsigned_flag) { @@ -192,8 +205,8 @@ inline uint32 my_decimal_precision_to_le */ DBUG_ASSERT(precision || !scale); set_if_smaller(precision, DECIMAL_MAX_PRECISION); - return (uint32)(precision + (scale>0 ? 1:0) + - (unsigned_flag || !precision ? 0:1)); + return my_decimal_precision_to_length_no_truncation(precision, scale, + unsigned_flag); } inline === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2009-06-17 14:56:44 +0000 +++ b/sql/sql_select.cc 2009-07-03 10:36:04 +0000 @@ -9392,13 +9392,17 @@ static Field *create_tmp_field_from_item +1: for decimal point */ - overflow= my_decimal_precision_to_length(intg + dec, dec, - item->unsigned_flag) - len; + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + item->unsigned_flag); + + overflow= required_length - len; if (overflow > 0) dec= max(0, dec - overflow); // too long, discard fract else - len -= item->decimals - dec; // corrected value fits + /* Corrected value fits. */ + len= required_length; } new_field= new Field_new_decimal(len, maybe_null, item->name, --Boundary_(ID_8dkAK6Y7pvC4oasl2UBNww) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name="bzr/alexey.kopytov@stripped" Content-transfer-encoding: 7BIT Content-disposition: inline; filename="bzr/alexey.kopytov@stripped" # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: alexey.kopytov@stripped # target_branch: file:///data/src/bzr/bugteam/bug45262/my51-bug45262/ # testament_sha1: bcdac6253bbcfe639e12426d434ecc10ffe0dd86 # timestamp: 2009-07-03 14:37:13 +0400 # source_branch: file:///data/src/bzr/bugteam/bug45262/my50-bug45262/ # base_revision_id: aelkin@stripped # # Begin bundle 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 Dwf/xdyRThQkJiFb0kA= --Boundary_(ID_8dkAK6Y7pvC4oasl2UBNww)--