diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 353 |
1 files changed, 164 insertions, 189 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 656758623bc..7f6ffd04d98 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -15,7 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Basic functions neaded by many modules */ +/* Basic functions needed by many modules */ #include "mysql_priv.h" #include "sql_acl.h" @@ -34,8 +34,6 @@ 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); -static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, - const char *table_name, List_iterator<Item> *it); 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, @@ -111,75 +109,73 @@ static void check_unused(void) #define check_unused() #endif -int list_open_tables(THD *thd,List<char> *tables, const char *db, - const char *wild) +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]; DBUG_ENTER("list_open_tables"); + VOID(pthread_mutex_lock(&LOCK_open)); bzero((char*) &table_list,sizeof(table_list)); + start_list= &open_list; + open_list=0; - for (uint idx=0 ; idx < open_cache.records; idx++) + for (uint idx=0 ; result == 0 && idx < open_cache.records; idx++) { + OPEN_TABLE_LIST *table; TABLE *entry=(TABLE*) hash_element(&open_cache,idx); - if ((!entry->real_name) || strcmp(entry->table_cache_key,db)) - continue; - if (wild && wild[0] && wild_compare(entry->real_name,wild)) - continue; - if (db && !(col_access & TABLE_ACLS)) + + if ((!entry->real_name)) + continue; // Shouldn't happen + if (wild) { - table_list.db= (char*) db; - table_list.real_name= entry->real_name;/*real name*/ - table_list.grant.privilege=col_access; - if (check_grant(thd,TABLE_ACLS,&table_list,1,1)) - continue; + strxmov(name,entry->table_cache_key,".",entry->real_name,NullS); + if (wild_compare(name,wild)) + continue; } - /* need to check if he have't already listed it */ - List_iterator<char> it(*tables); - char *table_name; - int check = 0; - while (check == 0 && (table_name=it++)) + /* Check if user has SELECT privilege for any column in the table */ + table_list.db= (char*) entry->table_cache_key; + table_list.real_name= entry->real_name; + table_list.grant.privilege=0; + if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list)) + continue; + + /* need to check if we haven't already listed it */ + for (table= open_list ; table ; table=table->next) { - if (!strcmp(table_name,entry->real_name)) - check++; + if (!strcmp(table->table,entry->real_name) && + !strcmp(table->db,entry->table_cache_key)) + { + if (entry->in_use) + table->in_use++; + if (entry->locked_by_name) + table->locked++; + break; + } } - if (check) + if (table) continue; - - if (tables->push_back(thd->strdup(entry->real_name))) + if (!(*start_list = (OPEN_TABLE_LIST *) + sql_alloc(sizeof(**start_list)+entry->key_length))) { - result = -1; + open_list=0; // Out of memory break; } + strmov((*start_list)->table= + strmov(((*start_list)->db= (char*) ((*start_list)+1)), + entry->table_cache_key)+1, + entry->real_name); + (*start_list)->in_use= entry->in_use ? 1 : 0; + (*start_list)->locked= entry->locked_by_name ? 1 : 0; + start_list= &(*start_list)->next; + *start_list=0; } - VOID(pthread_mutex_unlock(&LOCK_open)); - DBUG_RETURN(result); -} - -char* -query_table_status(THD *thd,const char *db,const char *table_name) -{ - int cached = 0, in_use = 0; - char info[256]; - - for (uint idx=0 ; idx < open_cache.records; idx++) - { - TABLE *entry=(TABLE*) hash_element(&open_cache,idx); - if (strcmp(entry->table_cache_key,db) || - strcmp(entry->real_name,table_name)) - continue; - - cached++; - if (entry->in_use) - in_use++; - } - - sprintf(info, "cached=%d, in_use=%d", cached, in_use); - return thd->strdup(info); + DBUG_RETURN(open_list); } @@ -195,7 +191,7 @@ query_table_status(THD *thd,const char *db,const char *table_name) bool send_fields(THD *thd,List<Item> &list,uint flag) { - List_iterator<Item> it(list); + List_iterator_fast<Item> it(list); Item *item; char buff[80]; CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set; @@ -259,7 +255,7 @@ send_fields(THD *thd,List<Item> &list,uint flag) if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length())) break; /* purecov: inspected */ } - send_eof(&thd->net,(test_flags & TEST_MIT_THREAD) ? 0: 1); + send_eof(&thd->net); return 0; err: send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */ @@ -418,7 +414,6 @@ void close_thread_tables(THD *thd, bool locked) DBUG_VOID_RETURN; // LOCK TABLES in use } - TABLE *table,*next; bool found_old_table=0; if (thd->lock) @@ -431,40 +426,9 @@ void close_thread_tables(THD *thd, bool locked) DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); - for (table=thd->open_tables ; table ; table=next) - { - next=table->next; - if (table->version != refresh_version || - thd->version != refresh_version || !table->db_stat) - { - VOID(hash_delete(&open_cache,(byte*) table)); - found_old_table=1; - } - else - { - if (table->flush_version != flush_version) - { - table->flush_version=flush_version; - table->file->extra(HA_EXTRA_FLUSH); - } - else - { - // Free memory and reset for next loop - table->file->extra(HA_EXTRA_RESET); - } - table->in_use=0; - if (unused_tables) - { - table->next=unused_tables; /* Link in last */ - table->prev=unused_tables->prev; - unused_tables->prev=table; - table->prev->next=table; - } - else - unused_tables=table->next=table->prev=table; - } - } - thd->open_tables=0; + while (thd->open_tables) + found_old_table|=close_thread_table(thd, &thd->open_tables); + /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ @@ -480,6 +444,48 @@ void close_thread_tables(THD *thd, bool locked) DBUG_VOID_RETURN; } +/* move one table to free list */ + +bool close_thread_table(THD *thd, TABLE **table_ptr) +{ + DBUG_ENTER("close_thread_table"); + + bool found_old_table=0; + TABLE *table=*table_ptr; + + *table_ptr=table->next; + if (table->version != refresh_version || + thd->version != refresh_version || !table->db_stat) + { + VOID(hash_delete(&open_cache,(byte*) table)); + found_old_table=1; + } + else + { + if (table->flush_version != flush_version) + { + table->flush_version=flush_version; + table->file->extra(HA_EXTRA_FLUSH); + } + else + { + // Free memory and reset for next loop + table->file->extra(HA_EXTRA_RESET); + } + table->in_use=0; + if (unused_tables) + { + table->next=unused_tables; /* Link in last */ + table->prev=unused_tables->prev; + unused_tables->prev=table; + table->prev->next=table; + } + else + unused_tables=table->next=table->prev=table; + } + DBUG_RETURN(found_old_table); +} + /* Close and delete temporary tables */ void close_temporary(TABLE *table,bool delete_table) @@ -581,7 +587,7 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name) table= *prev; *prev= table->next; close_temporary(table); - if(thd->slave_thread) + if (thd->slave_thread) --slave_open_temp_tables; return 0; } @@ -689,7 +695,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) if (thd->killed) DBUG_RETURN(0); TABLE* table; - if(!(table = table_list->table)) + if (!(table = table_list->table)) DBUG_RETURN(0); char* db = thd->db ? thd->db : table_list->db; @@ -836,25 +842,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key, key_length))) { - MEM_ROOT* glob_alloc; - LINT_INIT(glob_alloc); - - if (errno == ENOENT && - (glob_alloc = my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC))) - // Sasha: needed for replication - // remember the name of the non-existent table - // so we can try to download it from the master - { - int table_name_len = (uint) strlen(table_name); - int db_len = (uint) strlen(db); - thd->last_nx_db = alloc_root(glob_alloc,db_len + table_name_len + 2); - if(thd->last_nx_db) - { - thd->last_nx_table = thd->last_nx_db + db_len + 1; - memcpy(thd->last_nx_table, table_name, table_name_len + 1); - memcpy(thd->last_nx_db, db, db_len + 1); - } - } table->next=table->prev=table; free_cache_entry(table); VOID(pthread_mutex_unlock(&LOCK_open)); @@ -895,7 +882,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, 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; - dbug_assert(table->key_read == 0); + DBUG_ASSERT(table->key_read == 0); DBUG_RETURN(table); } @@ -1337,7 +1324,7 @@ int open_tables(THD *thd,TABLE_LIST *start) { if (!tables->table && !(tables->table=open_table(thd, - tables->db ? tables->db : thd->db, + tables->db, tables->real_name, tables->name, &refresh))) { @@ -1394,7 +1381,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) DBUG_ENTER("open_ltable"); thd->proc_info="Opening table"; - while (!(table=open_table(thd,table_list->db ? table_list->db : thd->db, + while (!(table=open_table(thd,table_list->db, table_list->real_name,table_list->name, &refresh)) && refresh) ; if (table) @@ -1403,11 +1390,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) #if defined( __WIN__) || defined(OS2) /* Win32 can't drop a file that is open */ - if (lock_type == TL_WRITE_ALLOW_READ -#ifdef HAVE_GEMINI_DB - && table->db_type != DB_TYPE_GEMINI -#endif /* HAVE_GEMINI_DB */ - ) + if (lock_type == TL_WRITE_ALLOW_READ) { lock_type= TL_WRITE; } @@ -1533,8 +1516,8 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, { tmp_table->next=thd->temporary_tables; thd->temporary_tables=tmp_table; - if(thd->slave_thread) - ++slave_open_temp_tables; + if (thd->slave_thread) + slave_open_temp_tables++; } DBUG_RETURN(tmp_table); } @@ -1594,18 +1577,13 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, { field->query_id=thd->query_id; table->used_fields++; - if (field->part_of_key) - { - if (!(field->part_of_key & table->ref_primary_key)) - table->used_keys&=field->part_of_key; - } - else - table->used_keys=0; + table->used_keys&=field->part_of_key; } else thd->dupp_field=field; } - if (check_grants && !thd->master_access && check_grant_column(thd,table,name,length)) + if (check_grants && !thd->master_access && + check_grant_column(thd,table,name,length)) return WRONG_GRANT; return field; } @@ -1626,9 +1604,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) for (; tables ; tables=tables->next) { if (!strcmp(tables->name,table_name) && - (!db || - (tables->db && !strcmp(db,tables->db)) || - (!tables->db && !strcmp(db,thd->db)))) + (!db || !strcmp(db,tables->db))) { found_table=1; Field *find=find_field_in_table(thd,tables->table,name,length, @@ -1671,7 +1647,8 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) for (; tables ; tables=tables->next) { Field *field=find_field_in_table(thd,tables->table,name,length, - grant_option && !thd->master_access, allow_rowid); + grant_option && + !thd->master_access, allow_rowid); if (field) { if (field == WRONG_GRANT) @@ -1752,14 +1729,15 @@ find_item_in_list(Item *find,List<Item> &items) ****************************************************************************/ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, - bool set_query_id, List<Item> *sum_func_list) + bool set_query_id, List<Item> *sum_func_list, + bool allow_sum_func) { reg2 Item *item; List_iterator<Item> it(fields); DBUG_ENTER("setup_fields"); thd->set_query_id=set_query_id; - thd->allow_sum_func= test(sum_func_list); + thd->allow_sum_func= allow_sum_func; thd->where="field list"; while ((item=it++)) @@ -1775,7 +1753,8 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, { if (item->fix_fields(thd,tables)) DBUG_RETURN(-1); /* purecov: inspected */ - if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) + if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && + sum_func_list) item->split_sum_func(*sum_func_list); thd->used_tables|=item->used_tables(); } @@ -1794,27 +1773,40 @@ bool setup_tables(TABLE_LIST *tables) { DBUG_ENTER("setup_tables"); uint tablenr=0; - for (TABLE_LIST *table=tables ; table ; table=table->next,tablenr++) - { - table->table->tablenr=tablenr; - table->table->map= (table_map) 1 << tablenr; - if ((table->table->outer_join=table->outer_join)) - table->table->maybe_null=1; // LEFT OUTER JOIN ... - if (table->use_index) + for (TABLE_LIST *table_list=tables ; table_list ; + table_list=table_list->next,tablenr++) + { + TABLE *table=table_list->table; + + table->used_fields=0; + 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->maybe_null=test(table->outer_join=table_list->outer_join); + table->tablenr=tablenr; + table->map= (table_map) 1 << tablenr; + if (table_list->use_index) { - key_map map= get_key_map_from_key_list(table->table, - table->use_index); + key_map map= get_key_map_from_key_list(table, + table_list->use_index); if (map == ~(key_map) 0) DBUG_RETURN(1); - table->table->keys_in_use_for_query=map; + table->keys_in_use_for_query=map; } - if (table->ignore_index) + if (table_list->ignore_index) { - key_map map= get_key_map_from_key_list(table->table, - table->ignore_index); + key_map map= get_key_map_from_key_list(table, + table_list->ignore_index); if (map == ~(key_map) 0) DBUG_RETURN(1); - table->table->keys_in_use_for_query &= ~map; + table->keys_in_use_for_query &= ~map; + } + if (table_list->shared) + { + /* Clear query_id that may have been set by previous select */ + for (Field **ptr=table->field ; *ptr ; ptr++) + (*ptr)->query_id=0; } } if (tablenr > MAX_TABLES) @@ -1830,7 +1822,7 @@ static key_map get_key_map_from_key_list(TABLE *table, List<String> *index_list) { key_map map=0; - List_iterator<String> it(*index_list); + List_iterator_fast<String> it(*index_list); String *name; uint pos; while ((name=it++)) @@ -1851,7 +1843,7 @@ static key_map get_key_map_from_key_list(TABLE *table, ** Returns pointer to last inserted field if ok ****************************************************************************/ -static bool +bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it) { @@ -1866,8 +1858,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, check_grant_all_columns(thd,SELECT_ACL,table) ) DBUG_RETURN(-1); if (!table_name || (!strcmp(table_name,tables->name) && - (!db_name || !tables->db || - !strcmp(tables->db,db_name)))) + (!db_name || !strcmp(tables->db,db_name)))) { Field **ptr=table->field,*field; thd->used_tables|=table->map; @@ -1881,14 +1872,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; - - if (field->part_of_key) - { - if (!(field->part_of_key & table->ref_primary_key)) - table->used_keys&=field->part_of_key; - } - else - table->used_keys=0; + table->used_keys&=field->part_of_key; } /* All fields are used */ table->used_fields=table->fields; @@ -1956,7 +1940,6 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) // TODO: This could be optimized to use hashed names if t2 had a hash for (j=0 ; j < t2->fields ; j++) { - key_map tmp_map; if (!my_strcasecmp(t1->field[i]->field_name, t2->field[j]->field_name)) { @@ -1969,20 +1952,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) /* Mark field used for table cache */ t1->field[i]->query_id=t2->field[j]->query_id=thd->query_id; cond_and->list.push_back(tmp); - if ((tmp_map=t1->field[i]->part_of_key)) - { - if (!(tmp_map & t1->ref_primary_key)) - t1->used_keys&=tmp_map; - } - else - t1->used_keys=0; - if ((tmp_map=t2->field[j]->part_of_key)) - { - if (!(tmp_map & t2->ref_primary_key)) - t2->used_keys&=tmp_map; - } - else - t2->used_keys=0; + t1->used_keys&= t1->field[i]->part_of_key; + t2->used_keys&= t2->field[j]->part_of_key; break; } } @@ -2010,7 +1981,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) int fill_record(List<Item> &fields,List<Item> &values) { - List_iterator<Item> f(fields),v(values); + List_iterator_fast<Item> f(fields),v(values); Item *value; Item_field *field; DBUG_ENTER("fill_record"); @@ -2028,7 +1999,7 @@ fill_record(List<Item> &fields,List<Item> &values) int fill_record(Field **ptr,List<Item> &values) { - List_iterator<Item> v(values); + List_iterator_fast<Item> v(values); Item *value; DBUG_ENTER("fill_record"); @@ -2091,7 +2062,8 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) create_info.db_type=DB_TYPE_DEFAULT; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, - fields, keys, drop, alter, (ORDER*)0, FALSE, DUP_ERROR)); + fields, keys, drop, alter, (ORDER*)0, FALSE, + DUP_ERROR)); } @@ -2106,7 +2078,8 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) create_info.db_type=DB_TYPE_DEFAULT; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, - fields, keys, drop, alter, (ORDER*)0, FALSE, DUP_ERROR)); + fields, keys, drop, alter, (ORDER*)0, FALSE, + DUP_ERROR)); } /***************************************************************************** @@ -2201,8 +2174,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, int setup_ftfuncs(THD *thd) { - List_iterator<Item_func_match> li(thd->lex.ftfunc_list), - lj(thd->lex.ftfunc_list); + List_iterator<Item_func_match> li(thd->lex.select_lex.ftfunc_list), + lj(thd->lex.select_lex.ftfunc_list); Item_func_match *ftf, *ftf2; while ((ftf=li++)) @@ -2222,16 +2195,18 @@ int setup_ftfuncs(THD *thd) int init_ftfuncs(THD *thd, bool no_order) { - List_iterator<Item_func_match> li(thd->lex.ftfunc_list); - Item_func_match *ifm; - DBUG_PRINT("info",("Performing FULLTEXT search")); - thd->proc_info="FULLTEXT initialization"; - - while ((ifm=li++)) + if (thd->lex.select_lex.ftfunc_list.elements) { - ifm->init_search(no_order); - } + List_iterator<Item_func_match> li(thd->lex.select_lex.ftfunc_list); + Item_func_match *ifm; + DBUG_PRINT("info",("Performing FULLTEXT search")); + thd->proc_info="FULLTEXT initialization"; + while ((ifm=li++)) + { + ifm->init_search(no_order); + } + } return 0; } |