diff options
Diffstat (limited to 'sql/ha_myisam.cc')
-rw-r--r-- | sql/ha_myisam.cc | 873 |
1 files changed, 873 insertions, 0 deletions
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc new file mode 100644 index 00000000000..513a5affcb2 --- /dev/null +++ b/sql/ha_myisam.cc @@ -0,0 +1,873 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifdef __GNUC__ +#pragma implementation // gcc: Class implementation +#endif + +#include "mysql_priv.h" +#include <m_ctype.h> +#include <myisampack.h> +#include "ha_myisam.h" +#include <stdarg.h> +#ifndef MASTER +#include "../srclib/myisam/myisamdef.h" +#else +#include "../myisam/myisamdef.h" +#endif + +ulong myisam_sort_buffer_size; +#if !defined(HAVE_PREAD) +pthread_mutex_t THR_LOCK_keycache; +#endif + +/***************************************************************************** +** MyISAM tables +*****************************************************************************/ + +// collect errors printed by mi_check routines +static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, + const char *fmt, va_list args) +{ + THD* thd = (THD*)param->thd; + String* packet = &thd->packet; + packet->length(0); + char msgbuf[MI_MAX_MSG_BUF]; + msgbuf[0] = 0; + + my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia + + if (thd->net.vio == 0) + { + sql_print_error(msgbuf); + return; + } + + net_store_data(packet, param->table_name); + net_store_data(packet, param->op_name); + net_store_data(packet, msg_type); + net_store_data(packet, msgbuf); + if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length())) + fprintf(stderr, + "Failed on my_net_write, writing to stderr instead: %s\n", + msgbuf); + return; +} + +extern "C" { + +void mi_check_print_error(MI_CHECK *param, const char *fmt,...) +{ + param->error_printed|=1; + va_list args; + va_start(args, fmt); + mi_check_print_msg(param, "error", fmt, args); + va_end(args); +} + +void mi_check_print_info(MI_CHECK *param, const char *fmt,...) +{ + va_list args; + va_start(args, fmt); + mi_check_print_msg(param, "info", fmt, args); + va_end(args); +} + +void mi_check_print_warning(MI_CHECK *param, const char *fmt,...) +{ + param->warning_printed=1; + va_list args; + va_start(args, fmt); + mi_check_print_msg(param, "warning", fmt, args); + va_end(args); +} + +} + +const char **ha_myisam::bas_ext() const +{ static const char *ext[]= { ".MYD",".MYI", NullS }; return ext; } + + +int ha_myisam::net_read_dump(NET* net) +{ + MYISAM_SHARE* share = file->s; + int data_fd = file->dfile; + int error = 0; + + my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME)); + for(;;) + { + uint packet_len = my_net_read(net); + if (!packet_len) + break ; // end of file + if (packet_len == packet_error) + { + sql_print_error("ha_myisam::net_read_dump - read error "); + error= -1; + goto err; + } + if (my_write(data_fd, (byte*)net->read_pos, packet_len, + MYF(MY_WME|MY_FNABP))) + { + error = errno; + goto err; + } + } + +err: + return error; +} + + +int ha_myisam::dump(THD* thd, int fd) +{ + MYISAM_SHARE* share = file->s; + NET* net = &thd->net; + uint blocksize = share->blocksize; + my_off_t bytes_to_read = share->state.state.data_file_length; + int data_fd = file->dfile; + byte * buf = (byte*) my_malloc(blocksize, MYF(MY_WME)); + if(!buf) + return ENOMEM; + + int error = 0; + my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME)); + for(; bytes_to_read > 0;) + { + uint bytes = my_read(data_fd, buf, blocksize, MYF(MY_WME)); + if (bytes == MY_FILE_ERROR) + { + error = errno; + goto err; + } + + if (fd >= 0) + { + if (my_write(fd, buf, bytes, MYF(MY_WME | MY_FNABP))) + { + error = errno ? errno : EPIPE; + goto err; + } + } + else + { + if (my_net_write(net, (char*) buf, bytes)) + { + error = errno ? errno : EPIPE; + goto err; + } + } + bytes_to_read -= bytes; + } + + if (fd < 0) + { + my_net_write(net, "", 0); + net_flush(net); + } + +err: + my_free((gptr) buf, MYF(0)); + return error; +} + +int ha_myisam::open(const char *name, int mode, int test_if_locked) +{ + char name_buff[FN_REFLEN]; + if (!(file=mi_open(fn_format(name_buff,name,"","",2 | 4), mode, + test_if_locked))) + return (my_errno ? my_errno : -1); + + if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED || + test_if_locked == HA_OPEN_ABORT_IF_LOCKED)) + VOID(mi_extra(file,HA_EXTRA_NO_WAIT_LOCK)); + 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)); + if (!table->db_record_offset) + int_option_flag|=HA_REC_NOT_IN_SEQ; + return (0); +} + +int ha_myisam::close(void) +{ + MI_INFO *tmp=file; + file=0; + return mi_close(tmp); +} + +int ha_myisam::write_row(byte * buf) +{ + statistic_increment(ha_write_count,&LOCK_status); + if (table->time_stamp) + update_timestamp(buf+table->time_stamp-1); + if (table->next_number_field && buf == table->record[0]) + update_auto_increment(); + return mi_write(file,buf); +} + +int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) +{ + if (!file) return HA_CHECK_INTERNAL_ERROR; + int error ; + MI_CHECK param; + MYISAM_SHARE* share = file->s; + + myisamchk_init(¶m); + param.thd = thd; + param.op_name = (char*)"check"; + param.table_name = table->table_name; + param.testflag = check_opt->flags | T_CHECK | T_SILENT; + if (check_opt->quick) + param.testflag |= T_FAST; + + if (!(table->db_stat & HA_READ_ONLY)) + param.testflag|= T_STATISTICS; + param.using_global_keycache = 1; + + error = chk_size(¶m, file); + if (!((param.testflag & T_FAST) && share->state.open_count == 1 && + !share->state.changed)) + { + if (!error) + error |= chk_del(¶m, file, param.testflag); + if (!error) + error = chk_key(¶m, file); + if (!error) + { + if (!(param.testflag & T_FAST) || + (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) + { + init_io_cache(¶m.read_cache, file->dfile, + my_default_record_cache_size, READ_CACHE, + share->pack.header_length, 1, MYF(MY_WME)); + error |= chk_data_link(¶m, file, param.testflag & T_EXTEND); + end_io_cache(&(param.read_cache)); + } + } + } + if (!error) + { + if (share->state.changed) + { + file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; + pthread_mutex_lock(&share->intern_lock); +#ifndef HAVE_PREAD + pthread_mutex_lock(&THR_LOCK_keycache); // QQ; Has to be removed! +#endif + share->state.changed=0; + if (!(table->db_stat & HA_READ_ONLY)) + error=update_state_info(¶m,file,UPDATE_TIME | UPDATE_OPEN_COUNT); +#ifndef HAVE_PREAD + pthread_mutex_unlock(&THR_LOCK_keycache);// QQ; Has to be removed! +#endif + pthread_mutex_unlock(&share->intern_lock); + } + } + else if (!mi_is_crashed(file)) + { + mi_mark_crashed(file); + file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; + } + + return error ? HA_CHECK_CORRUPT : HA_CHECK_OK; +} + + +/* + analyze the key distribution in the table + As the table may be only locked for read, we have to take into account that + two threads may do an analyze at the same time! +*/ + +int ha_myisam::analyze(THD *thd) +{ + int error; + MI_CHECK param; + MYISAM_SHARE* share = file->s; + + myisamchk_init(¶m); + param.thd = thd; + param.op_name = (char*)" analyze"; + param.table_name = table->table_name; + param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS | + T_DONT_CHECK_CHECKSUM); + param.using_global_keycache = 1; + + error = chk_key(¶m, file); + if (!error) + { + pthread_mutex_lock(&share->intern_lock); +#ifndef HAVE_PREAD + pthread_mutex_lock(&THR_LOCK_keycache); // QQ; Has to be removed! +#endif + error=update_state_info(¶m,file,UPDATE_STAT); +#ifndef HAVE_PREAD + pthread_mutex_unlock(&THR_LOCK_keycache);// QQ; Has to be removed! +#endif + pthread_mutex_unlock(&share->intern_lock); + } + else if (!mi_is_crashed(file)) + mi_mark_crashed(file); + return error ? HA_CHECK_CORRUPT : HA_CHECK_OK; +} + + +int ha_myisam::repair(THD* thd, HA_CHECK_OPT* check_opt) +{ + if (!file) return HA_CHECK_INTERNAL_ERROR; + int error ; + MI_CHECK param; + MYISAM_SHARE* share = file->s; + char fixed_name[FN_REFLEN]; + + myisamchk_init(¶m); + param.thd = thd; + param.op_name = (char*) "repair"; + param.table_name = table->table_name; + param.testflag = check_opt->flags | T_SILENT|T_FORCE_CREATE|T_REP_BY_SORT; + param.sort_buffer_length= check_opt->sort_buffer_size; + if (check_opt->quick) + param.opt_rep_quick++; + param.tmpfile_createflag = O_RDWR | O_TRUNC; + param.using_global_keycache = 1; + + VOID(fn_format(fixed_name,file->filename,"",MI_NAME_IEXT, + 4+ (param.opt_follow_links ? 16 : 0))); + + if (share->state.key_map) + error = mi_repair_by_sort(¶m, file, fixed_name, param.opt_rep_quick); + else + error= mi_repair(¶m, file, fixed_name, param.opt_rep_quick); + if (!error) + { + if (share->state.changed) + { + share->state.changed = 0; + file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; + } + file->save_state=file->s->state.state; + if (file->s->base.auto_key) + update_auto_increment_key(¶m, file, 1); + error = update_state_info(¶m, file, UPDATE_TIME|UPDATE_STAT); + } + else if (!mi_is_crashed(file)) + { + mi_mark_crashed(file); + file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; + } + if (!error) + { + if (param.out_flag & (O_NEW_DATA | O_NEW_INDEX)) + { + /* + We have to close all instances of this file to ensure that we can + do the rename safely and that all threads are using the new version. + */ + VOID(pthread_mutex_lock(&LOCK_open)); + if (close_cached_table(thd,table)) + error=1; + + if (param.out_flag & O_NEW_DATA) + error|=change_to_newfile(fixed_name,MI_NAME_DEXT, + DATA_TMP_EXT, 0); + + if (param.out_flag & O_NEW_INDEX) + error|=change_to_newfile(fixed_name,MI_NAME_IEXT, + INDEX_TMP_EXT,0); + VOID(pthread_mutex_unlock(&LOCK_open)); + } + } + return error ? HA_REPAIR_FAILED : HA_REPAIR_OK; +} + + + +int ha_myisam::update_row(const byte * old_data, byte * new_data) +{ + statistic_increment(ha_update_count,&LOCK_status); + if (table->time_stamp) + update_timestamp(new_data+table->time_stamp-1); + return mi_update(file,old_data,new_data); +} + +int ha_myisam::delete_row(const byte * buf) +{ + statistic_increment(ha_delete_count,&LOCK_status); + return mi_delete(file,buf); +} + +int ha_myisam::index_read(byte * buf, const byte * key, + uint key_len, enum ha_rkey_function find_flag) +{ + statistic_increment(ha_read_key_count,&LOCK_status); + int error=mi_rkey(file,buf,active_index, key, key_len, find_flag); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::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); + int error=mi_rkey(file,buf,index, key, key_len, find_flag); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::index_next(byte * buf) +{ + statistic_increment(ha_read_next_count,&LOCK_status); + int error=mi_rnext(file,buf,active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::index_prev(byte * buf) +{ + statistic_increment(ha_read_prev_count,&LOCK_status); + int error=mi_rprev(file,buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::index_first(byte * buf) +{ + statistic_increment(ha_read_first_count,&LOCK_status); + int error=mi_rfirst(file, buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::index_last(byte * buf) +{ + statistic_increment(ha_read_last_count,&LOCK_status); + int error=mi_rlast(file, buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::index_next_same(byte * buf, + const byte *key __attribute__((unused)), + uint length __attribute__((unused))) +{ + statistic_increment(ha_read_next_count,&LOCK_status); + int error=mi_rnext_same(file,buf); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + + +int ha_myisam::rnd_init(bool scan) +{ + if (scan) + return mi_scan_init(file); + else + return mi_extra(file,HA_EXTRA_RESET); +} + +int ha_myisam::rnd_next(byte *buf) +{ + statistic_increment(ha_read_rnd_next_count,&LOCK_status); + int error=mi_scan(file, buf); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisam::restart_rnd_next(byte *buf, byte *pos) +{ + return rnd_pos(buf,pos); +} + +int ha_myisam::rnd_pos(byte * buf, byte *pos) +{ + statistic_increment(ha_read_rnd_count,&LOCK_status); + int error=mi_rrnd(file, buf, ha_get_ptr(pos,ref_length)); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +void ha_myisam::position(const byte* record) +{ + my_off_t position=mi_position(file); + ha_store_ptr(ref, ref_length, position); +} + +void ha_myisam::info(uint flag) +{ + MI_ISAMINFO info; + (void) mi_status(file,&info,flag); + if (flag & HA_STATUS_VARIABLE) + { + records = info.records; + deleted = info.deleted; + data_file_length=info.data_file_length; + index_file_length=info.index_file_length; + delete_length = info.delete_length; + check_time = info.check_time; + mean_rec_length=info.mean_reclength; + } + if (flag & HA_STATUS_CONST) + { + max_data_file_length=info.max_data_file_length; + max_index_file_length=info.max_index_file_length; + create_time = info.create_time; + sortkey = info.sortkey; + ref_length=info.reflength; + table->db_options_in_use = info.options; + block_size=myisam_block_size; + table->keys_in_use &= info.key_map; + table->db_record_offset=info.record_offset; + if (table->key_parts) + memcpy((char*) table->key_info[0].rec_per_key, + (char*) info.rec_per_key, + sizeof(ulong)*table->key_parts); + raid_type=info.raid_type; + raid_chunks=info.raid_chunks; + raid_chunksize=info.raid_chunksize; + } + if (flag & HA_STATUS_ERRKEY) + { + errkey = info.errkey; + ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos); + } + if (flag & HA_STATUS_TIME) + update_time = info.update_time; + if (flag & HA_STATUS_AUTO) + auto_increment_value= info.auto_increment; +} + + +int ha_myisam::extra(enum ha_extra_function operation) +{ + if (((specialflag & SPECIAL_SAFE_MODE) || (test_flags & TEST_NO_EXTRA)) && + (operation == HA_EXTRA_WRITE_CACHE || + operation == HA_EXTRA_KEYREAD)) + return 0; + return mi_extra(file,operation); +} + +int ha_myisam::reset(void) +{ + return mi_extra(file,HA_EXTRA_RESET); +} + +int ha_myisam::delete_all_rows() +{ + return mi_delete_all_rows(file); +} + +int ha_myisam::delete_table(const char *name) +{ + return mi_delete_table(name); +} + +int ha_myisam::external_lock(THD *thd, int lock_type) +{ + return mi_lock_database(file,lock_type); +} + + +THR_LOCK_DATA **ha_myisam::store_lock(THD *thd, + THR_LOCK_DATA **to, + enum thr_lock_type lock_type) +{ + if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK) + file->lock.type=lock_type; + *to++= &file->lock; + return to; +} + +void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) +{ + table->file->info(HA_STATUS_AUTO | HA_STATUS_CONST); + if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) + { + 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; + } +} + + +int ha_myisam::create(const char *name, register TABLE *form, + HA_CREATE_INFO *info) +{ + int error; + uint i,j,recpos,minpos,fieldpos,temp_length,length; + bool found_auto_increment=0; + enum ha_base_keytype type; + char buff[FN_REFLEN]; + KEY *pos; + MI_KEYDEF *keydef; + MI_COLUMNDEF *recinfo,*recinfo_pos; + MI_KEYSEG *keyseg; + uint options=form->db_options_in_use; + DBUG_ENTER("ha_myisam::create"); + + type=HA_KEYTYPE_BINARY; // Keep compiler happy + if (!(my_multi_malloc(MYF(MY_WME), + &recinfo,(form->fields*2+2)*sizeof(MI_COLUMNDEF), + &keydef, form->keys*sizeof(MI_KEYDEF), + &keyseg, + ((form->key_parts + form->keys) * sizeof(MI_KEYSEG)), + 0))) + DBUG_RETURN(1); + + pos=form->key_info; + for (i=0; i < form->keys ; i++, pos++) + { + keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT)); + keydef[i].seg=keyseg; + keydef[i].keysegs=pos->key_parts; + for (j=0 ; j < pos->key_parts ; j++) + { + keydef[i].seg[j].flag=pos->key_part[j].key_part_flag; + Field *field=pos->key_part[j].field; + type=field->key_type(); + + if (options & HA_OPTION_PACK_KEYS || + (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY | + HA_SPACE_PACK_USED))) + { + if (pos->key_part[j].length > 8 && + (type == HA_KEYTYPE_TEXT || + type == HA_KEYTYPE_NUM || + (type == HA_KEYTYPE_BINARY && !field->zero_pack()))) + { + /* No blobs here */ + if (j == 0) + keydef[i].flag|=HA_PACK_KEY; + if (!(field->flags & ZEROFILL_FLAG) && + (field->type() == FIELD_TYPE_STRING || + field->type() == FIELD_TYPE_VAR_STRING || + ((int) (pos->key_part[j].length - field->decimals())) + >= 4)) + keydef[i].seg[j].flag|=HA_SPACE_PACK; + } + else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16)) + keydef[i].flag|= HA_BINARY_PACK_KEY; + } + keydef[i].seg[j].type= (int) type; + keydef[i].seg[j].start= pos->key_part[j].offset; + keydef[i].seg[j].length= pos->key_part[j].length; + keydef[i].seg[j].bit_start=keydef[i].seg[j].bit_end=0; + keydef[i].seg[j].language=MY_CHARSET_CURRENT; + + if (field->null_ptr) + { + keydef[i].seg[j].null_bit=field->null_bit; + keydef[i].seg[j].null_pos= (uint) (field->null_ptr- + (uchar*) form->record[0]); + } + else + { + keydef[i].seg[j].null_bit=0; + keydef[i].seg[j].null_pos=0; + } + if (j == 0 && field->flags & AUTO_INCREMENT_FLAG && + !found_auto_increment) + { + keydef[i].flag|=HA_AUTO_KEY; + found_auto_increment=1; + } + if (field->type() == FIELD_TYPE_BLOB) + { + keydef[i].seg[j].flag|=HA_BLOB_PART; + /* save number of bytes used to pack length */ + keydef[i].seg[j].bit_start= (uint) (field->pack_length() - + form->blob_ptr_size); + } + } + keyseg+=pos->key_parts; + } + + recpos=0; recinfo_pos=recinfo; + while (recpos < (uint) form->reclength) + { + Field **field,*found=0; + minpos=form->reclength; length=0; + + for (field=form->field ; *field ; field++) + { + if ((fieldpos=(*field)->offset()) >= recpos && + fieldpos <= minpos) + { + /* skip null fields */ + if (!(temp_length= (*field)->pack_length())) + continue; /* Skipp null-fields */ + if (! found || fieldpos < minpos || + (fieldpos == minpos && temp_length < length)) + { + minpos=fieldpos; found= *field; length=temp_length; + } + } + } + DBUG_PRINT("loop",("found: %lx recpos: %d minpos: %d length: %d", + found,recpos,minpos,length)); + if (recpos != minpos) + { // Reserved space (Null bits?) + bzero((char*) recinfo_pos,sizeof(*recinfo_pos)); + recinfo_pos->type=(int) FIELD_NORMAL; + recinfo_pos++->length= (uint16) (minpos-recpos); + } + if (! found) + break; + + if (found->flags & BLOB_FLAG) + { + recinfo_pos->type= (int) FIELD_BLOB; + } + else if (!(options & HA_OPTION_PACK_RECORD)) + recinfo_pos->type= (int) FIELD_NORMAL; + else if (found->zero_pack()) + recinfo_pos->type= (int) FIELD_SKIPP_ZERO; + else + recinfo_pos->type= (int) ((length <= 3 || + (found->flags & ZEROFILL_FLAG)) ? + FIELD_NORMAL : + found->type() == FIELD_TYPE_STRING || + found->type() == FIELD_TYPE_VAR_STRING ? + FIELD_SKIPP_ENDSPACE : + FIELD_SKIPP_PRESPACE); + if (found->null_ptr) + { + recinfo_pos->null_bit=found->null_bit; + recinfo_pos->null_pos= (uint) (found->null_ptr- + (uchar*) form->record[0]); + } + else + { + recinfo_pos->null_bit=0; + recinfo_pos->null_pos=0; + } + (recinfo_pos++) ->length=(uint16) length; + recpos=minpos+length; + DBUG_PRINT("loop",("length: %d type: %d", + recinfo_pos[-1].length,recinfo_pos[-1].type)); + + } + MI_CREATE_INFO create_info; + bzero((char*) &create_info,sizeof(create_info)); + create_info.max_rows=form->max_rows; + create_info.reloc_rows=form->min_rows; + create_info.auto_increment=(info->auto_increment_value ? + info->auto_increment_value -1 : + (ulonglong) 0); + create_info.data_file_length=(ulonglong) form->max_rows*form->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; + + error=mi_create(fn_format(buff,name,"","",2+4+16), + form->keys,keydef, + (uint) (recinfo_pos-recinfo), recinfo, + 0, (MI_UNIQUEDEF*) 0, + &create_info, + (((options & HA_OPTION_PACK_RECORD) ? HA_PACK_RECORD : 0) | + ((options & HA_OPTION_CHECKSUM) ? HA_CREATE_CHECKSUM : 0) | + ((options & HA_OPTION_DELAY_KEY_WRITE) ? + HA_CREATE_DELAY_KEY_WRITE : 0))); + + + my_free((gptr) recinfo,MYF(0)); + DBUG_RETURN(error); +} + + +int ha_myisam::rename_table(const char * from, const char * to) +{ + return mi_rename(from,to); +} + + +longlong ha_myisam::get_auto_increment() +{ + if (!table->next_number_key_offset) + { // Autoincrement at key-start + ha_myisam::info(HA_STATUS_AUTO); + return auto_increment_value; + } + + longlong nr; + int error; + byte key[MAX_KEY_LENGTH]; + (void) extra(HA_EXTRA_KEYREAD); + key_copy(key,table,table->next_number_index, + table->next_number_key_offset); + error=mi_rkey(file,table->record[1],(int) table->next_number_index, + key,table->next_number_key_offset,HA_READ_PREFIX_LAST); + if (error) + nr=1; + else + nr=(longlong) + table->next_number_field->val_int_offset(table->rec_buff_length)+1; + extra(HA_EXTRA_NO_KEYREAD); + return nr; +} + + +ha_rows ha_myisam::records_in_range(int inx, + const byte *start_key,uint start_key_len, + enum ha_rkey_function start_search_flag, + const byte *end_key,uint end_key_len, + enum ha_rkey_function end_search_flag) +{ + return (ha_rows) mi_records_in_range(file, + inx, + start_key,start_key_len, + start_search_flag, + end_key,end_key_len, + end_search_flag); +} + +int ha_myisam::ft_init(uint inx, const byte *key, uint keylen, bool presort) +{ + if (ft_handler) + return -1; + + // Do the search! + ft_handler=ft_init_search(file,inx,(byte*) key,keylen,presort); + + if (!ft_handler) + return (my_errno ? my_errno : -1); + + return 0; +} + +int ha_myisam::ft_read(byte * buf) +{ + int error; + + thread_safe_increment(ha_read_next_count,&LOCK_status); // why ? + if (ft_handler) + ft_relevance=ft_read_next((FT_DOCLIST *) ft_handler,(char*) buf); + else + ft_relevance=0; + + error=((ft_relevance == 0) ? HA_ERR_END_OF_FILE : + (ft_relevance > 0) ? 0 : + (int) -ft_relevance); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + |