diff options
author | unknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru> | 2007-01-31 14:31:11 +0400 |
---|---|---|
committer | unknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru> | 2007-01-31 14:31:11 +0400 |
commit | 1bcc167053a88b46f9c8dafbad0bb2e584acf289 (patch) | |
tree | b4e0d9edcc581bb4acc1f697ed311c5e52245be0 /sql | |
parent | 29617cad4182c5e95255db90767f83249d1e94e5 (diff) | |
parent | abf7eb0627d1a652beaa2380dbb94c6ad0ae0a2a (diff) | |
download | mariadb-git-1bcc167053a88b46f9c8dafbad0bb2e584acf289.tar.gz |
Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-5.0-maint
into mysql.com:/home/ram/work/b19690/b19690.5.0
sql/item_cmpfunc.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 15 | ||||
-rw-r--r-- | sql/init.cc | 6 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 49 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 3 | ||||
-rw-r--r-- | sql/item_sum.cc | 7 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 |
9 files changed, 80 insertions, 8 deletions
diff --git a/sql/field.cc b/sql/field.cc index efe608b7bdd..74a5e742c06 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4064,7 +4064,7 @@ int Field_double::store(double nr) else { double max_value; - if (dec >= NOT_FIXED_DEC) + if (not_fixed) { max_value= DBL_MAX; } diff --git a/sql/field.h b/sql/field.h index 565342637ba..26092c12372 100644 --- a/sql/field.h +++ b/sql/field.h @@ -725,6 +725,7 @@ public: class Field_double :public Field_real { public: + my_bool not_fixed; Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, @@ -732,12 +733,20 @@ public: uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_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, struct st_table *table_arg, uint8 dec_arg) - :Field_real((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, - NONE, field_name_arg, table_arg, dec_arg, 0, 0) + :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(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 ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } diff --git a/sql/init.cc b/sql/init.cc index 25856a1e1b4..ad55a2a8b24 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -44,5 +44,11 @@ void unireg_init(ulong options) { /* It's used by filesort... */ 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; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f4b99e19864..f64b53bfa12 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -423,8 +423,19 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) break; } case DECIMAL_RESULT: + break; case 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; + } break; + } default: DBUG_ASSERT(0); } @@ -563,6 +574,44 @@ int Arg_comparator::compare_e_decimal() 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_real(); + if (!(*a)->null_value) + { + val2= (*b)->val_real(); + 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_real(); + double val2= (*b)->val_real(); + 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() { longlong val1= (*a)->val_int(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7bdc90adcee..1b27aac0871 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -34,6 +34,7 @@ class Arg_comparator: public Sql_alloc arg_cmp_func func; Item_bool_func2 *owner; Arg_comparator *comparators; // used only for compare_row() + double precision; public: DTCollation cmp_collation; @@ -80,6 +81,8 @@ public: int compare_e_int(); // compare args[0] & args[1] int compare_e_int_diff_signedness(); 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]; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 8bfac058936..28a9a1f4dbf 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -398,7 +398,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, { switch (result_type()) { case REAL_RESULT: - return new Field_double(max_length,maybe_null,name,table,decimals); + return new Field_double(max_length, maybe_null, name, table, decimals, + TRUE); case INT_RESULT: return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag); case STRING_RESULT: @@ -1123,7 +1124,7 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, if (hybrid_type == DECIMAL_RESULT) return new Field_new_decimal(max_length, maybe_null, name, table, decimals, unsigned_flag); - return new Field_double(max_length, maybe_null, name, table, decimals); + return new Field_double(max_length, maybe_null, name, table, decimals, TRUE); } @@ -1317,7 +1318,7 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table, */ return new Field_string(sizeof(double)*2 + sizeof(longlong), 0, name, table, &my_charset_bin); } - return new Field_double(max_length, maybe_null,name,table,decimals); + return new Field_double(max_length, maybe_null, name, table, decimals, TRUE); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8295f247835..4c0554719ed 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1218,6 +1218,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 log_error_file[FN_REFLEN], *opt_tc_log_file; extern double log_10[32]; +extern double log_01[32]; extern ulonglong log_10_int[20]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d481bc928f8..8a1c1797736 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -432,6 +432,7 @@ ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; double log_10[32]; /* 10 potences */ +double log_01[32]; time_t start_time; char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30]; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d62032c2b44..395c70e711a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8598,6 +8598,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field, if (org_field->type() == MYSQL_TYPE_VAR_STRING || org_field->type() == MYSQL_TYPE_VARCHAR) 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; } @@ -8638,7 +8640,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, switch (item->result_type()) { case REAL_RESULT: new_field=new Field_double(item->max_length, maybe_null, - item->name, table, item->decimals); + item->name, table, item->decimals, TRUE); break; case INT_RESULT: /* Select an integer type with the minimal fit precision */ |