diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 338 |
1 files changed, 67 insertions, 271 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 870c341c148..6bbec63c258 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -19,11 +19,11 @@ #include "mysql_priv.h" #include "sql_acl.h" +#include "sql_select.h" #include <m_ctype.h> #include <my_dir.h> #include <hash.h> #include <nisam.h> -#include <assert.h> #ifdef __WIN__ #include <io.h> #endif @@ -195,251 +195,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) DBUG_RETURN(open_list); } - -/* - 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 -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_convert_fields"); - - while ((item=it++)) - { - char *pos; - Send_field field; - item->make_field(&field); - packet->length(0); - - if (thd->client_capabilities & CLIENT_PROTOCOL_41) - { - if (convert->store(packet,field.db_name, - (uint) strlen(field.db_name)) || - convert->store(packet,field.table_name, - (uint) strlen(field.table_name)) || - convert->store(packet,field.org_table_name, - (uint) strlen(field.org_table_name)) || - convert->store(packet,field.col_name, - (uint) strlen(field.col_name)) || - convert->store(packet,field.org_col_name, - (uint) strlen(field.org_col_name)) || - packet->realloc(packet->length()+10)) - goto err; - } - else - { - if (convert->store(packet,field.table_name, - (uint) strlen(field.table_name)) || - convert->store(packet,field.col_name, - (uint) strlen(field.col_name)) || - packet->realloc(packet->length()+10)) - goto err; - } - pos= (char*) packet->ptr()+packet->length(); - - if (!(thd->client_capabilities & CLIENT_LONG_FLAG)) - { - packet->length(packet->length()+9); - pos[0]=3; int3store(pos+1,field.length); - pos[4]=1; pos[5]=field.type; - pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals; - } - else - { - packet->length(packet->length()+10); - pos[0]=3; int3store(pos+1,field.length); - pos[4]=1; pos[5]=field.type; - pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals; - } - if (flag & 2) - { // Send default value - if (!(res=item->val_str(&tmp))) - { - if (net_store_null(packet)) - goto err; - } - 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 */ - } - DBUG_RETURN(0); - -err: - DBUG_RETURN(1); -} - - -/* - 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 -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) - { - if (net_store_data(packet,field.db_name) || - net_store_data(packet,field.table_name) || - net_store_data(packet,field.org_table_name) || - net_store_data(packet,field.col_name) || - net_store_data(packet,field.org_col_name) || - packet->realloc(packet->length()+10)) - return 1; - } - else - { - if (net_store_data(packet,field.table_name) || - net_store_data(packet,field.col_name) || - packet->realloc(packet->length()+10)) - return 1; - } - - pos= (char*) packet->ptr()+packet->length(); - - if (!(thd->client_capabilities & CLIENT_LONG_FLAG)) - { - packet->length(packet->length()+9); - pos[0]=3; int3store(pos+1,field.length); - pos[4]=1; pos[5]=field.type; - pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals; - } - else - { - packet->length(packet->length()+10); - pos[0]=3; int3store(pos+1,field.length); - pos[4]=1; pos[5]=field.type; - pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals; - } - if (flag & 2) - { // Send default value - if (!(res=item->val_str(&tmp))) - { - if (net_store_null(packet)) - return 1; - } - else if (net_store_data(packet,res->ptr(),res->length())) - return 1; - } - if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) - break; - } - return 0; -} - - -/* - 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) -{ - char buff[9]; // Big enough for store_length - CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->variables.convert_set; - DBUG_ENTER("send_fields"); - - if (thd->fatal_error) // We have got an error - goto err; - - if (flag & 1) - { // Packet with number of elements - char *pos=net_store_length(buff, (uint) list.elements); - (void) my_net_write(&thd->net, buff,(uint) (pos-buff)); - } - - /* - Avoid check conditions on convert() for each field - by having two different functions - */ - 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); - DBUG_RETURN(0); - -err: - send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */ - DBUG_RETURN(1); /* purecov: inspected */ -} - - /***************************************************************************** * Functions to free open table cache ****************************************************************************/ @@ -485,6 +240,7 @@ static void free_cache_entry(TABLE *table) DBUG_VOID_RETURN; } +/* Free resources allocated by filesort() and read_record() */ void free_io_cache(TABLE *table) { @@ -551,7 +307,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, close_old_data_files(thd,thd->open_tables,1,1); bool found=1; /* Wait until all threads has closed all the tables we had locked */ - DBUG_PRINT("info", ("Waiting for others threads to close their open tables")); + DBUG_PRINT("info", + ("Waiting for others threads to close their open tables")); while (found && ! thd->killed) { found=0; @@ -592,12 +349,40 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, } -/* Put all tables used by thread in free list */ +/* + Close all tables used by thread -void close_thread_tables(THD *thd, bool locked) + SYNOPSIS + close_thread_tables() + thd Thread handler + lock_in_use Set to 1 (0 = default) if caller has a lock on + LOCK_open + skip_derived Set to 1 (0 = default) if we should not free derived + tables. + + IMPLEMENTATION + Unlocks tables and frees derived tables. + Put all normal tables used by thread in free list. +*/ + +void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) { DBUG_ENTER("close_thread_tables"); + if (thd->derived_tables && !skip_derived) + { + TABLE *table, *next; + /* + Close all derived tables generated from questions like + SELECT * from (select * from t1)) + */ + for (table= thd->derived_tables ; table ; table= next) + { + next= table->next; + free_tmp_table(thd, table); + } + thd->derived_tables= 0; + } if (thd->locked_tables) { ha_commit_stmt(thd); // If select statement @@ -608,10 +393,11 @@ void close_thread_tables(THD *thd, bool locked) if (thd->lock) { - mysql_unlock_tables(thd, thd->lock); thd->lock=0; + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; } /* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */ - if (!locked) + if (!lock_in_use) VOID(pthread_mutex_lock(&LOCK_open)); safe_mutex_assert_owner(&LOCK_open); @@ -630,7 +416,7 @@ void close_thread_tables(THD *thd, bool locked) /* Tell threads waiting for refresh that something has happened */ VOID(pthread_cond_broadcast(&COND_refresh)); } - if (!locked) + if (!lock_in_use) VOID(pthread_mutex_unlock(&LOCK_open)); /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ DBUG_VOID_RETURN; @@ -798,7 +584,7 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name) uint key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1; TABLE *table,**prev; - int4store(key+key_length,thd->slave_proxy_id); + int4store(key+key_length,thd->variables.pseudo_thread_id); key_length += 4; prev= &thd->temporary_tables; @@ -838,7 +624,7 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db, (strmov((table->real_name=strmov(table->table_cache_key=key, db)+1), table_name) - table->table_cache_key)+1; - int4store(key+table->key_length,thd->slave_proxy_id); + int4store(key+table->key_length,thd->variables.pseudo_thread_id); table->key_length += 4; return 0; } @@ -960,7 +746,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) table->tablenr=thd->current_tablenr++; table->used_fields=0; table->const_table=0; - table->outer_join=table->null_row=table->maybe_null=0; + table->outer_join= table->null_row= table->maybe_null= table->force_index= 0; table->status=STATUS_NO_RECORD; table->keys_in_use_for_query= table->keys_in_use; table->used_keys= table->keys_for_keyread; @@ -992,7 +778,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, if (thd->killed) DBUG_RETURN(0); key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1; - int4store(key + key_length, thd->slave_proxy_id); + int4store(key + key_length, thd->variables.pseudo_thread_id); for (table=thd->temporary_tables; table ; table=table->next) { @@ -1006,6 +792,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, DBUG_RETURN(0); } table->query_id=thd->query_id; + thd->lex.tmp_table_used= 1; goto reset; } } @@ -1118,7 +905,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, table->tablenr=thd->current_tablenr++; table->used_fields=0; table->const_table=0; - table->outer_join=table->null_row=table->maybe_null=0; + table->outer_join= table->null_row= table->maybe_null= table->force_index= 0; table->status=STATUS_NO_RECORD; table->keys_in_use_for_query= table->keys_in_use; table->used_keys= table->keys_for_keyread; @@ -1189,6 +976,7 @@ bool reopen_table(TABLE *table,bool locked) tmp.status= table->status; tmp.keys_in_use_for_query= tmp.keys_in_use; tmp.used_keys= tmp.keys_for_keyread; + tmp.force_index= tmp.force_index; /* Get state */ tmp.key_length= table->key_length; @@ -1806,7 +1594,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, +1), table_name) - tmp_table->table_cache_key)+1; int4store(tmp_table->table_cache_key + tmp_table->key_length, - thd->slave_proxy_id); + thd->variables.pseudo_thread_id); tmp_table->key_length += 4; if (link_in_list) @@ -1898,6 +1686,7 @@ const Field *not_found_field= (Field*) 0x1; thd - pointer to current thread structure item - field item that should be found tables - tables for scaning + where - table where field found will be returned via this parameter report_error - if FALSE then do not report error if item not found and return not_found_field; @@ -1911,7 +1700,7 @@ const Field *not_found_field= (Field*) 0x1; Field * find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, - bool report_error) + TABLE_LIST **where, bool report_error) { Field *found=0; const char *db=item->db_name; @@ -1932,6 +1721,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, grant_option && !thd->master_access,1); if (find) { + (*where)= tables; if (find == WRONG_GRANT) return (Field*) 0; if (db || !thd->where) @@ -1951,19 +1741,15 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, if (!found_table && report_error) { char buff[NAME_LEN*2+1]; - if (db) + if (db && db[0]) { strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); table_name=buff; } if (report_error) { - if (thd->lex.current_select->get_master()->order_list.elements) - my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, ER(ER_TABLENAME_NOT_ALLOWED_HERE), - MYF(0), table_name, thd->where); - else - my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), - table_name, thd->where); + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + table_name, thd->where); } else return (Field*) not_found_field; @@ -1979,6 +1765,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, bool allow_rowid= tables && !tables->next; // Only one table for (; tables ; tables=tables->next) { + if (!tables->table) + { + if (report_error) + my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), + item->full_name(),thd->where); + return (Field*) not_found_field; + } + Field *field=find_field_in_table(thd,tables->table,name,length, grant_option && !thd->master_access, allow_rowid); @@ -1986,6 +1780,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, { if (field == WRONG_GRANT) return (Field*) 0; + (*where)= tables; if (found) { if (!thd->where) // Returns first found @@ -2158,8 +1953,8 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, for (uint i= 0; (item= it++); i++) { - if (item->check_cols(1) || - item->fix_fields(thd, tables, it.ref())) + if (item->fix_fields(thd, tables, it.ref()) || + item->check_cols(1)) DBUG_RETURN(-1); /* purecov: inspected */ item= *(it.ref()); //Item can be chenged in fix fields if (ref_pointer_array) @@ -2196,6 +1991,7 @@ bool setup_tables(TABLE_LIST *tables) table->maybe_null=test(table->outer_join=table_list->outer_join); table->tablenr=tablenr; table->map= (table_map) 1 << tablenr; + table->force_index= table_list->force_index; if (table_list->use_index) { key_map map= get_key_map_from_key_list(table, @@ -2318,7 +2114,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) if (*conds) { thd->where="where clause"; - if ((*conds)->check_cols(1) || (*conds)->fix_fields(thd, tables, conds)) + if ((*conds)->fix_fields(thd, tables, conds) || (*conds)->check_cols(1)) DBUG_RETURN(1); } @@ -2329,8 +2125,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) { /* Make a join an a expression */ thd->where="on clause"; - if (table->on_expr->check_cols(1) || - table->on_expr->fix_fields(thd, tables, &table->on_expr)) + if (table->on_expr->fix_fields(thd, tables, &table->on_expr) || + table->on_expr->check_cols(1)) DBUG_RETURN(1); thd->cond_count++; |