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,
Attachment: [text/bzr-bundle] bzr/alexey.kopytov@sun.com-20090703105000-toiyvlbi2ca7bvtx.bundle
| Thread |
|---|
| • bzr push into mysql-pe branch (Alexey.Kopytov:3426 to 3428) | Alexey Kopytov | 3 Jul 2009 |