summaryrefslogtreecommitdiff
path: root/sql/ha_myisammrg.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/ha_myisammrg.cc')
-rw-r--r--sql/ha_myisammrg.cc157
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 ;