diff options
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 210 |
1 files changed, 112 insertions, 98 deletions
diff --git a/sql/handler.cc b/sql/handler.cc index 3db2f76aef8..2688b117318 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -189,7 +189,8 @@ enum db_type ha_checktype(THD *thd, enum db_type database_type, } /* ha_checktype */ -handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type) +handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, + enum db_type db_type) { handler *file= NULL; handlerton **types; @@ -205,7 +206,7 @@ handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type) if (db_type == (*types)->db_type && (*types)->create) { file= ((*types)->state == SHOW_OPTION_YES) ? - (*types)->create(table) : NULL; + (*types)->create(share) : NULL; break; } } @@ -216,7 +217,7 @@ handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type) enum db_type def=(enum db_type) current_thd->variables.table_type; /* Try first with 'default table type' */ if (db_type != def) - return get_new_handler(table, alloc, def); + return get_new_handler(share, alloc, def); } if (file) { @@ -1047,7 +1048,8 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; } - statistic_increment(thd->status_var.ha_savepoint_rollback_count,&LOCK_status); + statistic_increment(thd->status_var.ha_savepoint_rollback_count, + &LOCK_status); trans->no_2pc|=(*ht)->prepare == 0; } /* @@ -1176,7 +1178,7 @@ bool ha_flush_logs(enum db_type db_type) */ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, - const char *alias, bool generate_warning) + const char *db, const char *alias, bool generate_warning) { handler *file; char tmp_path[FN_REFLEN]; @@ -1191,7 +1193,7 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */ if (table_type == DB_TYPE_UNKNOWN || - ! (file=get_new_handler(&dummy_table, thd->mem_root, table_type))) + ! (file=get_new_handler(&dummy_share, thd->mem_root, table_type))) DBUG_RETURN(ENOENT); if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED)) @@ -1224,7 +1226,12 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, thd->net.last_error[0]= 0; /* Fill up strucutures that print_error may need */ - dummy_table.s->path= path; + dummy_share.path.str= (char*) path; + dummy_share.path.length= strlen(path); + dummy_share.db.str= (char*) db; + dummy_share.db.length= strlen(db); + dummy_share.table_name.str= (char*) alias; + dummy_share.table_name.length= strlen(alias); dummy_table.alias= alias; file->print_error(error, 0); @@ -1246,16 +1253,26 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, ** General handler functions ****************************************************************************/ - /* Open database-handler. Try O_RDONLY if can't open as O_RDWR */ - /* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */ +/* + Open database-handler. + + IMPLEMENTATION + Try O_RDONLY if cannot open as O_RDWR + Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set +*/ -int handler::ha_open(const char *name, int mode, int test_if_locked) +int handler::ha_open(TABLE *table_arg, const char *name, int mode, + int test_if_locked) { int error; DBUG_ENTER("handler::ha_open"); - DBUG_PRINT("enter",("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d", - name, table->s->db_type, table->db_stat, mode, - test_if_locked)); + DBUG_PRINT("enter", + ("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d", + name, table_share->db_type, table_arg->db_stat, mode, + test_if_locked)); + + table= table_arg; + DBUG_ASSERT(table->s == table_share); if ((error=open(name,mode,test_if_locked))) { @@ -1268,7 +1285,7 @@ int handler::ha_open(const char *name, int mode, int test_if_locked) } if (error) { - my_errno=error; /* Safeguard */ + my_errno= error; /* Safeguard */ DBUG_PRINT("error",("error: %d errno: %d",error,errno)); } else @@ -1286,74 +1303,51 @@ int handler::ha_open(const char *name, int mode, int test_if_locked) } else dupp_ref=ref+ALIGN_SIZE(ref_length); + + if (ha_allocate_read_write_set(table->s->fields)) + error= 1; } DBUG_RETURN(error); } + int handler::ha_initialise() { DBUG_ENTER("ha_initialise"); - if (table && table->s->fields && - ha_allocate_read_write_set(table->s->fields)) - { - DBUG_RETURN(TRUE); - } DBUG_RETURN(FALSE); } + +/* + Initalize bit maps for used fields + + Called from open_table_from_share() +*/ + int handler::ha_allocate_read_write_set(ulong no_fields) { uint bitmap_size= 4*(((no_fields+1)+31)/32); uint32 *read_buf, *write_buf; -#ifndef DEBUG_OFF - my_bool r; -#endif DBUG_ENTER("ha_allocate_read_write_set"); DBUG_PRINT("enter", ("no_fields = %d", no_fields)); - if (table) + if (!multi_alloc_root(&table->mem_root, + &read_set, sizeof(MY_BITMAP), + &write_set, sizeof(MY_BITMAP), + &read_buf, bitmap_size, + &write_buf, bitmap_size, + NullS)) { - if (table->read_set == NULL) - { - read_set= (MY_BITMAP*)sql_alloc(sizeof(MY_BITMAP)); - write_set= (MY_BITMAP*)sql_alloc(sizeof(MY_BITMAP)); - read_buf= (uint32*)sql_alloc(bitmap_size); - write_buf= (uint32*)sql_alloc(bitmap_size); - if (!read_set || !write_set || !read_buf || !write_buf) - { - ha_deallocate_read_write_set(); - DBUG_RETURN(TRUE); - } -#ifndef DEBUG_OFF - r = -#endif - bitmap_init(read_set, read_buf, no_fields+1, FALSE); - DBUG_ASSERT(!r /*bitmap_init(read_set...)*/); -#ifndef DEBUG_OFF - r = -#endif - bitmap_init(write_set, write_buf, no_fields+1, FALSE); - DBUG_ASSERT(!r /*bitmap_init(write_set...)*/); - table->read_set= read_set; - table->write_set= write_set; - ha_clear_all_set(); - } - else - { - read_set= table->read_set; - write_set= table->write_set; - } + DBUG_RETURN(TRUE); } + bitmap_init(read_set, read_buf, no_fields+1, FALSE); + bitmap_init(write_set, write_buf, no_fields+1, FALSE); + table->read_set= read_set; + table->write_set= write_set; + ha_clear_all_set(); DBUG_RETURN(FALSE); } -void handler::ha_deallocate_read_write_set() -{ - DBUG_ENTER("ha_deallocate_read_write_set"); - read_set=write_set=0; - DBUG_VOID_RETURN; -} - void handler::ha_clear_all_set() { DBUG_ENTER("ha_clear_all_set"); @@ -1395,6 +1389,7 @@ void handler::ha_set_primary_key_in_read_set() } + /* Read first row (only) from a table This is never called for InnoDB or BDB tables, as these table types @@ -1406,7 +1401,8 @@ int handler::read_first_row(byte * buf, uint primary_key) register int error; DBUG_ENTER("handler::read_first_row"); - statistic_increment(current_thd->status_var.ha_read_first_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_first_count, + &LOCK_status); /* If there is very few deleted rows in the table, find the first row by @@ -1672,9 +1668,10 @@ void handler::print_error(int error, myf errflag) uint key_nr=get_dup_key(error); if ((int) key_nr >= 0) { - /* Write the dupplicated key in the error message */ + /* Write the duplicated key in the error message */ char key[MAX_KEY_LENGTH]; String str(key,sizeof(key),system_charset_info); + /* Table is opened and defined at this point */ key_unpack(&str,table,(uint) key_nr); uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY)); if (str.length() >= max_length) @@ -1761,20 +1758,9 @@ void handler::print_error(int error, myf errflag) textno=ER_TABLE_DEF_CHANGED; break; case HA_ERR_NO_SUCH_TABLE: - { - /* - We have to use path to find database name instead of using - table->table_cache_key because if the table didn't exist, then - table_cache_key was not set up - */ - char *db; - char buff[FN_REFLEN]; - uint length= dirname_part(buff,table->s->path); - buff[length-1]=0; - db=buff+dirname_length(buff); - my_error(ER_NO_SUCH_TABLE, MYF(0), db, table->alias); + my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str, + table_share->table_name.str); break; - } default: { /* The error was "unknown" to this function. @@ -1795,7 +1781,7 @@ void handler::print_error(int error, myf errflag) DBUG_VOID_RETURN; } } - my_error(textno, errflag, table->alias, error); + my_error(textno, errflag, table_share->table_name.str, error); DBUG_VOID_RETURN; } @@ -1940,23 +1926,37 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen) /* Initiates table-file and calls apropriate database-creator - Returns 1 if something got wrong + + NOTES + We must have a write lock on LOCK_open to be sure no other thread + interfers with table + + RETURN + 0 ok + 1 error */ -int ha_create_table(const char *name, HA_CREATE_INFO *create_info, +int ha_create_table(THD *thd, const char *path, + const char *db, const char *table_name, + HA_CREATE_INFO *create_info, bool update_create_info) { - int error; + int error= 1; TABLE table; char name_buff[FN_REFLEN]; + const char *name; + TABLE_SHARE share; DBUG_ENTER("ha_create_table"); + + init_tmp_table_share(&share, db, 0, table_name, path); + if (open_table_def(thd, &share, 0) || + open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table)) + goto err; - if (openfrm(current_thd, name,"",0,(uint) READ_ALL, 0, &table)) - DBUG_RETURN(1); if (update_create_info) - { update_create_info_from_table(create_info, &table); - } + + name= share.path.str; if (lower_case_table_names == 2 && !(table.file->table_flags() & HA_FILE_BASED)) { @@ -1966,27 +1966,32 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, name= name_buff; } - error=table.file->create(name,&table,create_info); - VOID(closefrm(&table)); + error= table.file->create(name, &table, create_info); + VOID(closefrm(&table, 0)); if (error) - my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name,error); + { + strxmov(name_buff, db, ".", table_name, NullS); + my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error); + } +err: + free_table_share(&share); DBUG_RETURN(error != 0); } /* - Try to discover table from engine and - if found, write the frm file to disk. + Try to discover table from engine + + NOTES + If found, write the frm file to disk. RETURN VALUES: - -1 : Table did not exists - 0 : Table created ok - > 0 : Error, table existed but could not be created + -1 Table did not exists + 0 Table created ok + > 0 Error, table existed but could not be created */ -int ha_create_table_from_engine(THD* thd, - const char *db, - const char *name) +int ha_create_table_from_engine(THD* thd, const char *db, const char *name) { int error; const void *frmblob; @@ -1994,6 +1999,7 @@ int ha_create_table_from_engine(THD* thd, char path[FN_REFLEN]; HA_CREATE_INFO create_info; TABLE table; + TABLE_SHARE share; DBUG_ENTER("ha_create_table_from_engine"); DBUG_PRINT("enter", ("name '%s'.'%s'", db, name)); @@ -2009,15 +2015,23 @@ int ha_create_table_from_engine(THD* thd, frmblob and frmlen are set, write the frm to disk */ - (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS); + (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,"/",db,"/",name,NullS); // Save the frm file error= writefrm(path, frmblob, frmlen); my_free((char*) frmblob, MYF(0)); if (error) DBUG_RETURN(2); - if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table)) + init_tmp_table_share(&share, db, 0, name, path); + if (open_table_def(thd, &share, 0)) + { + DBUG_RETURN(3); + } + if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table)) + { + free_table_share(&share); DBUG_RETURN(3); + } update_create_info_from_table(&create_info, &table); create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE; @@ -2029,7 +2043,7 @@ int ha_create_table_from_engine(THD* thd, my_casedn_str(files_charset_info, path); } error=table.file->create(path,&table,&create_info); - VOID(closefrm(&table)); + VOID(closefrm(&table, 1)); DBUG_RETURN(error != 0); } @@ -2488,7 +2502,7 @@ TYPELIB *ha_known_exts(void) { if ((*types)->state == SHOW_OPTION_YES) { - handler *file= get_new_handler(0, mem_root, + handler *file= get_new_handler((TABLE_SHARE*) 0, mem_root, (enum db_type) (*types)->db_type); for (ext= file->bas_ext(); *ext; ext++) { |