diff options
author | unknown <tsmith@quadxeon.mysql.com> | 2007-05-01 18:12:04 +0200 |
---|---|---|
committer | unknown <tsmith@quadxeon.mysql.com> | 2007-05-01 18:12:04 +0200 |
commit | dc9b20a60301040cfc3801703f4799c5e60477a3 (patch) | |
tree | e068de92f3f81a2e6ee7f047617547c148454474 /sql | |
parent | 5352b41d29bf3a0ca37d64acfa61527a4944812d (diff) | |
parent | f827425712cb7cf2afdb729365615554582411c2 (diff) | |
download | mariadb-git-dc9b20a60301040cfc3801703f4799c5e60477a3.tar.gz |
Merge quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/50
into quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/maint/50
sql/item_func.h:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_func.cc | 115 | ||||
-rw-r--r-- | sql/item_func.h | 8 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/sql_table.cc | 32 | ||||
-rw-r--r-- | sql/sql_update.cc | 19 |
6 files changed, 113 insertions, 66 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 503b4362e7a..14a4c4dcf4b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -616,6 +616,14 @@ Item *Item_func::get_tmp_table_item(THD *thd) return copy_or_same(thd); } +double Item_int_func::val_real() +{ + DBUG_ASSERT(fixed == 1); + + return unsigned_flag ? (double) ((ulonglong) val_int()) : (double) val_int(); +} + + String *Item_int_func::val_str(String *str) { DBUG_ASSERT(fixed == 1); @@ -804,7 +812,10 @@ double Item_func_numhybrid::val_real() return result; } case INT_RESULT: - return (double)int_op(); + { + longlong result= int_op(); + return unsigned_flag ? (double) ((ulonglong) result) : (double) result; + } case REAL_RESULT: return real_op(); case STRING_RESULT: @@ -1341,6 +1352,8 @@ longlong Item_func_mod::int_op() DBUG_ASSERT(fixed == 1); longlong value= args[0]->val_int(); longlong val2= args[1]->val_int(); + longlong result; + if ((null_value= args[0]->null_value || args[1]->null_value)) return 0; /* purecov: inspected */ if (val2 == 0) @@ -1350,9 +1363,13 @@ longlong Item_func_mod::int_op() } if (args[0]->unsigned_flag) - return ((ulonglong) value) % val2; + result= args[1]->unsigned_flag ? + ((ulonglong) value) % ((ulonglong) val2) : ((ulonglong) value) % val2; + else + result= args[1]->unsigned_flag ? + value % ((ulonglong) val2) : value % val2; - return value % val2; + return result; } double Item_func_mod::real_op() @@ -1407,6 +1424,7 @@ void Item_func_mod::fix_length_and_dec() { Item_num_op::fix_length_and_dec(); maybe_null= 1; + unsigned_flag= args[0]->unsigned_flag; } @@ -1485,8 +1503,9 @@ double Item_func_abs::real_op() longlong Item_func_abs::int_op() { longlong value= args[0]->val_int(); - null_value= args[0]->null_value; - return value >= 0 ? value : -value; + if ((null_value= args[0]->null_value)) + return 0; + return (value >= 0) || unsigned_flag ? value : -value; } @@ -1507,6 +1526,7 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) void Item_func_abs::fix_length_and_dec() { Item_func_num1::fix_length_and_dec(); + unsigned_flag= args[0]->unsigned_flag; } @@ -1881,6 +1901,10 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) void Item_func_round::fix_length_and_dec() { + int decimals_to_set; + longlong val1; + bool val1_unsigned; + unsigned_flag= args[0]->unsigned_flag; if (!args[1]->const_item()) { @@ -1889,8 +1913,14 @@ void Item_func_round::fix_length_and_dec() hybrid_type= REAL_RESULT; return; } - - int decimals_to_set= max((int)args[1]->val_int(), 0); + + val1= args[1]->val_int(); + val1_unsigned= args[1]->unsigned_flag; + if (val1 < 0) + decimals_to_set= val1_unsigned ? INT_MAX : 0; + else + decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1; + if (args[0]->decimals == NOT_FIXED_DEC) { max_length= args[0]->max_length; @@ -1907,10 +1937,9 @@ void Item_func_round::fix_length_and_dec() max_length= float_length(decimals); break; case INT_RESULT: - if (!decimals_to_set && - (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))) + if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)) { - int length_can_increase= test(!truncate && (args[1]->val_int() < 0)); + int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned); max_length= args[0]->max_length + length_can_increase; /* Here we can keep INT_RESULT */ hybrid_type= INT_RESULT; @@ -1936,10 +1965,12 @@ void Item_func_round::fix_length_and_dec() } } -double my_double_round(double value, int dec, bool truncate) +double my_double_round(double value, longlong dec, bool dec_unsigned, + bool truncate) { double tmp; - uint abs_dec= abs(dec); + bool dec_negative= (dec < 0) && !dec_unsigned; + ulonglong abs_dec= dec_negative ? -dec : dec; /* tmp2 is here to avoid return the value with 80 bit precision This will fix that the test round(0.1,1) = round(0.1,1) is true @@ -1949,7 +1980,11 @@ double my_double_round(double value, int dec, bool truncate) tmp=(abs_dec < array_elements(log_10) ? log_10[abs_dec] : pow(10.0,(double) abs_dec)); - if (truncate) + if (dec_negative && isinf(tmp)) + tmp2= 0; + else if (!dec_negative && isinf(value * tmp)) + tmp2= value; + else if (truncate) { if (value >= 0) tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp; @@ -1965,24 +2000,35 @@ double my_double_round(double value, int dec, bool truncate) double Item_func_round::real_op() { double value= args[0]->val_real(); - int dec= (int) args[1]->val_int(); if (!(null_value= args[0]->null_value || args[1]->null_value)) - return my_double_round(value, dec, truncate); + return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag, + truncate); return 0.0; } +/* + Rounds a given value to a power of 10 specified as the 'to' argument, + avoiding overflows when the value is close to the ulonglong range boundary. +*/ + +static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to) +{ + ulonglong tmp= value / to * to; + return (value - tmp < (to >> 1)) ? tmp : tmp + to; +} + longlong Item_func_round::int_op() { longlong value= args[0]->val_int(); - int dec=(int) args[1]->val_int(); + longlong dec= args[1]->val_int(); decimals= 0; - uint abs_dec; + ulonglong abs_dec; if ((null_value= args[0]->null_value || args[1]->null_value)) return 0; - if (dec >= 0) + if ((dec >= 0) || args[1]->unsigned_flag) return value; // integer have not digits after point abs_dec= -dec; @@ -1994,21 +2040,12 @@ longlong Item_func_round::int_op() tmp= log_10_int[abs_dec]; if (truncate) - { - if (unsigned_flag) - value= (ulonglong(value)/tmp)*tmp; - else - value= (value/tmp)*tmp; - } + value= (unsigned_flag) ? + ((ulonglong) value / tmp) * tmp : (value / tmp) * tmp; else - { - if (unsigned_flag) - value= ((ulonglong(value)+(tmp>>1))/tmp)*tmp; - else if ( value >= 0) - value= ((value+(tmp>>1))/tmp)*tmp; - else - value= ((value-(tmp>>1))/tmp)*tmp; - } + value= (unsigned_flag || value >= 0) ? + my_unsigned_round((ulonglong) value, tmp) : + -(longlong) my_unsigned_round((ulonglong) -value, tmp); return value; } @@ -2016,14 +2053,18 @@ longlong Item_func_round::int_op() my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) { my_decimal val, *value= args[0]->val_decimal(&val); - int dec=(int) args[1]->val_int(); - if (dec > 0) + longlong dec= args[1]->val_int(); + if (dec > 0 || (dec < 0 && args[1]->unsigned_flag)) { - decimals= min(dec, DECIMAL_MAX_SCALE); // to get correct output + dec= min((ulonglong) dec, DECIMAL_MAX_SCALE); + decimals= (uint8) dec; // to get correct output } + else if (dec < INT_MIN) + dec= INT_MIN; + if (!(null_value= (args[0]->null_value || args[1]->null_value || - my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate, - decimal_value) > 1))) + my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec, + truncate, decimal_value) > 1))) return decimal_value; return 0; } diff --git a/sql/item_func.h b/sql/item_func.h index ec5d6bcda02..2d70f57d0e9 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -278,7 +278,7 @@ public: { max_length= 21; } Item_int_func(List<Item> &list) :Item_func(list) { max_length= 21; } Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {} - double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } + double val_real(); String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } void fix_length_and_dec() {} @@ -303,12 +303,6 @@ class Item_func_signed :public Item_int_func public: Item_func_signed(Item *a) :Item_int_func(a) {} const char *func_name() const { return "cast_as_signed"; } - double val_real() - { - double tmp= args[0]->val_real(); - null_value= args[0]->null_value; - return tmp; - } longlong val_int(); longlong val_int_from_str(int *error); void fix_length_and_dec() diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1991526345c..f9a0f715985 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1995,7 +1995,7 @@ String *Item_func_format::val_str(String *str) double nr= args[0]->val_real(); if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ - nr= my_double_round(nr, decimals, FALSE); + nr= my_double_round(nr, (longlong) decimals, FALSE, FALSE); /* Here default_charset() is right as this is not an automatic conversion */ str->set(nr,decimals, default_charset()); if (isnan(nr)) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7e873dd7cc6..7ab683134e0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1539,7 +1539,8 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, ha_rows max_rows, ha_rows *examined_rows); void filesort_free_buffers(TABLE *table, bool full); void change_double_for_sort(double nr,byte *to); -double my_double_round(double value, int dec, bool truncate); +double my_double_round(double value, longlong dec, bool dec_unsigned, + bool truncate); int get_quick_record(SQL_SELECT *select); int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(TIME *l_time, uint week_behaviour, uint *year); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6f953349c03..42d59a10712 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -42,6 +42,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, static bool prepare_blob_field(THD *thd, create_field *sql_field); static bool check_engine(THD *thd, const char *table_name, enum db_type *new_engine); +static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd); /* @@ -1681,11 +1682,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { - my_snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s", - mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id, - thd->tmp_table++, reg_ext); - if (lower_case_table_names) - my_casedn_str(files_charset_info, path); + set_tmp_file_path(path, sizeof(path), thd); create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; } else @@ -2801,11 +2798,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, { if (find_temporary_table(thd, db, table_name)) goto table_exists; - my_snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s", - mysql_tmpdir, tmp_file_prefix, current_pid, - thd->thread_id, thd->tmp_table++, reg_ext); - if (lower_case_table_names) - my_casedn_str(files_charset_info, dst_path); + set_tmp_file_path(dst_path, sizeof(dst_path), thd); create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE; } else @@ -3316,6 +3309,12 @@ view_err: create_info->avg_row_length= table->s->avg_row_length; if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) create_info->default_table_charset= table->s->table_charset; + if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field) + { + /* Table has an autoincrement, copy value to new table */ + table->file->info(HA_STATUS_AUTO); + create_info->auto_increment_value= table->file->auto_increment_value; + } restore_record(table, s->default_values); // Empty record for DEFAULT List_iterator<Alter_drop> drop_it(alter_info->drop_list); @@ -4313,3 +4312,16 @@ static bool check_engine(THD *thd, const char *table_name, } return FALSE; } + +static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd) +{ + char *p= strnmov(buf, mysql_tmpdir, bufsize); + my_snprintf(p, bufsize - (p - buf), "%s%lx_%lx_%x%s", + tmp_file_prefix, current_pid, + thd->thread_id, thd->tmp_table++, reg_ext); + if (lower_case_table_names) + { + /* Convert all except tmpdir to lower case */ + my_casedn_str(files_charset_info, p); + } +} diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6f6c4538040..e17c71ae541 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1354,19 +1354,18 @@ bool multi_update::send_data(List<Item> ¬_used_values) memcpy((char*) tmp_table->field[0]->ptr, (char*) table->file->ref, table->file->ref_length); /* Write row, ignoring duplicated updates to a row */ - if ((error= tmp_table->file->write_row(tmp_table->record[0]))) + error= tmp_table->file->write_row(tmp_table->record[0]); + if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) { - if (error != HA_ERR_FOUND_DUPP_KEY && - error != HA_ERR_FOUND_DUPP_UNIQUE && + if (error && create_myisam_from_heap(thd, tmp_table, - tmp_table_param + offset, error, 1)) - { - do_update=0; - DBUG_RETURN(1); // Not a table_is_full error - } - } - else + tmp_table_param + offset, error, 1)) + { + do_update= 0; + DBUG_RETURN(1); // Not a table_is_full error + } found++; + } } } DBUG_RETURN(0); |