diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 226 |
1 files changed, 149 insertions, 77 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6185b031c2e..a8115c15412 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -19,7 +19,6 @@ #include "mysql_priv.h" #include "sql_acl.h" -#include <thr_alarm.h> #include <m_ctype.h> #include <my_dir.h> #include <hash.h> @@ -33,7 +32,7 @@ TABLE *unused_tables; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */ static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, - const char *name, const char *alias, bool locked); + const char *name, const char *alias); static void free_cache_entry(TABLE *entry); static void mysql_rm_tmp_tables(void); static key_map get_key_map_from_key_list(TABLE *table, @@ -110,10 +109,27 @@ static void check_unused(void) #define check_unused() #endif +/* + Create a list for all open tables matching SQL expression + + SYNOPSIS + list_open_tables() + thd Thread THD + wild SQL like expression + + NOTES + One gets only a list of tables for which one has any kind of privilege. + db and table names are allocated in result struct, so one doesn't need + a lock on LOCK_open when traversing the return list. + + RETURN VALUES + NULL Error (Probably OOM) + # Pointer to list of names of open tables. +*/ + OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) { int result = 0; - uint col_access=thd->col_access; OPEN_TABLE_LIST **start_list, *open_list; TABLE_LIST table_list; char name[NAME_LEN*2]; @@ -179,13 +195,25 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) DBUG_RETURN(open_list); } + /* - Send name and type of result to client. - Sum fields has table name empty and field_name. - flag is a bit mask with the following functions: - 1 send number of rows - 2 send default values - 4 Don't convert field names + Send name and type of result to client converted to a given char set + + SYNOPSIS + send_convert_fields() + THD Thread data object + list List of items to send to client + convert object used to convertation to another character set + flag Bit mask with the following functions: + 2 send default values + 4 Don't convert field names + + DESCRIPTION + Sum fields has table name empty and field_name. + + RETURN VALUES + 0 ok + 1 Error (Note that in this case the error is not sent to the client) */ bool @@ -194,16 +222,15 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag) List_iterator_fast<Item> it(list); Item *item; char buff[80]; - String tmp((char*) buff,sizeof(buff),default_charset_info); String *res,*packet= &thd->packet; - + DBUG_ENTER("send_fields"); + while ((item=it++)) { char *pos; Send_field field; item->make_field(&field); - packet->length(0); if (thd->client_capabilities & CLIENT_PROTOCOL_41) @@ -219,7 +246,7 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag) convert->store(packet,field.org_col_name, (uint) strlen(field.org_col_name)) || packet->realloc(packet->length()+10)) - return 1; + goto err; } else { @@ -228,9 +255,8 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag) convert->store(packet,field.col_name, (uint) strlen(field.col_name)) || packet->realloc(packet->length()+10)) - return 1; + goto err; } - pos= (char*) packet->ptr()+packet->length(); if (!(thd->client_capabilities & CLIENT_LONG_FLAG)) @@ -252,24 +278,38 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag) if (!(res=item->val_str(&tmp))) { if (net_store_null(packet)) - return 1; + goto err; } - else if (net_store_data(packet,res->ptr(),res->length())) - return 1; + else if (convert->store(packet,res->ptr(),res->length())) + goto err; } if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) break; /* purecov: inspected */ } return 0; + +err: + return 1; } + /* - Send name and type of result to client. - Sum fields has table name empty and field_name - flag is a bit mask with the following functios: - 1 send number of rows - 2 send default values - 4 Don't convert field names + Send name and type of result to client. + + SYNOPSIS + send_non_convert_fields() + THD Thread data object + list List of items to send to client + flag Bit mask with the following functions: + 2 send default values + 4 Don't convert field names + + DESCRIPTION + Sum fields has table name empty and field_name. + + RETURN VALUES + 0 ok + 1 Error */ bool @@ -278,16 +318,15 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag) List_iterator_fast<Item> it(list); Item *item; char buff[80]; - + String tmp((char*) buff,sizeof(buff),default_charset_info); String *res,*packet= &thd->packet; - + while ((item=it++)) { char *pos; Send_field field; item->make_field(&field); - packet->length(0); if (thd->client_capabilities & CLIENT_PROTOCOL_41) @@ -307,7 +346,7 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag) packet->realloc(packet->length()+10)) return 1; } - + pos= (char*) packet->ptr()+packet->length(); if (!(thd->client_capabilities & CLIENT_LONG_FLAG)) @@ -340,23 +379,35 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag) return 0; } -/****************************************************************************** -** Send name and type of result to client. -** Sum fields has table name empty and field_name. -** flag is a bit mask with the following functions: -** 1 send number of rows -** 2 send default values -** 4 Don't convert field names -******************************************************************************/ + +/* + Send name and type of result to client. + + SYNOPSIS + send_fields() + THD Thread data object + list List of items to send to client + convert object used to convertation to another character set + flag Bit mask with the following functions: + 1 send number of rows + 2 send default values + 4 Don't convert field names + + DESCRIPTION + Sum fields has table name empty and field_name. + Uses send_fields_convert() and send_fields() depending on + if we have an active character set convert or not. + + RETURN VALUES + 0 ok + 1 Error (Note that in this case the error is not sent to the client) +*/ bool -send_fields(THD *thd,List<Item> &list,uint flag) +send_fields(THD *thd, List<Item> &list, uint flag) { - List_iterator_fast<Item> it(list); - char buff[80]; CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set; - - String tmp((char*) buff,sizeof(buff),default_charset_info); + DBUG_ENTER("send_fields"); if (thd->fatal_error) // We have got an error goto err; @@ -367,20 +418,24 @@ send_fields(THD *thd,List<Item> &list,uint flag) (void) my_net_write(&thd->net, buff,(uint) (pos-buff)); } - /* Avoid check conditions on convert() for each field - by having two diffrent functions + /* + Avoid check conditions on convert() for each field + by having two different functions */ - if (convert && send_convert_fields(thd,list,convert,flag)) - goto err; - - else if(send_non_convert_fields(thd,list,flag)) + if (convert) + { + if (send_convert_fields(thd, list, convert, flag)) + goto err; + } + else if (send_non_convert_fields(thd, list, flag)) goto err; send_eof(&thd->net); return 0; + err: send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ - return 1; /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ } @@ -396,10 +451,21 @@ void intern_close_table(TABLE *table) VOID(closefrm(table)); // close file } +/* + Remove table from the open table cache + + SYNOPSIS + free_cache_entry() + table Table to remove + + NOTE + We need to have a lock on LOCK_open when calling this +*/ static void free_cache_entry(TABLE *table) { DBUG_ENTER("free_cache_entry"); + safe_mutex_assert_owner(&LOCK_open); intern_close_table(table); if (!table->in_use) @@ -546,6 +612,7 @@ void close_thread_tables(THD *thd, bool locked) /* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */ if (!locked) VOID(pthread_mutex_lock(&LOCK_open)); + safe_mutex_assert_owner(&LOCK_open); DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); @@ -671,12 +738,10 @@ void close_temporary_tables(THD *thd) } if (query && found_user_tables && mysql_bin_log.is_open()) { - uint save_query_len = thd->query_length; - *--end = 0; // Remove last ',' - thd->query_length = (uint)(end-query); - Query_log_event qinfo(thd, query); + /* The -1 is to remove last ',' */ + Query_log_event qinfo(thd, query, (ulong)(end-query)-1); + qinfo.error_code=0; mysql_bin_log.write(&qinfo); - thd->query_length = save_query_len; } thd->temporary_tables=0; } @@ -789,11 +854,13 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find) /* When we call the following function we must have a lock on - LOCK_OPEN ; This lock will be unlocked on return. + LOCK_open ; This lock will be unlocked on return. */ void wait_for_refresh(THD *thd) { + safe_mutex_assert_owner(&LOCK_open); + /* Wait until the current table is up to date */ const char *proc_info; thd->mysys_var->current_mutex= &LOCK_open; @@ -811,6 +878,7 @@ void wait_for_refresh(THD *thd) pthread_mutex_unlock(&thd->mysys_var->mutex); } + TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("reopen_name_locked_table"); @@ -827,7 +895,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1; pthread_mutex_lock(&LOCK_open); - if (open_unireg_entry(thd, table, db, table_name, table_name, 1) || + if (open_unireg_entry(thd, table, db, table_name, table_name) || !(table->table_cache_key =memdup_root(&table->mem_root,(char*) key, key_length))) { @@ -849,7 +917,8 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) table->const_table=0; table->outer_join=table->null_row=table->maybe_null=0; table->status=STATUS_NO_RECORD; - table->keys_in_use_for_query=table->used_keys= table->keys_in_use; + table->keys_in_use_for_query= table->keys_in_use; + table->used_keys= table->keys_for_keyread; DBUG_RETURN(table); } @@ -959,8 +1028,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) + { + VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(NULL); - if (open_unireg_entry(thd, table,db,table_name,alias,1) || + } + if (open_unireg_entry(thd, table,db,table_name,alias) || !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key, key_length))) { @@ -1003,7 +1075,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, table->const_table=0; table->outer_join=table->null_row=table->maybe_null=0; table->status=STATUS_NO_RECORD; - table->keys_in_use_for_query=table->used_keys= table->keys_in_use; + table->keys_in_use_for_query= table->keys_in_use; + table->used_keys= table->keys_for_keyread; DBUG_ASSERT(table->key_read == 0); DBUG_RETURN(table); } @@ -1048,9 +1121,9 @@ bool reopen_table(TABLE *table,bool locked) #endif if (!locked) VOID(pthread_mutex_lock(&LOCK_open)); + safe_mutex_assert_owner(&LOCK_open); - if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name, - locked)) + if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name)) goto end; free_io_cache(table); @@ -1069,7 +1142,8 @@ bool reopen_table(TABLE *table,bool locked) tmp.null_row= table->null_row; tmp.maybe_null= table->maybe_null; tmp.status= table->status; - tmp.keys_in_use_for_query=tmp.used_keys=tmp.keys_in_use; + tmp.keys_in_use_for_query= tmp.keys_in_use; + tmp.used_keys= tmp.keys_for_keyread; /* Get state */ tmp.key_length= table->key_length; @@ -1138,6 +1212,8 @@ bool close_data_tables(THD *thd,const char *db, const char *table_name) bool reopen_tables(THD *thd,bool get_locks,bool in_refresh) { DBUG_ENTER("reopen_tables"); + safe_mutex_assert_owner(&LOCK_open); + if (!thd->open_tables) DBUG_RETURN(0); @@ -1288,7 +1364,6 @@ bool wait_for_tables(THD *thd) /* Now we can open all tables without any interference */ thd->proc_info="Reopen tables"; result=reopen_tables(thd,0,0); - } pthread_mutex_unlock(&LOCK_open); thd->proc_info=0; @@ -1353,7 +1428,7 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name) */ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, - const char *name, const char *alias, bool locked) + const char *name, const char *alias) { char path[FN_REFLEN]; int error; @@ -1373,21 +1448,17 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, table_list.db=(char*) db; table_list.name=(char*) name; table_list.next=0; - if (!locked) - pthread_mutex_lock(&LOCK_open); + safe_mutex_assert_owner(&LOCK_open); + if ((error=lock_table_name(thd,&table_list))) { if (error < 0) { - if (!locked) - pthread_mutex_unlock(&LOCK_open); goto err; } if (wait_for_locked_table_names(thd,&table_list)) { unlock_table_name(thd,&table_list); - if (!locked) - pthread_mutex_unlock(&LOCK_open); goto err; } } @@ -1417,9 +1488,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, thd->net.last_error[0]=0; // Clear error message thd->net.last_errno=0; } - if (locked) - pthread_mutex_lock(&LOCK_open); // Get back original lock + pthread_mutex_lock(&LOCK_open); unlock_table_name(thd,&table_list); + if (error) goto err; } @@ -1478,9 +1549,9 @@ int open_tables(THD *thd,TABLE_LIST *start) } } *prev_table=0; + pthread_mutex_unlock(&LOCK_open); if (found) VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh - pthread_mutex_unlock(&LOCK_open); goto restart; } result= -1; // Fatal error @@ -1698,7 +1769,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, { field->query_id=thd->query_id; table->used_fields++; - table->used_keys&=field->part_of_key; + table->used_keys&= field->part_of_key; } else thd->dupp_field=field; @@ -1905,7 +1976,8 @@ bool setup_tables(TABLE_LIST *tables) table->const_table=0; table->outer_join=table->null_row=0; table->status=STATUS_NO_RECORD; - table->keys_in_use_for_query=table->used_keys= table->keys_in_use; + table->keys_in_use_for_query= table->keys_in_use; + table->used_keys= table->keys_for_keyread; table->maybe_null=test(table->outer_join=table_list->outer_join); table->tablenr=tablenr; table->map= (table_map) 1 << tablenr; @@ -1995,7 +2067,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, if (field->query_id == thd->query_id) thd->dupp_field=field; field->query_id=thd->query_id; - table->used_keys&=field->part_of_key; + table->used_keys&= field->part_of_key; } /* All fields are used */ table->used_fields=table->fields; @@ -2184,6 +2256,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) DBUG_ENTER("mysql_create_index"); bzero((char*) &create_info,sizeof(create_info)); create_info.db_type=DB_TYPE_DEFAULT; + /* TODO: Fix to use database character set */ create_info.table_charset=default_charset_info; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, @@ -2322,6 +2395,7 @@ int setup_ftfuncs(THD *thd) return 0; } + int init_ftfuncs(THD *thd, bool no_order) { if (thd->lex.select->ftfunc_list.elements) @@ -2332,9 +2406,7 @@ int init_ftfuncs(THD *thd, bool no_order) thd->proc_info="FULLTEXT initialization"; while ((ifm=li++)) - { ifm->init_search(no_order); - } } return 0; } |