From: Date: July 3 2009 12:51pm Subject: bzr push into mysql-pe branch (Alexey.Kopytov:3426 to 3428) List-Archive: http://lists.mysql.com/commits/77883 Message-Id: <20090703105151.AA9FD51AF@kaamos.local> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_ngZ8vFTCOUdZ5uhpHzsvSw)" --Boundary_(ID_ngZ8vFTCOUdZ5uhpHzsvSw) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline 3428 Alexey Kopytov 2009-07-03 [merge] Automerge. 3427 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 3426 Sergey Glukhov 2009-07-03 [merge] 5.1-bugteam->6.0-bugteam merge @ mysql-test/r/view.result 5.1-bugteam->6.0-bugteam merge @ mysql-test/t/view.test 5.1-bugteam->6.0-bugteam merge @ sql/sql_insert.cc 5.1-bugteam->6.0-bugteam merge modified: mysql-test/r/view.result mysql-test/t/view.test sql/sql_insert.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-07-02 15:51:04 +0000 +++ b/sql/item.cc 2009-07-03 10:50:00 +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; } @@ -7539,8 +7551,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-29 12:59:20 +0000 +++ b/sql/sql_select.cc 2009-07-03 10:50:00 +0000 @@ -13785,13 +13785,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_ngZ8vFTCOUdZ5uhpHzsvSw) 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/mysql-6.0-bugteam/ # testament_sha1: 0624a00558e3fc2a96760f335a21d2c524e83533 # timestamp: 2009-07-03 14:51:51 +0400 # source_branch: file:///data/src/bzr/bugteam/bug45236/my60-bug45236/ # base_revision_id: sergey.glukhov@stripped\ # enrwy4y38vlnumrw # # Begin bundle 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 EEkAkhJCSHEfuE2kHSxe12/U9P2PoySSSSSOXveoyd3d3oo4NOLo610bbNneM8/TO3VCVBNHfJDM JqXR5xJKMUdqi240ZZlwaXQ1Zgce5A28y9JGnTDbQWaI9ZgMtw5ZZ5Db2ymCw0BljaMMbFdhdlYg h0+hW3qruwtoqvi+M6+BlyyC1f1B8VKMjJV5MgZICUNjciVcUwGSkuoxFycDkkTCJdIZKIiPzElh YQLBgSFAkKyvKI/C/Y+I8YVzaQUvL9rWQWWX4Pzr2TVhMmWYiwkqALZYggSBhkCbggNy0rvqkxVZ SEgk0HtJRNCxlOhXKzndtxQCaQaLzPvpjoPUsbM2Lf5OGyc1yyR06NFbLmjm22Z3VIgqxqAQR2Jv HRSk3acpgO+CpBdIO0wGH0cliR0zywWAQiVlUW5QPAkKTEA5pJMipJrIzwnJmpqszOKmjmos2cnN /H93M3UFJOGYsMgYyqrb9ivrt9x7F0rTQaLELhbD6rcNyEHW9OS1Ix1uex2egtY9qGqQhtZeGRgb Gs3mrQCqkYaZZlmZxApibG8WkYozvf1CMYnlp3QLPzuYPafRxK/C4bl8723G2iEFX+YbAUckj6CB kJxRvLVVzQIFZdhfWVHTh6bVOasWhwPXpWoS2pGT/G1wYqNgGGKD0BBUMn1ylJ1Yo40423E1TDzE XsQCGlgQYEWUkdhMBDHJ8EOewME5HTbyNFJeGL8W153fv9UoxjrLypx5y0+98X4rm1PIWCDBY88d afhqIUYGVG8YfGZ2UPoKyUmomRBJOQfLsofMIClODdyTlRINEgmUDgyKc5ysbqROCji5KGg5bTzo 0LI4zGEwi547SJJhqxWszwNyMHLlCXyFjk4vQyVA0YiWmOxYoTYjxzs7HBNMVw1ZTi+njYnCyeSb vKCRjouTtlpP7a2G21ZKLlsz3+K5njOHRegzpKWeKlhc1sx3nzEswo1UlMM+aw1lprOoUM2Uw4Ct AodGQ8XJ5rmTxeC5g7jF0ZMDdi72DNpi5rLMnkuegOy5e8KatmzoucVPJs4HNwkkNZsJjrOoxX28 vvLCKFWaSbiaNVuf8VMkaZqhtOFtLpPQEcudTiqBcwDtkpEiE7tpoiqT4neIVtjP62K7bVbRrnfP pFuH1QmPnYZqERo9xw0asFi8HkQjpCG2ZwTPmQuMVpKvTywT5Gktlh+xGjbjbPU5qYow/vBjBYNm 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 --Boundary_(ID_ngZ8vFTCOUdZ5uhpHzsvSw)--