diff options
Diffstat (limited to 'sql/ha_isam.cc')
-rw-r--r-- | sql/ha_isam.cc | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc new file mode 100644 index 00000000000..fc836977f23 --- /dev/null +++ b/sql/ha_isam.cc @@ -0,0 +1,390 @@ +/* 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_isam.h" +#ifndef MASTER +#include "../srclib/isam/isamdef.h" +#else +#include "../isam/isamdef.h" +#endif + +/***************************************************************************** +** isam tables +*****************************************************************************/ + +const char **ha_isam::bas_ext() const +{ static const char *ext[]= { ".ISD",".ISM", NullS }; return ext; } + + +int ha_isam::open(const char *name, int mode, int test_if_locked) +{ + char name_buff[FN_REFLEN]; + if (!(file=nisam_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) nisam_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) nisam_extra(file,HA_EXTRA_WAIT_LOCK); + if (!table->db_record_offset) + int_option_flag|=HA_REC_NOT_IN_SEQ; + return (0); +} + +int ha_isam::close(void) +{ + return !nisam_close(file) ? 0 : my_errno ? my_errno : -1; +} + +uint ha_isam::min_record_length(uint options) const +{ + return (options & HA_OPTION_PACK_RECORD) ? 1 : 5; +} + + +int ha_isam::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 !nisam_write(file,buf) ? 0 : my_errno ? my_errno : -1; +} + +int ha_isam::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 !nisam_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1; +} + +int ha_isam::delete_row(const byte * buf) +{ + statistic_increment(ha_delete_count,&LOCK_status); + return !nisam_delete(file,buf) ? 0 : my_errno ? my_errno : -1; +} + +int ha_isam::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=nisam_rkey(file, buf, active_index, key, key_len, find_flag); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : -1; +} + +int ha_isam::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=nisam_rkey(file, buf, index, key, key_len, find_flag); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : -1; +} + +int ha_isam::index_next(byte * buf) +{ + statistic_increment(ha_read_next_count,&LOCK_status); + int error=nisam_rnext(file,buf,active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE; +} + +int ha_isam::index_prev(byte * buf) +{ + statistic_increment(ha_read_prev_count,&LOCK_status); + int error=nisam_rprev(file,buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE; +} + +int ha_isam::index_first(byte * buf) +{ + statistic_increment(ha_read_first_count,&LOCK_status); + int error=nisam_rfirst(file, buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE; +} + +int ha_isam::index_last(byte * buf) +{ + statistic_increment(ha_read_last_count,&LOCK_status); + int error=nisam_rlast(file, buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE; +} + +int ha_isam::rnd_init(bool scan) +{ + return nisam_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;; +} + +int ha_isam::rnd_next(byte *buf) +{ + statistic_increment(ha_read_rnd_next_count,&LOCK_status); + int error=nisam_rrnd(file, buf, NI_POS_ERROR); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : -1; +} + +int ha_isam::rnd_pos(byte * buf, byte *pos) +{ + statistic_increment(ha_read_rnd_count,&LOCK_status); + int error=nisam_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length)); + table->status=error ? STATUS_NOT_FOUND: 0; + return !error ? 0 : my_errno ? my_errno : -1; +} + +void ha_isam::position(const byte *record) +{ + my_off_t position=nisam_position(file); + if (position == (my_off_t) ~ (ulong) 0) + position=HA_OFFSET_ERROR; + ha_store_ptr(ref, ref_length, position); +} + +void ha_isam::info(uint flag) +{ + N_ISAMINFO info; + (void) nisam_info(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.isamchk_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; + block_size=nisam_block_size; + table->keys = min(table->keys,info.keys); + table->keys_in_use= (((key_map) 1) << table->keys)- (key_map) 1; + table->db_options_in_use= info.options; + table->db_record_offset= + (table->db_options_in_use & + (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? 0 : + table->reclength; + if (!table->tmp_table) + { + ulong *rec_per_key=info.rec_per_key; + for (uint i=0 ; i < table->keys ; i++) + { + table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]= + *(rec_per_key++); + } + } + ref_length=4; + } + 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; +} + + +int ha_isam::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 nisam_extra(file,operation); +} + +int ha_isam::reset(void) +{ + return nisam_extra(file,HA_EXTRA_RESET); +} + +int ha_isam::external_lock(THD *thd, int lock_type) +{ + return nisam_lock_database(file,lock_type); +} + + +THR_LOCK_DATA **ha_isam::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; +} + + +int ha_isam::create(const char *name, register TABLE *form, + HA_CREATE_INFO *create_info) + +{ + uint options=form->db_options_in_use; + int error; + uint i,j,recpos,minpos,fieldpos,temp_length,length; + enum ha_base_keytype type; + char buff[FN_REFLEN]; + KEY *pos; + N_KEYDEF keydef[MAX_KEY]; + N_RECINFO *recinfo,*recinfo_pos; + DBUG_ENTER("ha_isam::create"); + + type=HA_KEYTYPE_BINARY; // Keep compiler happy + if (!(recinfo= (N_RECINFO*) my_malloc((form->fields*2+2)*sizeof(N_RECINFO), + MYF(MY_WME)))) + DBUG_RETURN(1); + + pos=form->key_info; + for (i=0; i < form->keys ; i++, pos++) + { + keydef[i].base.flag= (pos->flags & HA_NOSAME); + for (j=0 ; (int7) j < pos->key_parts ; j++) + { + keydef[i].seg[j].base.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))) && + pos->key_part[j].length > 8 && + (type == HA_KEYTYPE_TEXT || + type == HA_KEYTYPE_NUM || + (type == HA_KEYTYPE_BINARY && !field->zero_pack()))) + { + if (j == 0) + keydef[i].base.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].base.flag|=HA_SPACE_PACK; + } + keydef[i].seg[j].base.type=(int) type; + keydef[i].seg[j].base.start= pos->key_part[j].offset; + keydef[i].seg[j].base.length= pos->key_part[j].length; + } + keydef[i].seg[j].base.type=(int) HA_KEYTYPE_END; /* End of 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?) + recinfo_pos->base.type=(int) FIELD_NORMAL; + recinfo_pos++->base.length= (uint16) (minpos-recpos); + } + if (! found) + break; + + if (found->flags & BLOB_FLAG) + { + /* ISAM can only handle blob pointers of sizeof(char(*)) */ + recinfo_pos->base.type= (int) FIELD_BLOB; + if (options & HA_OPTION_LONG_BLOB_PTR) + length= length-portable_sizeof_char_ptr+sizeof(char*); + } + else if (!(options & HA_OPTION_PACK_RECORD)) + recinfo_pos->base.type= (int) FIELD_NORMAL; + else if (found->zero_pack()) + recinfo_pos->base.type= (int) FIELD_SKIPP_ZERO; + else + recinfo_pos->base.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); + recinfo_pos++ ->base.length=(uint16) length; + recpos=minpos+length; + DBUG_PRINT("loop",("length: %d type: %d", + recinfo_pos[-1].base.length,recinfo_pos[-1].base.type)); + + if ((found->flags & BLOB_FLAG) && (options & HA_OPTION_LONG_BLOB_PTR) && + sizeof(char*) != portable_sizeof_char_ptr) + { // Not used space + recinfo_pos->base.type=(int) FIELD_ZERO; + recinfo_pos++->base.length= + (uint16) (portable_sizeof_char_ptr-sizeof(char*)); + recpos+= (portable_sizeof_char_ptr-sizeof(char*)); + } + } + recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */ + error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef, + recinfo,form->max_rows,form->min_rows,0,0,0L); + my_free((gptr) recinfo,MYF(0)); + DBUG_RETURN(error); + +} + + +ha_rows ha_isam::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) nisam_records_in_range(file, + inx, + start_key,start_key_len, + start_search_flag, + end_key,end_key_len, + end_search_flag); +} |