diff options
-rw-r--r-- | mysql-test/r/union.result | 12 | ||||
-rw-r--r-- | mysql-test/t/union.test | 15 | ||||
-rw-r--r-- | sql/field.cc | 6 | ||||
-rw-r--r-- | sql/item.cc | 30 | ||||
-rw-r--r-- | sql/mysql_priv.h | 5 |
5 files changed, 54 insertions, 14 deletions
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 6007fdd403a..3ae7953e283 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1506,4 +1506,16 @@ DESC t6; Field Type Null Key Default Extra NULL int(11) YES NULL DROP TABLE t1, t2, t3, t4, t5, t6; +CREATE TABLE t1 (f FLOAT(9,6)); +CREATE TABLE t2 AS SELECT f FROM t1 UNION SELECT f FROM t1; +SHOW FIELDS FROM t2; +Field Type Null Key Default Extra +f float(9,6) YES NULL +DROP TABLE t1, t2; +CREATE TABLE t1(d DOUBLE(9,6)); +CREATE TABLE t2 AS SELECT d FROM t1 UNION SELECT d FROM t1; +SHOW FIELDS FROM t2; +Field Type Null Key Default Extra +d double(9,6) YES NULL +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 44f21abda19..35b9be60f2b 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1000,4 +1000,19 @@ SELECT * FROM (SELECT * FROM (SELECT NULL)a) b UNION SELECT a FROM t1; DESC t6; DROP TABLE t1, t2, t3, t4, t5, t6; + +# +# Bug #43432: Union on floats does unnecessary rounding +# + +CREATE TABLE t1 (f FLOAT(9,6)); +CREATE TABLE t2 AS SELECT f FROM t1 UNION SELECT f FROM t1; +SHOW FIELDS FROM t2; +DROP TABLE t1, t2; + +CREATE TABLE t1(d DOUBLE(9,6)); +CREATE TABLE t2 AS SELECT d FROM t1 UNION SELECT d FROM t1; +SHOW FIELDS FROM t2; +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/sql/field.cc b/sql/field.cc index f8ab4b852ec..36cc4681dec 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8587,16 +8587,16 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, else if (tmp_length > PRECISION_FOR_FLOAT) { sql_type= FIELD_TYPE_DOUBLE; - length= DBL_DIG+7; /* -[digits].E+### */ + length= MAX_DOUBLE_STR_LENGTH; } else - length= FLT_DIG+6; /* -[digits].E+## */ + length= MAX_FLOAT_STR_LENGTH; decimals= NOT_FIXED_DEC; break; } if (!fld_length && !fld_decimals) { - length= FLT_DIG+6; + length= MAX_FLOAT_STR_LENGTH; decimals= NOT_FIXED_DEC; } if (length < decimals && diff --git a/sql/item.cc b/sql/item.cc index f32828629cf..f2b52a0f865 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6949,18 +6949,26 @@ bool Item_type_holder::join_types(THD *thd, Item *item) { if (decimals != NOT_FIXED_DEC) { - int delta1= max_length_orig - decimals_orig; - int delta2= item->max_length - item->decimals; - max_length= max(delta1, delta2) + decimals; - if (fld_type == MYSQL_TYPE_FLOAT && max_length > FLT_DIG + 2) - { - max_length= FLT_DIG + 6; - decimals= NOT_FIXED_DEC; - } - if (fld_type == MYSQL_TYPE_DOUBLE && max_length > DBL_DIG + 2) + /* + For FLOAT(M,D)/DOUBLE(M,D) do not change precision + if both fields have the same M and D + */ + if (item->max_length != max_length_orig || + item->decimals != decimals_orig) { - max_length= DBL_DIG + 7; - decimals= NOT_FIXED_DEC; + int delta1= max_length_orig - decimals_orig; + int delta2= item->max_length - item->decimals; + max_length= max(delta1, delta2) + decimals; + if (fld_type == MYSQL_TYPE_FLOAT && max_length > FLT_DIG + 2) + { + max_length= MAX_FLOAT_STR_LENGTH; + decimals= NOT_FIXED_DEC; + } + else if (fld_type == MYSQL_TYPE_DOUBLE && max_length > DBL_DIG + 2) + { + max_length= MAX_DOUBLE_STR_LENGTH; + decimals= NOT_FIXED_DEC; + } } } else diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b855af9a8d3..58ab7a08837 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -251,6 +251,11 @@ MY_LOCALE *my_locale_by_number(uint number); #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 +/* -[digits].E+## */ +#define MAX_FLOAT_STR_LENGTH (FLT_DIG + 6) +/* -[digits].E+### */ +#define MAX_DOUBLE_STR_LENGTH (DBL_DIG + 7) + /* Default time to wait before aborting a new client connection that does not respond to "initial server greeting" timely |