diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_heap.cc | 4 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/item.cc | 5 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 57 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 140 | ||||
-rw-r--r-- | sql/opt_range.cc | 4 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_handler.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 13 | ||||
-rw-r--r-- | sql/sql_select.cc | 28 | ||||
-rw-r--r-- | sql/sql_string.cc | 51 | ||||
-rw-r--r-- | sql/sql_string.h | 1 | ||||
-rw-r--r-- | sql/sql_table.cc | 4 | ||||
-rw-r--r-- | sql/sql_update.cc | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 4 |
16 files changed, 230 insertions, 102 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 656224d4a7a..807b6e35a29 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -38,7 +38,10 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) HA_CREATE_INFO create_info; bzero(&create_info, sizeof(create_info)); if (!create(name, table, &create_info)) + { file= heap_open(name, mode); + implicit_emptied= 1; + } } ref_length= sizeof(HEAP_PTR); return (file ? 0 : 1); @@ -174,7 +177,6 @@ void ha_heap::info(uint flag) index_file_length=info.index_length; max_data_file_length= info.max_records* info.reclength; delete_length= info.deleted * info.reclength; - implicit_emptied= info.implicit_emptied; if (flag & HA_STATUS_AUTO) auto_increment_value= info.auto_increment; } diff --git a/sql/handler.cc b/sql/handler.cc index afeec26f034..5aa3967edb6 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -657,7 +657,7 @@ int ha_delete_table(enum db_type table_type, const char *path) { /* Ensure that table handler get path in lower case */ strmov(tmp_path, path); - casedn_str(tmp_path); + my_casedn_str(system_charset_info, tmp_path); path= tmp_path; } int error=file->delete_table(path); @@ -1159,7 +1159,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, { /* Ensure that handler gets name in lower case */ strmov(name_buff, name); - casedn_str(name_buff); + my_casedn_str(system_charset_info, name_buff); name= name_buff; } diff --git a/sql/item.cc b/sql/item.cc index 4d06d0d7765..b9a6a164a86 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -175,12 +175,13 @@ bool Item::eq(const Item *item, bool binary_cmp) const !my_strcasecmp(system_charset_info,name,item->name); } + bool Item_string::eq(const Item *item, bool binary_cmp) const { if (type() == item->type()) { if (binary_cmp) - return !sortcmp(&str_value, &item->str_value, &my_charset_bin); + return !stringcmp(&str_value, &item->str_value); return !sortcmp(&str_value, &item->str_value, collation.collation); } return 0; @@ -1823,7 +1824,7 @@ bool field_is_equal_to_item(Field *field,Item *item) if (item->null_value) return 1; // This must be true field->val_str(&field_tmp,&field_tmp); - return !sortcmp(&field_tmp,item_result,&my_charset_bin); + return !stringcmp(&field_tmp,item_result); } if (res_type == INT_RESULT) return 1; // Both where of type int diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4046a4d6414..1bba934cf8f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -293,6 +293,17 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name()); return 1; } + if (my_binary_compare(cmp_collation.collation)) + { + /* + We are using binary collation, change to compare byte by byte, + without removing end space + */ + if (func == &Arg_comparator::compare_string) + func= &Arg_comparator::compare_binary_string; + else if (func == &Arg_comparator::compare_e_string) + func= &Arg_comparator::compare_e_binary_string; + } } return 0; } @@ -313,6 +324,39 @@ int Arg_comparator::compare_string() return -1; } + +/* + Compare strings byte by byte. End spaces are also compared. + + RETURN + < 0 *a < *b + 0 *b == *b + > 0 *a > *b +*/ + +int Arg_comparator::compare_binary_string() +{ + String *res1,*res2; + if ((res1= (*a)->val_str(&owner->tmp_value1))) + { + if ((res2= (*b)->val_str(&owner->tmp_value2))) + { + owner->null_value= 0; + uint res1_length= res1->length(); + uint res2_length= res2->length(); + int cmp= memcmp(res1->ptr(), res2->ptr(), min(res1_length,res2_length)); + return cmp ? cmp : (int) (res1_length - res2_length); + } + } + owner->null_value= 1; + return -1; +} + + +/* + Compare strings, but take into account that NULL == NULL +*/ + int Arg_comparator::compare_e_string() { String *res1,*res2; @@ -324,6 +368,17 @@ int Arg_comparator::compare_e_string() } +int Arg_comparator::compare_e_binary_string() +{ + String *res1,*res2; + res1= (*a)->val_str(&owner->tmp_value1); + res2= (*b)->val_str(&owner->tmp_value2); + if (!res1 || !res2) + return test(res1 == res2); + return test(stringcmp(res1, res2) == 0); +} + + int Arg_comparator::compare_real() { double val1= (*a)->val(); @@ -2132,7 +2187,7 @@ longlong Item_func_regex::val_int() null_value=1; return 0; } - if (!regex_compiled || sortcmp(res2,&prev_regexp,&my_charset_bin)) + if (!regex_compiled || stringcmp(res2,&prev_regexp)) { prev_regexp.copy(*res2); if (regex_compiled) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 4e9628c8db9..3c70a50502a 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -63,10 +63,12 @@ public: inline int compare() { return (this->*func)(); } int compare_string(); // compare args[0] & args[1] + int compare_binary_string(); // compare args[0] & args[1] int compare_real(); // compare args[0] & args[1] int compare_int(); // compare args[0] & args[1] int compare_row(); // compare args[0] & args[1] int compare_e_string(); // compare args[0] & args[1] + int compare_e_binary_string(); // compare args[0] & args[1] int compare_e_real(); // compare args[0] & args[1] int compare_e_int(); // compare args[0] & args[1] int compare_e_row(); // compare args[0] & args[1] diff --git a/sql/log_event.cc b/sql/log_event.cc index 84757a0a1f2..f64f740da30 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -290,6 +290,8 @@ Log_event::Log_event(const char* buf, bool old_format) int Log_event::exec_event(struct st_relay_log_info* rli) { + DBUG_ENTER("Log_event::exec_event"); + /* rli is null when (as far as I (Guilhem) know) the caller is @@ -342,7 +344,7 @@ int Log_event::exec_event(struct st_relay_log_info* rli) rli->last_master_timestamp= when; } } - return 0; + DBUG_RETURN(0); } @@ -592,11 +594,13 @@ Error in Log_event::read_log_event(): '%s', data_len: %d, event_type: %d", Log_event* Log_event::read_log_event(const char* buf, int event_len, const char **error, bool old_format) { + DBUG_ENTER("Log_event::read_log_event"); + if (event_len < EVENT_LEN_OFFSET || (uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET)) { *error="Sanity check failed"; // Needed to free buffer - return NULL; // general sanity check - will fail on a partial read + DBUG_RETURN(NULL); // general sanity check - will fail on a partial read } Log_event* ev = NULL; @@ -658,16 +662,16 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len, if (!force_opt) { *error= "Found invalid event in binary log"; - return 0; + DBUG_RETURN(0); } ev= new Unknown_log_event(buf, old_format); #else *error= "Found invalid event in binary log"; - return 0; + DBUG_RETURN(0); #endif } ev->cached_event_len = event_len; - return ev; + DBUG_RETURN(ev); } #ifdef MYSQL_CLIENT @@ -1249,38 +1253,21 @@ void Load_log_event::pack_info(Protocol *protocol) memcpy(pos, table_name, table_name_len); pos+= table_name_len; - if (sql_ex.field_term_len) - { - pos= strmov(pos, " FIELDS TERMINATED BY "); - pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len); - } - - if (sql_ex.enclosed_len) - { - if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) - pos= strmov(pos, " OPTIONALLY "); - pos= strmov(pos, " ENCLOSED BY "); - pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len); - } + /* We have to create all optinal fields as the default is not empty */ + pos= strmov(pos, " FIELDS TERMINATED BY "); + pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len); + if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) + pos= strmov(pos, " OPTIONALLY "); + pos= strmov(pos, " ENCLOSED BY "); + pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len); - if (sql_ex.escaped_len) - { - pos= strmov(pos, " ESCAPED BY "); - pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len); - } - - bool line_lexem_added= false; - if (sql_ex.line_term_len) - { - pos= strmov(pos, " LINES TERMINATED BY "); - pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len); - line_lexem_added= true; - } + pos= strmov(pos, " ESCAPED BY "); + pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len); + pos= strmov(pos, " LINES TERMINATED BY "); + pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len); if (sql_ex.line_start_len) { - if (!line_lexem_added) - pos= strmov(pos," LINES"); pos= strmov(pos, " STARTING BY "); pos= pretty_print_str(pos, sql_ex.line_start, sql_ex.line_start_len); } @@ -1455,9 +1442,10 @@ Load_log_event::Load_log_event(const char *buf, int event_len, field_lens(0), field_block_len(0), table_name(0), db(0), fname(0), local_fname(FALSE) { - if (!event_len) // derived class, will call copy_log_event() itself - return; - copy_log_event(buf, event_len, old_format); + DBUG_ENTER("Load_log_event"); + if (event_len) // derived class, will call copy_log_event() itself + copy_log_event(buf, event_len, old_format); + DBUG_VOID_RETURN; } @@ -1472,6 +1460,8 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, char* buf_end = (char*)buf + event_len; uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; const char* data_head = buf + header_len; + DBUG_ENTER("Load_log_event::copy_log_event"); + slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET); exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET); skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET); @@ -1484,19 +1474,19 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, get_data_body_offset()); if ((int) event_len < body_offset) - return 1; + DBUG_RETURN(1); /* Sql_ex.init() on success returns the pointer to the first byte after the sql_ex structure, which is the start of field lengths array. */ if (!(field_lens=(uchar*)sql_ex.init((char*)buf + body_offset, - buf_end, - buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) - return 1; - + buf_end, + buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) + DBUG_RETURN(1); + data_len = event_len - body_offset; if (num_fields > data_len) // simple sanity check against corruption - return 1; + DBUG_RETURN(1); for (uint i = 0; i < num_fields; i++) field_block_len += (uint)field_lens[i] + 1; @@ -1506,7 +1496,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, fname = db + db_len + 1; fname_len = strlen(fname); // null termination is accomplished by the caller doing buf[event_len]=0 - return 0; + DBUG_RETURN(0); } @@ -1524,6 +1514,7 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db) void Load_log_event::print(FILE* file, bool short_form, char* last_db, bool commented) { + DBUG_ENTER("Load_log_event::print"); if (!short_form) { print_header(file); @@ -1555,42 +1546,26 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db, fprintf(file," IGNORE "); fprintf(file, "INTO TABLE %s ", table_name); - if (sql_ex.field_term) - { - fprintf(file, " FIELDS TERMINATED BY "); - pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len); - } + fprintf(file, " FIELDS TERMINATED BY "); + pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len); - if (sql_ex.enclosed) - { - if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) - fprintf(file," OPTIONALLY "); - fprintf(file, " ENCLOSED BY "); - pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len); - } + if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG) + fprintf(file," OPTIONALLY "); + fprintf(file, " ENCLOSED BY "); + pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len); - if (sql_ex.escaped) - { - fprintf(file, " ESCAPED BY "); - pretty_print_str(file, sql_ex.escaped, sql_ex.escaped_len); - } + fprintf(file, " ESCAPED BY "); + pretty_print_str(file, sql_ex.escaped, sql_ex.escaped_len); - bool line_lexem_added= false; - if (sql_ex.line_term) - { - fprintf(file," LINES TERMINATED BY "); - pretty_print_str(file, sql_ex.line_term, sql_ex.line_term_len); - line_lexem_added= true; - } + fprintf(file," LINES TERMINATED BY "); + pretty_print_str(file, sql_ex.line_term, sql_ex.line_term_len); + if (sql_ex.line_start) { - if (!line_lexem_added) - fprintf(file," LINES"); fprintf(file," STARTING BY "); pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len); } - if ((long) skip_lines > 0) fprintf(file, " IGNORE %ld LINES", (long) skip_lines); @@ -1611,6 +1586,7 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db, } fprintf(file, ";\n"); + DBUG_VOID_RETURN; } #endif /* MYSQL_CLIENT */ @@ -1877,8 +1853,11 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len, // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; uint ident_offset; + DBUG_ENTER("Rotate_log_event"); + if (event_len < header_size) - return; + DBUG_VOID_RETURN; + buf += header_size; if (old_format) { @@ -1897,8 +1876,9 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len, ident_offset, (uint) ident_len, MYF(MY_WME)))) - return; + DBUG_VOID_RETURN; alloced = 1; + DBUG_VOID_RETURN; } @@ -2593,7 +2573,9 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex, fake_base(0),block(block_arg),block_len(block_len_arg), file_id(thd_arg->file_id = mysql_bin_log.next_file_id()) { + DBUG_ENTER("Create_file_log_event"); sql_ex.force_new_format(); + DBUG_VOID_RETURN; } #endif /* !MYSQL_CLIENT */ @@ -2650,8 +2632,10 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len, :Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0) { int block_offset; + DBUG_ENTER("Create_file_log_event"); + if (copy_log_event(buf,len,old_format)) - return; + DBUG_VOID_RETURN; if (!old_format) { file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + @@ -2669,6 +2653,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len, sql_ex.force_new_format(); inited_from_old = 1; } + DBUG_VOID_RETURN; } @@ -2821,11 +2806,13 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, const char* db_arg, Append_block_log_event::Append_block_log_event(const char* buf, int len) :Log_event(buf, 0),block(0) { + DBUG_ENTER("Append_block_log_event"); if ((uint)len < APPEND_BLOCK_EVENT_OVERHEAD) - return; + DBUG_VOID_RETURN; file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET); block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD; block_len = len - APPEND_BLOCK_EVENT_OVERHEAD; + DBUG_VOID_RETURN; } @@ -2888,6 +2875,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli) char *p= slave_load_file_stem(fname, file_id, server_id); int fd; int error = 1; + DBUG_ENTER("Append_block_log_event::exec_event"); memcpy(p, ".data", 6); if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0) @@ -2905,7 +2893,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli) err: if (fd >= 0) my_close(fd, MYF(0)); - return error ? error : Log_event::exec_event(rli); + DBUG_RETURN(error ? error : Log_event::exec_event(rli)); } #endif diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d1f42ac865e..1dbe883aef4 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1064,8 +1064,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, like_error= my_like_range(field->charset(), res->ptr(), res->length(), - ((Item_func_like*)(param->cond))->escape - wild_prefix, wild_one, wild_many, + ((Item_func_like*)(param->cond))->escape, + wild_one, wild_many, field_length, min_str+offset, max_str+offset, &min_length, &max_length); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 7a1fd091e7c..0323e90a166 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -363,7 +363,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) { /* Convert database to lower case */ strmov(tmp_db, db); - casedn_str(tmp_db); + my_casedn_str(system_charset_info, tmp_db); db= tmp_db; } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 6db97ab3c41..d0f241b3291 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -288,12 +288,12 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db, TABLE **ptr; DBUG_ASSERT(db); - dblen= *db ? strlen(db)+1 : 0; + dblen= strlen(db); ptr= &(thd->handler_tables); for (TABLE *table= *ptr; table ; table= *ptr) { - if ((!dblen || !memcmp(table->table_cache_key, db, dblen)) && + if ((db == any_db || !memcmp(table->table_cache_key, db, dblen)) && !my_strcasecmp(system_charset_info, (is_alias ? table->table_name : table->real_name), table_name)) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f7bbfdae2b3..dd68337d5dd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1451,7 +1451,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_casedn_str(files_charset_info, table_list.real_name); remove_escape(table_list.real_name); // This can't have wildcards - if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege)) + if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege, + 0, 0)) break; if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2,0)) break; @@ -1771,7 +1772,7 @@ mysql_execute_command(THD *thd) */ if (table_rules_on && tables && !tables_ok(thd,tables) && ((lex->sql_command != SQLCOM_DELETE_MULTI) || - !tables_ok(thd,(TABLE_LIST *)thd->lex.auxilliary_table_list.first))) + !tables_ok(thd,(TABLE_LIST *)thd->lex->auxilliary_table_list.first))) { /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); @@ -2103,7 +2104,7 @@ mysql_execute_command(THD *thd) ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? CREATE_TMP_ACL : CREATE_ACL); - lex->create_info.alias= tables->alias; + lex->create_info.alias= create_table->alias; if (check_access(thd, want_priv, create_table->db, &create_table->grant.privilege, 0, 0) || check_merge_table_access(thd, create_table->db, @@ -2872,7 +2873,7 @@ mysql_execute_command(THD *thd) remove_escape(db); // Fix escaped '_' remove_escape(tables->real_name); if (check_access(thd,SELECT_ACL | EXTRA_ACL,db, - &tables->grant.privilege)) + &tables->grant.privilege, 0, 0)) goto error; /* purecov: inspected */ if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0)) goto error; @@ -2977,7 +2978,7 @@ mysql_execute_command(THD *thd) if (check_access(thd,CREATE_ACL,lex->name,0,1,0)) break; res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name), - lex->create_info.options,0); + &lex->create_info, 0); break; } case SQLCOM_DROP_DB: @@ -3393,7 +3394,7 @@ static int check_one_table_access(THD *thd, ulong privilege, if (subselects_tables) { tables->next= subselects_tables; - if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0))) + if ((check_table_access(thd, SELECT_ACL, subselects_tables,0))) return 1; } return 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9cb8bb7b768..592820e6e19 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2864,7 +2864,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, If quick_select was used on a part of this key, we know the maximum number of rows that the key can match. */ - if (table->quick_keys & ((key_map) 1 << key) && + if (table->quick_keys.is_set(key) && table->quick_key_parts[key] <= max_key_part && records > (double) table->quick_rows[key]) tmp= records= (double) table->quick_rows[key]; @@ -6717,8 +6717,11 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) /* We can remove binary fields and numerical fields except float, as float comparison isn't 100 % secure + We have to keep binary strings to be able to check for end spaces */ if (field->binary() && + field->real_type() != FIELD_TYPE_STRING && + field->real_type() != FIELD_TYPE_VAR_STRING && (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0)) { return !store_val_in_field(field,right_item); @@ -7931,6 +7934,29 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, } +/* + Intitialize the GROUP BY list. + + SYNOPSIS + setup_group() + thd Thread handler + ref_pointer_array We store references to all fields that was not in + 'fields' here. + fields All fields in the select part. Any item in 'order' + that is part of these list is replaced by a pointer + to this fields. + all_fields Total list of all unique fields used by the select. + All items in 'order' that was not part of fields will + be added first to this list. + order The fields we should do GROUP BY on. + hidden_group_fields Pointer to flag that is set to 1 if we added any fields + to all_fields. + + RETURN + 0 ok + 1 error (probably out of memory) +*/ + int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, List<Item> &fields, List<Item> &all_fields, ORDER *order, diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 422b1ec3b4b..83a048297af 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -699,11 +699,56 @@ void String::qs_append(const char &c) } -int sortcmp(const String *x,const String *y, CHARSET_INFO *cs) +/* + Compare strings according to collation, without end space. + + SYNOPSIS + sortcmp() + s First string + t Second string + cs Collation + + NOTE: + Normally this is case sensitive comparison + + RETURN + < 0 s < t + 0 s == t + > 0 s > t +*/ + + +int sortcmp(const String *s,const String *t, CHARSET_INFO *cs) { return cs->coll->strnncollsp(cs, - (unsigned char *) x->ptr(),x->length(), - (unsigned char *) y->ptr(),y->length()); + (unsigned char *) s->ptr(),s->length(), + (unsigned char *) t->ptr(),t->length()); +} + + +/* + Compare strings byte by byte. End spaces are also compared. + + SYNOPSIS + stringcmp() + s First string + t Second string + + NOTE: + Strings are compared as a stream of unsigned chars + + RETURN + < 0 s < t + 0 s == t + > 0 s > t +*/ + + +int stringcmp(const String *s,const String *t) +{ + uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len); + int cmp= memcmp(s->ptr(), t->ptr(), len); + return (cmp) ? cmp : (int) (s_len - t_len); } diff --git a/sql/sql_string.h b/sql/sql_string.h index 163156fdfe2..cdfb00276d4 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -221,6 +221,7 @@ public: inline void caseup() { my_caseup(str_charset,Ptr,str_length); } inline void casedn() { my_casedn(str_charset,Ptr,str_length); } friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); + friend int stringcmp(const String *a,const String *b); friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); uint32 numchars(); int charpos(int i,uint32 offset=0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 922775083d5..12494703419 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1152,11 +1152,11 @@ mysql_rename_table(enum db_type base, { /* Table handler expects to get all file names as lower case */ strmov(tmp_from, old_name); - casedn_str(tmp_from); + my_casedn_str(system_charset_info, tmp_from); old_name= tmp_from; strmov(tmp_to, new_name); - casedn_str(tmp_to); + my_casedn_str(system_charset_info, tmp_to); new_name= tmp_to; } (void) sprintf(from,"%s/%s/%s",mysql_data_home,old_db,old_name); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1e702a9517c..977dd2595de 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -439,7 +439,14 @@ int mysql_multi_update(THD *thd, for (tl= table_list ; tl ; tl=tl->next) { TABLE *table= tl->table; - table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege); + /* + Update of derived tables is checked later + We don't check privileges here, becasue then we would get error + "UPDATE command denided .. for column N" instead of + "Target table ... is not updatable" + */ + if (!tl->derived) + table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege); } if (thd->lex->derived_tables) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bd51df8810c..7ef5d219f07 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4626,8 +4626,8 @@ table_ident: ; table_ident_ref: - ident { LEX_STRING db={"",0}; $$=new Table_ident(db,$1,0); } - | ident '.' ident { $$=new Table_ident($1,$3,0);} + ident { LEX_STRING db={(char*) any_db,3}; $$=new Table_ident(YYTHD, db,$1,0); } + | ident '.' ident { $$=new Table_ident(YYTHD, $1,$3,0);} ; IDENT_sys: |