diff options
Diffstat (limited to 'sql/ha_myisammrg.cc')
-rw-r--r-- | sql/ha_myisammrg.cc | 157 |
1 files changed, 113 insertions, 44 deletions
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index edb3521470f..9780f163634 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -32,8 +32,47 @@ ** MyISAM MERGE tables *****************************************************************************/ +/* MyISAM MERGE handlerton */ + +handlerton myisammrg_hton= { + "MRG_MYISAM", + SHOW_OPTION_YES, + "Collection of identical MyISAM tables", + DB_TYPE_MRG_MYISAM, + NULL, + 0, /* slot */ + 0, /* savepoint size. */ + NULL, /* close_connection */ + NULL, /* savepoint */ + NULL, /* rollback to savepoint */ + NULL, /* release savepoint */ + NULL, /* commit */ + NULL, /* rollback */ + NULL, /* prepare */ + NULL, /* recover */ + NULL, /* commit_by_xid */ + NULL, /* rollback_by_xid */ + NULL, /* create_cursor_read_view */ + NULL, /* set_cursor_read_view */ + NULL, /* close_cursor_read_view */ + HTON_CAN_RECREATE +}; + + +ha_myisammrg::ha_myisammrg(TABLE *table_arg) + :handler(&myisammrg_hton, table_arg), file(0) +{} + +static const char *ha_myisammrg_exts[] = { + ".MRG", + NullS +}; + const char **ha_myisammrg::bas_ext() const -{ static const char *ext[]= { ".MRG", NullS }; return ext; } +{ + return ha_myisammrg_exts; +} + const char *ha_myisammrg::index_type(uint key_number) { @@ -67,15 +106,15 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED)) myrg_extra(file,HA_EXTRA_WAIT_LOCK,0); - if (table->reclength != mean_rec_length && mean_rec_length) + if (table->s->reclength != mean_rec_length && mean_rec_length) { DBUG_PRINT("error",("reclength: %d mean_rec_length: %d", - table->reclength, mean_rec_length)); + table->s->reclength, mean_rec_length)); goto err; } #if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4 /* Merge table has more than 2G rows */ - if (table->crashed) + if (table->s->crashed) goto err; #endif return (0); @@ -92,7 +131,7 @@ int ha_myisammrg::close(void) int ha_myisammrg::write_row(byte * buf) { - statistic_increment(ha_write_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) @@ -102,7 +141,7 @@ int ha_myisammrg::write_row(byte * buf) int ha_myisammrg::update_row(const byte * old_data, byte * new_data) { - statistic_increment(ha_update_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); return myrg_update(file,old_data,new_data); @@ -110,14 +149,15 @@ int ha_myisammrg::update_row(const byte * old_data, byte * new_data) int ha_myisammrg::delete_row(const byte * buf) { - statistic_increment(ha_delete_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); return myrg_delete(file,buf); } int ha_myisammrg::index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(ha_read_key_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -126,7 +166,8 @@ int ha_myisammrg::index_read(byte * buf, const byte * key, int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key, uint key_len, enum ha_rkey_function find_flag) { - statistic_increment(ha_read_key_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); int error=myrg_rkey(file,buf,index, key, key_len, find_flag); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -134,7 +175,8 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key, int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len) { - statistic_increment(ha_read_key_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); int error=myrg_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST); table->status=error ? STATUS_NOT_FOUND: 0; @@ -143,7 +185,8 @@ int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len) int ha_myisammrg::index_next(byte * buf) { - statistic_increment(ha_read_next_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_next_count, + &LOCK_status); int error=myrg_rnext(file,buf,active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -151,7 +194,8 @@ int ha_myisammrg::index_next(byte * buf) int ha_myisammrg::index_prev(byte * buf) { - statistic_increment(ha_read_prev_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_prev_count, + &LOCK_status); int error=myrg_rprev(file,buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -159,7 +203,8 @@ int ha_myisammrg::index_prev(byte * buf) int ha_myisammrg::index_first(byte * buf) { - statistic_increment(ha_read_first_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_first_count, + &LOCK_status); int error=myrg_rfirst(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -167,7 +212,8 @@ int ha_myisammrg::index_first(byte * buf) int ha_myisammrg::index_last(byte * buf) { - statistic_increment(ha_read_last_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_last_count, + &LOCK_status); int error=myrg_rlast(file, buf, active_index); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -177,7 +223,8 @@ int ha_myisammrg::index_next_same(byte * buf, const byte *key __attribute__((unused)), uint length __attribute__((unused))) { - statistic_increment(ha_read_next_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_next_count, + &LOCK_status); int error=myrg_rnext_same(file,buf); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -190,7 +237,8 @@ int ha_myisammrg::rnd_init(bool scan) int ha_myisammrg::rnd_next(byte *buf) { - statistic_increment(ha_read_rnd_next_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, + &LOCK_status); int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR); table->status=error ? STATUS_NOT_FOUND: 0; return error; @@ -198,8 +246,9 @@ int ha_myisammrg::rnd_next(byte *buf) int ha_myisammrg::rnd_pos(byte * buf, byte *pos) { - statistic_increment(ha_read_rnd_count,&LOCK_status); - int error=myrg_rrnd(file, buf, ha_get_ptr(pos,ref_length)); + statistic_increment(table->in_use->status_var.ha_read_rnd_count, + &LOCK_status); + int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length)); table->status=error ? STATUS_NOT_FOUND: 0; return error; } @@ -207,7 +256,7 @@ int ha_myisammrg::rnd_pos(byte * buf, byte *pos) void ha_myisammrg::position(const byte *record) { ulonglong position= myrg_position(file); - ha_store_ptr(ref, ref_length, (my_off_t) position); + my_store_ptr(ref, ref_length, (my_off_t) position); } @@ -231,15 +280,35 @@ void ha_myisammrg::info(uint flag) #if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4 if ((info.records >= (ulonglong) 1 << 32) || (info.deleted >= (ulonglong) 1 << 32)) - table->crashed=1; + table->s->crashed= 1; #endif data_file_length=info.data_file_length; errkey = info.errkey; - table->keys_in_use.set_prefix(table->keys); - table->db_options_in_use = info.options; - table->is_view=1; - mean_rec_length=info.reclength; - block_size=0; + table->s->keys_in_use.set_prefix(table->s->keys); + table->s->db_options_in_use= info.options; + table->s->is_view= 1; + mean_rec_length= info.reclength; + + /* + The handler::block_size is used all over the code in index scan cost + calculations. It is used to get number of disk seeks required to + retrieve a number of index tuples. + If the merge table has N underlying tables, then (assuming underlying + tables have equal size, the only "simple" approach we can use) + retrieving X index records from a merge table will require N times more + disk seeks compared to doing the same on a MyISAM table with equal + number of records. + In the edge case (file_tables > myisam_block_size) we'll get + block_size==0, and index calculation code will act as if we need one + disk seek to retrieve one index tuple. + + TODO: In 5.2 index scan cost calculation will be factored out into a + virtual function in class handler and we'll be able to remove this hack. + */ + block_size= 0; + if (file->tables) + block_size= myisam_block_size / file->tables; + update_time=0; #if SIZEOF_OFF_T > 4 ref_length=6; // Should be big enough @@ -248,10 +317,10 @@ void ha_myisammrg::info(uint flag) #endif if (flag & HA_STATUS_CONST) { - if (table->key_parts && info.rec_per_key) + if (table->s->key_parts && info.rec_per_key) memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key, - sizeof(table->key_info[0].rec_per_key)*table->key_parts); + sizeof(table->key_info[0].rec_per_key)*table->s->key_parts); } } @@ -351,14 +420,14 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) goto err; split_file_name(open_table->table->filename, &db, &name); - if (!(ptr->real_name= thd->strmake(name.str, name.length))) + if (!(ptr->table_name= thd->strmake(name.str, name.length))) goto err; if (db.length && !(ptr->db= thd->strmake(db.str, db.length))) goto err; create_info->merge_list.elements++; (*create_info->merge_list.next) = (byte*) ptr; - create_info->merge_list.next= (byte**) &ptr->next; + create_info->merge_list.next= (byte**) &ptr->next_local; } *create_info->merge_list.next=0; } @@ -378,21 +447,22 @@ err: int ha_myisammrg::create(const char *name, register TABLE *form, HA_CREATE_INFO *create_info) { - char buff[FN_REFLEN],**table_names,**pos; + char buff[FN_REFLEN]; + const char **table_names, **pos; TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first; THD *thd= current_thd; uint dirlgt= dirname_length(name); DBUG_ENTER("ha_myisammrg::create"); - if (!(table_names= (char**) thd->alloc((create_info->merge_list.elements+1)* - sizeof(char*)))) + if (!(table_names= (const char**) + thd->alloc((create_info->merge_list.elements+1) * sizeof(char*)))) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - for (pos=table_names ; tables ; tables=tables->next) + for (pos= table_names; tables; tables= tables->next_local) { - char *table_name; + const char *table_name; TABLE **tbl= 0; if (create_info->options & HA_LEX_CREATE_TMP_TABLE) - tbl= find_temporary_table(thd, tables->db, tables->real_name); + tbl= find_temporary_table(thd, tables->db, tables->table_name); if (!tbl) { /* @@ -407,7 +477,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form, an embedded server without changing the paths in the .MRG file. */ uint length= my_snprintf(buff, FN_REFLEN, "%s/%s/%s", mysql_data_home, - tables->db, tables->real_name); + tables->db, tables->table_name); /* If a MyISAM table is in the same directory as the MERGE table, we use the table name without a path. This means that the @@ -415,19 +485,18 @@ int ha_myisammrg::create(const char *name, register TABLE *form, as the MyISAM tables are from the same database as the MERGE table. */ if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt)) - table_name= tables->real_name; + table_name= tables->table_name; else if (! (table_name= thd->strmake(buff, length))) DBUG_RETURN(HA_ERR_OUT_OF_MEM); } else - table_name=(*tbl)->path; - DBUG_PRINT("info",("MyISAM table_name: '%s'", table_name)); + table_name= (*tbl)->s->path; *pos++= table_name; } *pos=0; DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16), - (const char **) table_names, + table_names, create_info->merge_insert_method, (my_bool) 0)); } @@ -441,14 +510,14 @@ void ha_myisammrg::append_create_info(String *packet) if (file->merge_insert_method != MERGE_INSERT_DISABLED) { - packet->append(" INSERT_METHOD=",15); + packet->append(STRING_WITH_LEN(" INSERT_METHOD=")); packet->append(get_type(&merge_insert_method,file->merge_insert_method-1)); } - packet->append(" UNION=(",8); + packet->append(STRING_WITH_LEN(" UNION=(")); MYRG_TABLE *open_table,*first; - current_db= table->table_cache_key; - db_length= strlen(current_db); + current_db= table->s->db; + db_length= (uint) strlen(current_db); for (first=open_table=file->open_tables ; open_table != file->end_table ; |