diff options
Diffstat (limited to 'sql/ha_myisam.cc')
-rw-r--r-- | sql/ha_myisam.cc | 198 |
1 files changed, 146 insertions, 52 deletions
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 128cc191434..40081c975c8 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -27,10 +27,12 @@ #ifndef MASTER #include "../srclib/myisam/myisamdef.h" #else -#include "../myisam/myisamdef.h" -#include "../myisam/rt_index.h" +#include "../storage/myisam/myisamdef.h" +#include "../storage/myisam/rt_index.h" #endif +#include <mysql/plugin.h> + ulong myisam_recover_options= HA_RECOVER_NONE; /* bits in myisam_recover_options */ @@ -50,12 +52,19 @@ TYPELIB myisam_stats_method_typelib= { ** MyISAM tables *****************************************************************************/ +static handler *myisam_create_handler(TABLE_SHARE *table); + /* MyISAM handlerton */ +static const char myisam_hton_name[]= "MyISAM"; +static const char myisam_hton_comment[]= + "Default engine as of MySQL 3.23 with great performance"; + handlerton myisam_hton= { - "MyISAM", + MYSQL_HANDLERTON_INTERFACE_VERSION, + myisam_hton_name, SHOW_OPTION_YES, - "Default engine as of MySQL 3.23 with great performance", + myisam_hton_comment, DB_TYPE_MYISAM, NULL, 0, /* slot */ @@ -77,9 +86,29 @@ handlerton myisam_hton= { MyISAM doesn't support transactions and doesn't have transaction-dependent context: cursors can survive a commit. */ - HTON_CAN_RECREATE + myisam_create_handler, /* Create a new handler */ + NULL, /* Drop a database */ + mi_panic,/* Panic call */ + NULL, /* Start Consistent Snapshot */ + NULL, /* Flush logs */ + NULL, /* Show status */ + NULL, /* Partition flags */ + NULL, /* Alter table flags */ + NULL, /* Alter Tablespace */ + NULL, /* Fill Files Table */ + HTON_CAN_RECREATE, + NULL, /* binlog_func */ + NULL, /* binlog_log_query */ + NULL /* release_temporary_latches */ }; + +static handler *myisam_create_handler(TABLE_SHARE *table) +{ + return new ha_myisam(table); +} + + // collect errors printed by mi_check routines static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, @@ -160,7 +189,7 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...) } -ha_myisam::ha_myisam(TABLE *table_arg) +ha_myisam::ha_myisam(TABLE_SHARE *table_arg) :handler(&myisam_hton, table_arg), file(0), int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | @@ -277,15 +306,42 @@ err: } #endif /* HAVE_REPLICATION */ + +bool ha_myisam::check_if_locking_is_allowed(uint sql_command, + ulong type, TABLE *table, + uint count, + bool called_by_logger_thread) +{ + /* + To be able to open and lock for reading system tables like 'mysql.proc', + when we already have some tables opened and locked, and avoid deadlocks + we have to disallow write-locking of these tables with any other tables. + */ + if (table->s->system_table && + table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE && + count != 1) + { + my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table->s->db.str, + table->s->table_name.str); + return FALSE; + } + return TRUE; +} + /* Name is here without an extension */ int ha_myisam::open(const char *name, int mode, uint test_if_locked) { - if (!(file=mi_open(name, mode, test_if_locked))) + uint i; + if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER))) return (my_errno ? my_errno : -1); if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE)) VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0)); + + if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_myisam_use_mmap) + VOID(mi_extra(file, HA_EXTRA_MMAP, 0)); + info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED)) VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0)); @@ -293,6 +349,15 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) int_table_flags|=HA_REC_NOT_IN_SEQ; if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) int_table_flags|=HA_HAS_CHECKSUM; + + for (i= 0; i < table->s->keys; i++) + { + struct st_plugin_int *parser= table->key_info[i].parser; + if (table->key_info[i].flags & HA_USES_PARSER) + file->s->keyinfo[i].parser= + (struct st_mysql_ftparser *)parser->plugin->info; + table->key_info[i].block_size= file->s->keyinfo[i].block_length; + } return (0); } @@ -332,7 +397,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) myisamchk_init(¶m); param.thd = thd; param.op_name = "check"; - param.db_name= table->s->db; + param.db_name= table->s->db.str; param.table_name= table->alias; param.testflag = check_opt->flags | T_CHECK | T_SILENT; param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method; @@ -422,7 +487,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) myisamchk_init(¶m); param.thd = thd; param.op_name= "analyze"; - param.db_name= table->s->db; + param.db_name= table->s->db.str; param.table_name= table->alias; param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | T_DONT_CHECK_CHECKSUM); @@ -450,7 +515,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) HA_CHECK_OPT tmp_check_opt; char *backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; - const char *table_name= table->s->table_name; + const char *table_name= table->s->table_name.str; int error; const char* errmsg; DBUG_ENTER("restore"); @@ -459,8 +524,8 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) MI_NAME_DEXT)) DBUG_RETURN(HA_ADMIN_INVALID); - if (my_copy(src_path, fn_format(dst_path, table->s->path, "", - MI_NAME_DEXT, 4), MYF(MY_WME))) + strxmov(dst_path, table->s->normalized_path.str, MI_NAME_DEXT, NullS); + if (my_copy(src_path, dst_path, MYF(MY_WME))) { error= HA_ADMIN_FAILED; errmsg= "Failed in my_copy (Error %d)"; @@ -477,8 +542,8 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) myisamchk_init(¶m); param.thd= thd; param.op_name= "restore"; - param.db_name= table->s->db; - param.table_name= table->s->table_name; + param.db_name= table->s->db.str; + param.table_name= table->s->table_name.str; param.testflag= 0; mi_check_print_error(¶m, errmsg, my_errno); DBUG_RETURN(error); @@ -490,7 +555,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) { char *backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; - const char *table_name= table->s->table_name; + const char *table_name= table->s->table_name.str; int error; const char *errmsg; DBUG_ENTER("ha_myisam::backup"); @@ -503,9 +568,8 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) goto err; } - if (my_copy(fn_format(src_path, table->s->path, "", reg_ext, - MY_UNPACK_FILENAME), - dst_path, + strxmov(src_path, table->s->normalized_path.str, reg_ext, NullS); + if (my_copy(src_path, dst_path, MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE))) { error = HA_ADMIN_FAILED; @@ -514,17 +578,16 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) } /* Change extension */ - if (!fn_format(dst_path, dst_path, "", MI_NAME_DEXT, - MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH)) + if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir, + MI_NAME_DEXT)) { errmsg = "Failed in fn_format() for .MYD file (errno: %d)"; error = HA_ADMIN_INVALID; goto err; } - if (my_copy(fn_format(src_path, table->s->path, "", MI_NAME_DEXT, - MY_UNPACK_FILENAME), - dst_path, + strxmov(src_path, table->s->normalized_path.str, MI_NAME_DEXT, NullS); + if (my_copy(src_path, dst_path, MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE))) { errmsg = "Failed copying .MYD file (errno: %d)"; @@ -539,8 +602,8 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) myisamchk_init(¶m); param.thd= thd; param.op_name= "backup"; - param.db_name= table->s->db; - param.table_name= table->s->table_name; + param.db_name= table->s->db.str; + param.table_name= table->s->table_name.str; param.testflag = 0; mi_check_print_error(¶m,errmsg, my_errno); DBUG_RETURN(error); @@ -631,7 +694,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) ha_rows rows= file->state->records; DBUG_ENTER("ha_myisam::repair"); - param.db_name= table->s->db; + param.db_name= table->s->db.str; param.table_name= table->alias; param.tmpfile_createflag = O_RDWR | O_TRUNC; param.using_global_keycache = 1; @@ -802,8 +865,8 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) myisamchk_init(¶m); param.thd= thd; param.op_name= "assign_to_keycache"; - param.db_name= table->s->db; - param.table_name= table->s->table_name; + param.db_name= table->s->db.str; + param.table_name= table->s->table_name.str; param.testflag= 0; mi_check_print_error(¶m, errmsg); } @@ -870,8 +933,8 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) myisamchk_init(¶m); param.thd= thd; param.op_name= "preload_keys"; - param.db_name= table->s->db; - param.table_name= table->s->table_name; + param.db_name= table->s->db.str; + param.table_name= table->s->table_name.str; param.testflag= 0; mi_check_print_error(¶m, errmsg); DBUG_RETURN(error); @@ -1125,8 +1188,8 @@ bool ha_myisam::check_and_repair(THD *thd) old_query= thd->query; old_query_length= thd->query_length; pthread_mutex_lock(&LOCK_thread_count); - thd->query= (char*) table->s->table_name; - thd->query_length= (uint32) strlen(table->s->table_name); + thd->query= table->s->table_name.str; + thd->query_length= table->s->table_name.length; pthread_mutex_unlock(&LOCK_thread_count); if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt)) @@ -1312,7 +1375,11 @@ void ha_myisam::info(uint flag) sortkey= info.sortkey; ref_length= info.reflength; share->db_options_in_use= info.options; - block_size= myisam_block_size; + block_size= myisam_block_size; /* record block size */ + + /* Update share */ + if (share->tmp_table == NO_TMP_TABLE) + pthread_mutex_lock(&share->mutex); share->keys_in_use.set_prefix(share->keys); share->keys_in_use.intersect_extended(info.key_map); share->keys_for_keyread.intersect(share->keys_in_use); @@ -1321,19 +1388,18 @@ void ha_myisam::info(uint flag) memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key, sizeof(table->key_info[0].rec_per_key)*share->key_parts); - raid_type= info.raid_type; - raid_chunks= info.raid_chunks; - raid_chunksize= info.raid_chunksize; + if (share->tmp_table == NO_TMP_TABLE) + pthread_mutex_unlock(&share->mutex); /* Set data_file_name and index_file_name to point at the symlink value if table is symlinked (Ie; Real name is not same as generated name) */ - data_file_name=index_file_name=0; - fn_format(name_buff, file->filename, "", MI_NAME_DEXT, 2); + data_file_name= index_file_name= 0; + fn_format(name_buff, file->filename, "", MI_NAME_DEXT, MY_APPEND_EXT); if (strcmp(name_buff, info.data_file_name)) data_file_name=info.data_file_name; - strmov(fn_ext(name_buff),MI_NAME_IEXT); + fn_format(name_buff, file->filename, "", MI_NAME_IEXT, MY_APPEND_EXT); if (strcmp(name_buff, info.index_file_name)) index_file_name=info.index_file_name; } @@ -1401,12 +1467,6 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) { create_info->auto_increment_value=auto_increment_value; } - if (!(create_info->used_fields & HA_CREATE_USED_RAID)) - { - create_info->raid_type= raid_type; - create_info->raid_chunks= raid_chunks; - create_info->raid_chunksize= raid_chunksize; - } create_info->data_file_name=data_file_name; create_info->index_file_name=index_file_name; } @@ -1424,7 +1484,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, MI_KEYDEF *keydef; MI_COLUMNDEF *recinfo,*recinfo_pos; HA_KEYSEG *keyseg; - TABLE_SHARE *share= table->s; + TABLE_SHARE *share= table_arg->s; uint options= share->db_options_in_use; DBUG_ENTER("ha_myisam::create"); @@ -1442,10 +1502,14 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, pos=table_arg->key_info; for (i=0; i < share->keys ; i++, pos++) { + if (pos->flags & HA_USES_PARSER) + create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER; keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ? (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) : pos->algorithm; + keydef[i].block_length= pos->block_size; + keydef[i].seg=keyseg; keydef[i].keysegs=pos->key_parts; for (j=0 ; j < pos->key_parts ; j++) @@ -1596,11 +1660,6 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, (ulonglong) 0); create_info.data_file_length= ((ulonglong) share->max_rows * share->avg_row_length); - create_info.raid_type=info->raid_type; - create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks : - RAID_DEFAULT_CHUNKS); - create_info.raid_chunksize= (info->raid_chunksize ? info->raid_chunksize : - RAID_DEFAULT_CHUNKSIZE); create_info.data_file_name= info->data_file_name; create_info.index_file_name= info->index_file_name; @@ -1614,7 +1673,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, create_flags|= HA_CREATE_DELAY_KEY_WRITE; /* TODO: Check that the following fn_format is really needed */ - error=mi_create(fn_format(buff,name,"","",2+4), + error=mi_create(fn_format(buff,name,"","",MY_UNPACK_FILENAME|MY_APPEND_EXT), share->keys,keydef, (uint) (recinfo_pos-recinfo), recinfo, 0, (MI_UNIQUEDEF*) 0, @@ -1718,3 +1777,38 @@ uint ha_myisam::checksum() const return (uint)file->state->checksum; } + +bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info, + uint table_changes) +{ + uint options= table->s->db_options_in_use; + + if (info->auto_increment_value != auto_increment_value || + info->data_file_name != data_file_name || + info->index_file_name != index_file_name || + table_changes == IS_EQUAL_NO || + table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet + return COMPATIBLE_DATA_NO; + + if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM | + HA_OPTION_DELAY_KEY_WRITE)) != + (info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM | + HA_OPTION_DELAY_KEY_WRITE))) + return COMPATIBLE_DATA_NO; + return COMPATIBLE_DATA_YES; +} + + +mysql_declare_plugin(myisam) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &myisam_hton, + myisam_hton_name, + "MySQL AB", + myisam_hton_comment, + NULL, /* Plugin Init */ + NULL, /* Plugin Deinit */ + 0x0100, /* 1.0 */ + 0 +} +mysql_declare_plugin_end; |