From: Date: July 3 2009 12:40pm Subject: bzr commit into mysql-pe branch (Alexey.Kopytov:3391) List-Archive: http://lists.mysql.com/commits/77876 Message-Id: <20090703104008.8062151AF@kaamos.local> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_InM/d6+sVeFZSeROkkSukA)" --Boundary_(ID_InM/d6+sVeFZSeROkkSukA) 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/my60-bug45262/ based on revid:aelkin@stripped 3391 Alexey Kopytov 2009-07-03 [merge] Automerge. 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 10:04:27 +0000 +++ b/mysql-test/r/type_newdecimal.result 2009-07-03 10:39:01 +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 @@ Warning 1264 Out of range value for colu 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:47:38 +0000 +++ b/mysql-test/t/type_newdecimal.test 2009-07-03 10:39:01 +0000 @@ -1255,3 +1255,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 15:26:50 +0000 +++ b/sql/item.cc 2009-07-03 10:39:01 +0000 @@ -2316,8 +2316,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) @@ -2325,8 +2327,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); } @@ -2335,8 +2339,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); } @@ -2356,8 +2362,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); } @@ -2367,8 +2375,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); } @@ -2423,8 +2431,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); } @@ -2697,8 +2707,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; } @@ -2865,8 +2876,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; } @@ -7533,8 +7545,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:53:34 +0000 +++ b/sql/item_cmpfunc.cc 2009-07-03 10:39:01 +0000 @@ -2825,8 +2825,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:53:34 +0000 +++ b/sql/item_func.cc 2009-07-03 10:39:01 +0000 @@ -476,11 +476,45 @@ Field *Item_func::tmp_table_field(TABLE case STRING_RESULT: return make_string_field(table); 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 @@ -563,8 +597,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); } @@ -1159,16 +1193,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); } @@ -1273,7 +1306,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); } @@ -1329,8 +1363,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); } @@ -2051,8 +2085,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: @@ -2295,8 +2330,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:27:17 +0000 +++ b/sql/item_func.h 2009-07-03 10:39:01 +0000 @@ -377,7 +377,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 16:18:14 +0000 +++ b/sql/item_sum.cc 2009-07-03 10:39:01 +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); @@ -1244,8 +1245,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); @@ -1450,8 +1452,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 15:26:50 +0000 +++ b/sql/sql_select.cc 2009-07-03 10:39:01 +0000 @@ -13786,13 +13786,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_InM/d6+sVeFZSeROkkSukA) 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/my60-bug45262/ # testament_sha1: 16a0591ad9c32b7379d9ad625ef166231b094c1d # timestamp: 2009-07-03 14:40:08 +0400 # source_branch: file:///data/src/bzr/bugteam/bug45262/my51-bug45262/ # base_revision_id: aelkin@stripped # # Begin bundle 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 5MlOX/4u5IpwoSAoKrKK --Boundary_(ID_InM/d6+sVeFZSeROkkSukA)--