1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Fix for bug #43432: Union on floats does unnecessary rounding

UNION could convert fixed-point FLOAT(M,D)/DOUBLE(M,D) columns  
to FLOAT/DOUBLE when aggregating data types from the SELECT  
substatements. While there is nothing particularly wrong with  
this behavior, especially when M is greater than the hardware  
precision limits, it could be confusing in cases when all  
SELECT statements in a union have the same  
FLOAT(M,D)/DOUBLE(M,D) columns with equal precision  
specifications listed in the same position.  
  
Since the manual is quite vague on what data type should be  
returned in such cases, the bug was fixed by implementing the  
most 'expected' behavior: do not convert FLOAT(M,D)/DOUBLE(M,D)  
to anything else if all SELECT statements in a UNION have the  
same precision for that column.
This commit is contained in:
Alexey Kopytov
2009-03-27 13:12:50 +03:00
parent 8725bcd944
commit afb2b6de68
5 changed files with 54 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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 &&

View File

@ -6948,21 +6948,29 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
case REAL_RESULT:
{
if (decimals != NOT_FIXED_DEC)
{
/*
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)
{
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;
max_length= MAX_FLOAT_STR_LENGTH;
decimals= NOT_FIXED_DEC;
}
if (fld_type == MYSQL_TYPE_DOUBLE && max_length > DBL_DIG + 2)
else if (fld_type == MYSQL_TYPE_DOUBLE && max_length > DBL_DIG + 2)
{
max_length= DBL_DIG + 7;
max_length= MAX_DOUBLE_STR_LENGTH;
decimals= NOT_FIXED_DEC;
}
}
}
else
max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7;
break;

View File

@ -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