diff options
Diffstat (limited to 'myisam/mi_check.c')
-rw-r--r-- | myisam/mi_check.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 5b5583b136e..f8667afb46a 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -220,7 +220,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) if (next_link > info->state->key_file_length || next_link & (info->s->blocksize-1)) DBUG_RETURN(1); - if (!(buff=key_cache_read(info->s->kfile, next_link, info->buff, + if (!(buff=key_cache_read(info->s->kfile, next_link, (byte*) info->buff, myisam_block_size, block_size, 1))) DBUG_RETURN(1); next_link=mi_sizekorr(buff); @@ -1228,6 +1228,8 @@ err: VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks, MYF(MY_WME))); } + mi_mark_crashed_on_repair(info); + info->update|= HA_STATE_CHANGED; } if (sort_info->record) my_free(sort_info->record,MYF(0)); @@ -1580,7 +1582,7 @@ err: DBUG_RETURN(1); } - /* Fix table using sorting */ + /* Fix table or given index using sorting */ /* saves new table in temp_filename */ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, @@ -1597,6 +1599,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ulong *rec_per_key_part; char llbuff[22]; SORT_INFO *sort_info= ¶m->sort_info; + ulonglong key_map=share->state.key_map; DBUG_ENTER("rep_by_sort"); start_records=info->state->records; @@ -1621,7 +1624,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, init_io_cache(&info->rec_cache,info->dfile, (uint) param->write_buffer_length, WRITE_CACHE,new_header_length,1, - MYF(MY_WME | MY_WAIT_IF_FULL)))) + MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw))) goto err; sort_info->key_block_end=sort_info->key_block+param->sort_key_blocks; info->opt_flag|=WRITE_CACHE_USED; @@ -1664,10 +1667,15 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - for (i=0 ; i < share->base.keys ; i++) - share->state.key_root[i]= HA_OFFSET_ERROR; - for (i=0 ; i < share->state.header.max_block_size ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; + if (!(param->testflag & T_CREATE_MISSING_KEYS)) + { + for (i=0 ; i < share->base.keys ; i++) + share->state.key_root[i]= HA_OFFSET_ERROR; + for (i=0 ; i < share->state.header.max_block_size ; i++) + share->state.key_del[i]= HA_OFFSET_ERROR; + } + else + key_map= ~key_map; /* Create the missing keys */ info->state->key_file_length=share->base.keystart; @@ -1696,7 +1704,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, else length=share->base.pack_reclength; sort_param.max_records=sort_info->max_records= - (ha_rows) (sort_info->filelength/length+1); + ((param->testflag & T_TRUST_HEADER) ? info->state->records : + (ha_rows) (sort_info->filelength/length+1)); sort_param.key_cmp=sort_key_cmp; sort_param.key_write=sort_key_write; sort_param.key_read=sort_key_read; @@ -1714,7 +1723,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, rec_per_key_part+=sort_info->keyinfo->keysegs, sort_info->key++) { sort_info->keyinfo=share->keyinfo+sort_info->key; - if (!(((ulonglong) 1 << sort_info->key) & share->state.key_map)) + if (!(((ulonglong) 1 << sort_info->key) & key_map)) continue; if ((!(param->testflag & T_SILENT))) @@ -1755,6 +1764,15 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, param->read_cache.end_of_file=sort_info->filepos; if (write_data_suffix(param,info) || end_io_cache(&info->rec_cache)) goto err; + if (param->testflag & T_SAFE_REPAIR) + { + /* Don't repair if we loosed more than one row */ + if (info->state->records+1 < start_records) + { + info->state->records=start_records; + goto err; + } + } share->state.state.data_file_length = info->state->data_file_length = sort_info->filepos; /* Only whole records */ @@ -1837,6 +1855,8 @@ err: VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks, MYF(MY_WME))); } + mi_mark_crashed_on_repair(info); + info->update|= HA_STATE_CHANGED; } my_free((gptr) sort_info->key_block,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR)); @@ -1844,7 +1864,7 @@ err: VOID(end_io_cache(¶m->read_cache)); VOID(end_io_cache(&info->rec_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - if (!got_error && param->testflag & T_UNPACK) + if (!got_error && (param->testflag & T_UNPACK)) { share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; share->pack.header_length=0; @@ -2884,3 +2904,58 @@ ha_checksum mi_byte_checksum(const byte *buf, uint length) test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1))); return crc; } + +/* + Deactive all not unique index that can be recreated fast + These include packed keys on which sorting will use more temporary + space than the max allowed file length or for which the unpacked keys + will take much more space than packed keys. + Note that 'rows' may be zero for the case when we don't know how many + rows we will put into the file. + */ + +static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows) +{ + return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) && + ((ulonglong) rows * key->maxlength > MAX_FILE_SIZE || + (ulonglong) rows * (key->maxlength - key->minlength) / 2 > + MI_MAX_TEMP_LENGTH || + (rows == 0 && (key->maxlength / key->minlength) > 2))); +} + + +void mi_dectivate_non_unique_index(MI_INFO *info, ha_rows rows) +{ + MYISAM_SHARE *share=info->s; + uint i; + if (!info->state->records) /* Don't do this if old rows */ + { + MI_KEYDEF *key=share->keyinfo; + for (i=0 ; i < share->base.keys ; i++,key++) + { + if (!(key->flag & HA_NOSAME) && ! mi_too_big_key_for_sort(key,rows)) + { + share->state.key_map&= ~ ((ulonglong) 1 << i); + info->update|= HA_STATE_CHANGED; + } + } + } +} + + +/* Return TRUE if we can use repair by sorting */ + +my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows) +{ + MYISAM_SHARE *share=info->s; + uint i; + MI_KEYDEF *key=share->keyinfo; + if (!share->state.key_map) + return FALSE; /* Can't use sort */ + for (i=0 ; i < share->base.keys ; i++,key++) + { + if (mi_too_big_key_for_sort(key,rows)) + return FALSE; + } + return TRUE; +} |