From: Date: July 3 2009 12:48pm Subject: bzr commit into mysql-pe branch (Alexey.Kopytov:3427) List-Archive: http://lists.mysql.com/commits/77879 Message-Id: <20090703104830.A743551AF@kaamos.local> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_ODRW+0ExCIxan+yBvC/eSg)" --Boundary_(ID_ODRW+0ExCIxan+yBvC/eSg) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///data/src/bzr/bugteam/mysql-6.0-bugteam/ based on revid:sergey.glukhov@stripped 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 === 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:48:13 +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:48:13 +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_ODRW+0ExCIxan+yBvC/eSg) 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: c080c0c400994f1be073e9f755a0299d2e1c99ed # timestamp: 2009-07-03 14:48:30 +0400 # source_branch: file:///data/src/bzr/bugteam/bug45236/my60-bug45236/ # base_revision_id: sergey.glukhov@stripped\ # enrwy4y38vlnumrw # # Begin bundle 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 3H/B457v/F3JFOFCQ+dc7yA= --Boundary_(ID_ODRW+0ExCIxan+yBvC/eSg)--