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