diff --git a/sql/field.cc b/sql/field.cc index 77bd7392dd2..45089f282fa 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -806,14 +806,11 @@ double Field_decimal::val_real(void) longlong Field_decimal::val_int(void) { - char temp= *(ptr+field_length); *(ptr+field_length) = '\0'; - longlong nr; + CHARSET_INFO *cs=charset(); if (unsigned_flag) - nr=(longlong) strtoull(ptr,NULL,10); + return my_strntoull(cs,ptr,field_length,NULL,10); else - nr=strtoll(ptr,NULL,10); - *(ptr+field_length)=temp; - return(nr); + return my_strntoll(cs,ptr,field_length,NULL,10); } String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), @@ -1100,8 +1097,7 @@ void Field_tiny::sql_type(String &res) const ****************************************************************************/ -// Note: Sometimes this should be fixed to use one strtol() to use -// len and check for garbage after number. +// Note: Sometimes this should be fixed to check for garbage after number. int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { @@ -1363,8 +1359,7 @@ void Field_short::sql_type(String &res) const ** medium int ****************************************************************************/ -// Note: Sometimes this should be fixed to use one strtol() to use -// len and check for garbage after number. +// Note: Sometimes this should be fixed to check for garbage after number. int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { @@ -1571,8 +1566,7 @@ void Field_medium::sql_type(String &res) const ****************************************************************************/ -// Note: Sometimes this should be fixed to use one strtol() to use -// len and check for garbage after number. +// Note: Sometimes this should be fixed to check for garbage after number. int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) { @@ -3794,23 +3788,16 @@ int Field_string::store(longlong nr) double Field_string::val_real(void) { - double value; - char save=ptr[field_length]; // Ok to patch record - ptr[field_length]=0; - value=atof(ptr); - ptr[field_length]=save; - return value; + CHARSET_INFO *cs=charset(); + return my_strntod(cs,ptr,field_length,(char**)0); } longlong Field_string::val_int(void) { longlong value; - char save=ptr[field_length]; // Ok to patch record - ptr[field_length]=0; - value=strtoll(ptr,NULL,10); - ptr[field_length]=save; - return value; + CHARSET_INFO *cs=charset(); + return my_strntoll(cs,ptr,field_length,NULL,10); } @@ -3998,25 +3985,17 @@ int Field_varstring::store(longlong nr) double Field_varstring::val_real(void) { - double value; uint length=uint2korr(ptr)+2; - char save=ptr[length]; // Ok to patch record - ptr[length]=0; - value=atof(ptr+2); - ptr[length]=save; - return value; + CHARSET_INFO *cs=charset(); + return my_strntod(cs,ptr+2,length,(char**)0); } longlong Field_varstring::val_int(void) { - longlong value; uint length=uint2korr(ptr)+2; - char save=ptr[length]; // Ok to patch record - ptr[length]=0; - value=strtoll(ptr+2,NULL,10); - ptr[length]=save; - return value; + CHARSET_INFO *cs=charset(); + return my_strntoll(cs,ptr+2,length,NULL,10); } @@ -4339,12 +4318,8 @@ double Field_blob::val_real(void) if (!blob) return 0.0; uint32 length=get_length(ptr); - - char save=blob[length]; // Ok to patch blob in NISAM - blob[length]=0; - double nr=atof(blob); - blob[length]=save; - return nr; + CHARSET_INFO *cs=charset(); + return my_strntod(cs,blob,length,(char**)0); } @@ -4355,12 +4330,8 @@ longlong Field_blob::val_int(void) if (!blob) return 0; uint32 length=get_length(ptr); - - char save=blob[length]; // Ok to patch blob in NISAM - blob[length]=0; - longlong nr=strtoll(blob,NULL,10); - blob[length]=save; - return nr; + CHARSET_INFO *cs=charset(); + return my_strntoll(cs,blob,length,NULL,10); } @@ -4803,16 +4774,10 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) if (length < 6) // Can't be more than 99999 enums { /* This is for reading numbers with LOAD DATA INFILE */ - char buff[7], *end; - const char *conv=from; - if (from[length]) - { - strmake(buff, from, length); - conv=buff; - } + char *end; my_errno=0; - tmp=(uint) strtoul(conv,&end,10); - if (my_errno || end != conv+length || tmp > typelib->count) + tmp=(uint) my_strntoul(cs,from,length,&end,10); + if (my_errno || end != from+length || tmp > typelib->count) { tmp=0; current_thd->cuted_fields++; @@ -5007,16 +4972,10 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) if (!tmp && length && length < 22) { /* This is for reading numbers with LOAD DATA INFILE */ - char buff[22], *end; - const char *conv=from; - if (from[length]) - { - strmake(buff, from, length); - conv=buff; - } + char *end; my_errno=0; - tmp=strtoull(conv,&end,10); - if (my_errno || end != conv+length || + tmp=my_strntoull(cs,from,length,&end,10); + if (my_errno || end != from+length || tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1)) { tmp=0; diff --git a/sql/item.cc b/sql/item.cc index f21cd0fc0f3..568ad74a631 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -395,7 +395,7 @@ longlong Item_param::val_int() { switch (item_result_type) { case STRING_RESULT: - return strtoll(str_value.ptr(),(char**) 0,10); + return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); case REAL_RESULT: return (longlong) (real_value+(real_value > 0 ? 0.5 : -0.5)); default: diff --git a/sql/item.h b/sql/item.h index a189789ba24..4dff0591c09 100644 --- a/sql/item.h +++ b/sql/item.h @@ -370,8 +370,14 @@ public: } ~Item_string() {} enum Type type() const { return STRING_ITEM; } - double val() { return atof(str_value.ptr()); } - longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); } + double val() + { + return my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)NULL); + } + longlong val_int() + { + return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); + } String *val_str(String*) { return (String*) &str_value; } int save_in_field(Field *field, bool no_conversions); void make_field(Send_field *field); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6737d668401..7698b0f6f68 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -57,7 +57,7 @@ static store_key *get_store_key(THD *thd, static bool make_simple_join(JOIN *join,TABLE *tmp_table); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); static void make_join_readinfo(JOIN *join,uint options); -static void join_free(JOIN *join); +static void join_free(JOIN *join, bool full); static bool only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables); static void update_depend_map(JOIN *join); static void update_depend_map(JOIN *join, ORDER *order); @@ -403,8 +403,8 @@ JOIN::optimize() { // quick abort delete procedure; - error= thd->net.report_error ? -1 : 1; - DBUG_RETURN(-1); // Return without cleanup + error= thd->fatal_error ? -1 : 1; + DBUG_RETURN(error); } if (cond_value == Item::COND_FALSE || @@ -902,7 +902,7 @@ JOIN::exec() DBUG_PRINT("info",("Creating group table")); /* Free first data from old join */ - join_free(this); + join_free(this, 0); if (make_simple_join(this, exec_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(this, group_list); @@ -953,7 +953,7 @@ JOIN::exec() if (exec_tmp_table->distinct) select_distinct=0; /* Each row is unique */ - join_free(this); /* Free quick selects */ + join_free(this, 0); /* Free quick selects */ if (select_distinct && ! group_list) { thd->proc_info="Removing duplicates"; @@ -1068,7 +1068,7 @@ JOIN::cleanup(THD *thd) DBUG_ENTER("JOIN::cleanup"); lock=0; // It's faster to unlock later - join_free(this); + join_free(this, 1); if (exec_tmp_table) free_tmp_table(thd, exec_tmp_table); delete select; @@ -3035,7 +3035,7 @@ bool error_if_full_join(JOIN *join) static void -join_free(JOIN *join) +join_free(JOIN *join, bool full) { JOIN_TAB *tab,*end; DBUG_ENTER("join_free"); @@ -3048,7 +3048,7 @@ join_free(JOIN *join) */ if (join->tables > join->const_tables) // Test for not-const tables free_io_cache(join->table[join->const_tables]); - if (join->select_lex->dependent) + if (join->select_lex->dependent && !full) for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++) { if (tab->table) @@ -4680,7 +4680,7 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) error=0; if (!table) // If sending data to client { - join_free(join); // Unlock all cursors + join_free(join, 0); // Unlock all cursors if (join->result->send_eof()) error= 1; // Don't send error } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5e5c9117c61..ed8e8f0fb51 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -664,7 +664,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild union_clause union_list union_option - precision opt_on_delete_item subselect_start opt_and + precision subselect_start opt_and subselect_end select_var_list select_var_list_init help opt_len END_OF_INPUT @@ -921,7 +921,7 @@ create_table_options_space_separated: create_table_options: create_table_option - | create_table_option create_table_options; + | create_table_option create_table_options | create_table_option ',' create_table_options; create_table_option: @@ -1387,7 +1387,6 @@ alter: } alter_list {} - ; | ALTER DATABASE ident opt_db_default_character_set { LEX *lex=Lex; @@ -2811,6 +2810,7 @@ select_var_list_init: YYABORT; } select_var_list + {} ; select_var_list: @@ -2942,6 +2942,7 @@ insert: Select->set_lock_for_tables($3); } insert_field_spec opt_insert_update + {} ; replace: