Commit 86ed0e98 authored by unknown's avatar unknown

Merge mysql.com:/home/ram/work/b19690/b19690.4.1

into  mysql.com:/home/ram/work/b19690/b19690.5.0


mysql-test/r/type_float.result:
  Auto merged
mysql-test/t/type_float.test:
  Auto merged
sql/field.cc:
  Auto merged
sql/item_cmpfunc.h:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/field.h:
  merging
sql/init.cc:
  merging
sql/item_cmpfunc.cc:
  merging
sql/mysql_priv.h:
  merging
sql/sql_select.cc:
  merging
parents 7d4477f8 faad7355
...@@ -268,6 +268,77 @@ select 1e-308, 1.00000001e-300, 100000000e-300; ...@@ -268,6 +268,77 @@ select 1e-308, 1.00000001e-300, 100000000e-300;
select 10e307; select 10e307;
10e307 10e307
1e+308 1e+308
create table t1(a int, b double(8, 2));
insert into t1 values
(1, 28.50), (1, 121.85), (1, 157.23), (1, 1351.00), (1, -1965.35), (1, 81.75),
(1, 217.08), (1, 7.94), (4, 96.07), (4, 6404.65), (4, -6500.72), (2, 100.00),
(5, 5.00), (5, -2104.80), (5, 2033.80), (5, 0.07), (5, 65.93),
(3, -4986.24), (3, 5.00), (3, 4857.34), (3, 123.74), (3, 0.16),
(6, -1695.31), (6, 1003.77), (6, 499.72), (6, 191.82);
explain select sum(b) s from t1 group by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using temporary; Using filesort
select sum(b) s from t1 group by a;
s
0.00
100.00
0.00
-0.00
-0.00
0.00
select sum(b) s from t1 group by a having s <> 0;
s
100.00
select sum(b) s from t1 group by a having s <> 0 order by s;
s
100.00
select sum(b) s from t1 group by a having s <=> 0;
s
0.00
0.00
-0.00
-0.00
0.00
select sum(b) s from t1 group by a having s <=> 0 order by s;
s
-0.00
-0.00
0.00
0.00
0.00
alter table t1 add key (a, b);
explain select sum(b) s from t1 group by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 14 NULL 26 Using index
select sum(b) s from t1 group by a;
s
0.00
100.00
0.00
-0.00
0.00
0.00
select sum(b) s from t1 group by a having s <> 0;
s
100.00
select sum(b) s from t1 group by a having s <> 0 order by s;
s
100.00
select sum(b) s from t1 group by a having s <=> 0;
s
0.00
0.00
-0.00
0.00
0.00
select sum(b) s from t1 group by a having s <=> 0 order by s;
s
-0.00
0.00
0.00
0.00
0.00
drop table t1;
End of 4.1 tests End of 4.1 tests
create table t1 (s1 float(0,2)); create table t1 (s1 float(0,2));
ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1').
......
...@@ -187,6 +187,31 @@ select 1e-308, 1.00000001e-300, 100000000e-300; ...@@ -187,6 +187,31 @@ select 1e-308, 1.00000001e-300, 100000000e-300;
# check if overflows are detected correctly # check if overflows are detected correctly
select 10e307; select 10e307;
#
# Bug #19690: ORDER BY eliminates rows from the result
#
create table t1(a int, b double(8, 2));
insert into t1 values
(1, 28.50), (1, 121.85), (1, 157.23), (1, 1351.00), (1, -1965.35), (1, 81.75),
(1, 217.08), (1, 7.94), (4, 96.07), (4, 6404.65), (4, -6500.72), (2, 100.00),
(5, 5.00), (5, -2104.80), (5, 2033.80), (5, 0.07), (5, 65.93),
(3, -4986.24), (3, 5.00), (3, 4857.34), (3, 123.74), (3, 0.16),
(6, -1695.31), (6, 1003.77), (6, 499.72), (6, 191.82);
explain select sum(b) s from t1 group by a;
select sum(b) s from t1 group by a;
select sum(b) s from t1 group by a having s <> 0;
select sum(b) s from t1 group by a having s <> 0 order by s;
select sum(b) s from t1 group by a having s <=> 0;
select sum(b) s from t1 group by a having s <=> 0 order by s;
alter table t1 add key (a, b);
explain select sum(b) s from t1 group by a;
select sum(b) s from t1 group by a;
select sum(b) s from t1 group by a having s <> 0;
select sum(b) s from t1 group by a having s <> 0 order by s;
select sum(b) s from t1 group by a having s <=> 0;
select sum(b) s from t1 group by a having s <=> 0 order by s;
drop table t1;
--echo End of 4.1 tests --echo End of 4.1 tests
# #
......
...@@ -4064,7 +4064,7 @@ int Field_double::store(double nr) ...@@ -4064,7 +4064,7 @@ int Field_double::store(double nr)
else else
{ {
double max_value; double max_value;
if (dec >= NOT_FIXED_DEC) if (not_fixed)
{ {
max_value= DBL_MAX; max_value= DBL_MAX;
} }
......
...@@ -725,6 +725,7 @@ public: ...@@ -725,6 +725,7 @@ public:
class Field_double :public Field_real { class Field_double :public Field_real {
public: public:
my_bool not_fixed;
Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
...@@ -732,12 +733,20 @@ public: ...@@ -732,12 +733,20 @@ public:
uint8 dec_arg,bool zero_arg,bool unsigned_arg) uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg, unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg, unsigned_arg) dec_arg, zero_arg, unsigned_arg),
not_fixed(dec_arg >= NOT_FIXED_DEC)
{} {}
Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, uint8 dec_arg) struct st_table *table_arg, uint8 dec_arg)
:Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
NONE, field_name_arg, table_arg, dec_arg, 0, 0) NONE, field_name_arg, table_arg, dec_arg, 0, 0),
not_fixed(dec_arg >= NOT_FIXED_DEC)
{}
Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, uint8 dec_arg, my_bool not_fixed_srg)
:Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
NONE, field_name_arg, table_arg, dec_arg, 0, 0),
not_fixed(not_fixed_srg)
{} {}
enum_field_types type() const { return FIELD_TYPE_DOUBLE;} enum_field_types type() const { return FIELD_TYPE_DOUBLE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
......
...@@ -44,5 +44,11 @@ void unireg_init(ulong options) ...@@ -44,5 +44,11 @@ void unireg_init(ulong options)
{ /* It's used by filesort... */ { /* It's used by filesort... */
log_10[i]= nr ; nr*= 10.0; log_10[i]= nr ; nr*= 10.0;
} }
/* Make a tab of powers of 0.1 */
for (i= 0, nr= 0.1; i < array_elements(log_01); i++)
{
log_01[i]= nr;
nr*= 0.1;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -422,6 +422,17 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) ...@@ -422,6 +422,17 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
else if (type == REAL_RESULT)
{
if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC)
{
precision= 5 * log_01[max((*a)->decimals, (*b)->decimals)];
if (func == &Arg_comparator::compare_real)
func= &Arg_comparator::compare_real_fixed;
else if (func == &Arg_comparator::compare_e_real)
func= &Arg_comparator::compare_e_real_fixed;
}
}
return 0; return 0;
} }
...@@ -557,6 +568,44 @@ int Arg_comparator::compare_e_decimal() ...@@ -557,6 +568,44 @@ int Arg_comparator::compare_e_decimal()
return test(my_decimal_cmp(val1, val2) == 0); return test(my_decimal_cmp(val1, val2) == 0);
} }
int Arg_comparator::compare_real_fixed()
{
/*
Fix yet another manifestation of Bug#2338. 'Volatile' will instruct
gcc to flush double values out of 80-bit Intel FPU registers before
performing the comparison.
*/
volatile double val1, val2;
val1= (*a)->val();
if (!(*a)->null_value)
{
val2= (*b)->val();
if (!(*b)->null_value)
{
owner->null_value= 0;
if (val1 == val2 || fabs(val1 - val2) < precision)
return 0;
if (val1 < val2)
return -1;
return 1;
}
}
owner->null_value= 1;
return -1;
}
int Arg_comparator::compare_e_real_fixed()
{
double val1= (*a)->val();
double val2= (*b)->val();
if ((*a)->null_value || (*b)->null_value)
return test((*a)->null_value && (*b)->null_value);
return test(val1 == val2 || fabs(val1 - val2) < precision);
}
int Arg_comparator::compare_int_signed() int Arg_comparator::compare_int_signed()
{ {
longlong val1= (*a)->val_int(); longlong val1= (*a)->val_int();
......
...@@ -34,6 +34,7 @@ class Arg_comparator: public Sql_alloc ...@@ -34,6 +34,7 @@ class Arg_comparator: public Sql_alloc
arg_cmp_func func; arg_cmp_func func;
Item_bool_func2 *owner; Item_bool_func2 *owner;
Arg_comparator *comparators; // used only for compare_row() Arg_comparator *comparators; // used only for compare_row()
double precision;
public: public:
DTCollation cmp_collation; DTCollation cmp_collation;
...@@ -80,6 +81,8 @@ public: ...@@ -80,6 +81,8 @@ public:
int compare_e_int(); // compare args[0] & args[1] int compare_e_int(); // compare args[0] & args[1]
int compare_e_int_diff_signedness(); int compare_e_int_diff_signedness();
int compare_e_row(); // compare args[0] & args[1] int compare_e_row(); // compare args[0] & args[1]
int compare_real_fixed();
int compare_e_real_fixed();
static arg_cmp_func comparator_matrix [5][2]; static arg_cmp_func comparator_matrix [5][2];
......
...@@ -1211,6 +1211,7 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; ...@@ -1211,6 +1211,7 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
extern char log_error_file[FN_REFLEN], *opt_tc_log_file; extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
extern double log_10[32]; extern double log_10[32];
extern double log_01[32];
extern ulonglong log_10_int[20]; extern ulonglong log_10_int[20];
extern ulonglong keybuff_size; extern ulonglong keybuff_size;
extern ulonglong thd_startup_options; extern ulonglong thd_startup_options;
......
...@@ -432,6 +432,7 @@ ulong expire_logs_days = 0; ...@@ -432,6 +432,7 @@ ulong expire_logs_days = 0;
ulong rpl_recovery_rank=0; ulong rpl_recovery_rank=0;
double log_10[32]; /* 10 potences */ double log_10[32]; /* 10 potences */
double log_01[32];
time_t start_time; time_t start_time;
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30]; char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
......
...@@ -8598,6 +8598,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field, ...@@ -8598,6 +8598,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field,
if (org_field->type() == MYSQL_TYPE_VAR_STRING || if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
org_field->type() == MYSQL_TYPE_VARCHAR) org_field->type() == MYSQL_TYPE_VARCHAR)
table->s->db_create_options|= HA_OPTION_PACK_RECORD; table->s->db_create_options|= HA_OPTION_PACK_RECORD;
else if (org_field->type() == FIELD_TYPE_DOUBLE)
((Field_double *) new_field)->not_fixed= TRUE;
} }
return new_field; return new_field;
} }
...@@ -8638,7 +8640,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, ...@@ -8638,7 +8640,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
switch (item->result_type()) { switch (item->result_type()) {
case REAL_RESULT: case REAL_RESULT:
new_field=new Field_double(item->max_length, maybe_null, new_field=new Field_double(item->max_length, maybe_null,
item->name, table, item->decimals); item->name, table, item->decimals, TRUE);
break; break;
case INT_RESULT: case INT_RESULT:
/* Select an integer type with the minimal fit precision */ /* Select an integer type with the minimal fit precision */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment