ha_isam.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:12k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #ifdef USE_PRAGMA_IMPLEMENTATION
  14. #pragma implementation // gcc: Class implementation
  15. #endif
  16. #include "mysql_priv.h"
  17. #ifdef HAVE_ISAM
  18. #include <m_ctype.h>
  19. #include <myisampack.h>
  20. #include "ha_isam.h"
  21. #ifndef MASTER
  22. #include "../srclib/isam/isamdef.h"
  23. #else
  24. #include "../isam/isamdef.h"
  25. #endif
  26. /*****************************************************************************
  27. ** isam tables
  28. *****************************************************************************/
  29. const char **ha_isam::bas_ext() const
  30. { static const char *ext[]= { ".ISM",".ISD", NullS }; return ext; }
  31. int ha_isam::open(const char *name, int mode, uint test_if_locked)
  32. {
  33.   char name_buff[FN_REFLEN];
  34.   if (!(file=nisam_open(fn_format(name_buff,name,"","",2 | 4), mode,
  35.      test_if_locked)))
  36.     return (my_errno ? my_errno : -1);
  37.   if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
  38. test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
  39.     (void) nisam_extra(file,HA_EXTRA_NO_WAIT_LOCK);
  40.   info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
  41.   if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
  42.     (void) nisam_extra(file,HA_EXTRA_WAIT_LOCK);
  43.   if (!table->db_record_offset)
  44.     int_table_flags|=HA_REC_NOT_IN_SEQ;
  45.   return (0);
  46. }
  47. int ha_isam::close(void)
  48. {
  49.   return !nisam_close(file) ? 0 : my_errno ? my_errno : -1;
  50. }
  51. uint ha_isam::min_record_length(uint options) const
  52. {
  53.   return (options & HA_OPTION_PACK_RECORD) ? 1 : 5;
  54. }
  55. int ha_isam::write_row(byte * buf)
  56. {
  57.   statistic_increment(ha_write_count,&LOCK_status);
  58.   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
  59.     table->timestamp_field->set_time();
  60.   if (table->next_number_field && buf == table->record[0])
  61.     update_auto_increment();
  62.   return !nisam_write(file,buf) ? 0 : my_errno ? my_errno : -1;
  63. }
  64. int ha_isam::update_row(const byte * old_data, byte * new_data)
  65. {
  66.   statistic_increment(ha_update_count,&LOCK_status);
  67.   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
  68.     table->timestamp_field->set_time();
  69.   return !nisam_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
  70. }
  71. int ha_isam::delete_row(const byte * buf)
  72. {
  73.   statistic_increment(ha_delete_count,&LOCK_status);
  74.   return !nisam_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
  75. }
  76. int ha_isam::index_read(byte * buf, const byte * key,
  77. uint key_len, enum ha_rkey_function find_flag)
  78. {
  79.   statistic_increment(ha_read_key_count,&LOCK_status);
  80.   int error=nisam_rkey(file, buf, active_index, key, key_len, find_flag);
  81.   table->status=error ? STATUS_NOT_FOUND: 0;
  82.   return !error ? 0 : my_errno ? my_errno : -1;
  83. }
  84. int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
  85.     uint key_len, enum ha_rkey_function find_flag)
  86. {
  87.   statistic_increment(ha_read_key_count,&LOCK_status);
  88.   int error=nisam_rkey(file, buf, index, key, key_len, find_flag);
  89.   table->status=error ? STATUS_NOT_FOUND: 0;
  90.   return !error ? 0 : my_errno ? my_errno : -1;
  91. }
  92. int ha_isam::index_read_last(byte * buf, const byte * key, uint key_len)
  93. {
  94.   statistic_increment(ha_read_key_count,&LOCK_status);
  95.   int error=nisam_rkey(file, buf, active_index, key, key_len,
  96.        HA_READ_PREFIX_LAST);
  97.   table->status=error ? STATUS_NOT_FOUND: 0;
  98.   return !error ? 0 : my_errno ? my_errno : -1;
  99. }
  100. int ha_isam::index_next(byte * buf)
  101. {
  102.   statistic_increment(ha_read_next_count,&LOCK_status);
  103.   int error=nisam_rnext(file,buf,active_index);
  104.   table->status=error ? STATUS_NOT_FOUND: 0;
  105.   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
  106. }
  107. int ha_isam::index_prev(byte * buf)
  108. {
  109.   statistic_increment(ha_read_prev_count,&LOCK_status);
  110.   int error=nisam_rprev(file,buf, active_index);
  111.   table->status=error ? STATUS_NOT_FOUND: 0;
  112.   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
  113. }
  114. int ha_isam::index_first(byte * buf)
  115. {
  116.   statistic_increment(ha_read_first_count,&LOCK_status);
  117.   int error=nisam_rfirst(file, buf, active_index);
  118.   table->status=error ? STATUS_NOT_FOUND: 0;
  119.   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
  120. }
  121. int ha_isam::index_last(byte * buf)
  122. {
  123.   statistic_increment(ha_read_last_count,&LOCK_status);
  124.   int error=nisam_rlast(file, buf, active_index);
  125.   table->status=error ? STATUS_NOT_FOUND: 0;
  126.   return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
  127. }
  128. int ha_isam::rnd_init(bool scan)
  129. {
  130.   return nisam_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;;
  131. }
  132. int ha_isam::rnd_next(byte *buf)
  133. {
  134.   statistic_increment(ha_read_rnd_next_count,&LOCK_status);
  135.   int error=nisam_rrnd(file, buf, NI_POS_ERROR);
  136.   table->status=error ? STATUS_NOT_FOUND: 0;
  137.   return !error ? 0 : my_errno ? my_errno : -1;
  138. }
  139. int ha_isam::rnd_pos(byte * buf, byte *pos)
  140. {
  141.   statistic_increment(ha_read_rnd_count,&LOCK_status);
  142.   int error=nisam_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
  143.   table->status=error ? STATUS_NOT_FOUND: 0;
  144.   return !error ? 0 : my_errno ? my_errno : -1;
  145. }
  146. void ha_isam::position(const byte *record)
  147. {
  148.   my_off_t position=nisam_position(file);
  149.   if (position == (my_off_t) ~ (ulong) 0)
  150.     position=HA_OFFSET_ERROR;
  151.   ha_store_ptr(ref, ref_length, position);
  152. }
  153. void ha_isam::info(uint flag)
  154. {
  155.   N_ISAMINFO info;
  156.   (void) nisam_info(file,&info,flag);
  157.   if (flag & HA_STATUS_VARIABLE)
  158.   {
  159.     records = info.records;
  160.     deleted = info.deleted;
  161.     data_file_length=info.data_file_length;
  162.     index_file_length=info.index_file_length;
  163.     delete_length = info.delete_length;
  164.     check_time  = info.isamchk_time;
  165.     mean_rec_length=info.mean_reclength;
  166.   }
  167.   if (flag & HA_STATUS_CONST)
  168.   {
  169.     max_data_file_length=info.max_data_file_length;
  170.     max_index_file_length=info.max_index_file_length;
  171.     create_time = info.create_time;
  172.     sortkey = info.sortkey;
  173.     block_size=nisam_block_size;
  174.     table->keys    = min(table->keys,info.keys);
  175.     table->keys_in_use.set_prefix(table->keys);
  176.     table->db_options_in_use= info.options;
  177.     table->db_record_offset=
  178.       (table->db_options_in_use &
  179.        (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? 0 :
  180.       table->reclength;
  181.     if (!table->tmp_table)
  182.     {
  183.       ulong *rec_per_key=info.rec_per_key;
  184.       for (uint i=0 ; i < table->keys ; i++)
  185.       {
  186. table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]=
  187.   *(rec_per_key++);
  188.       }
  189.     }
  190.     ref_length=4;
  191.   }
  192.   if (flag & HA_STATUS_ERRKEY)
  193.   {
  194.     errkey  = info.errkey;
  195.     ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
  196.   }
  197.   if (flag & HA_STATUS_TIME)
  198.     update_time = info.update_time;
  199. }
  200. int ha_isam::extra(enum ha_extra_function operation)
  201. {
  202.   if ((specialflag & SPECIAL_SAFE_MODE || test_flags & TEST_NO_EXTRA) &&
  203.       (operation == HA_EXTRA_WRITE_CACHE ||
  204.        operation == HA_EXTRA_KEYREAD))
  205.     return 0;
  206.   return nisam_extra(file,operation);
  207. }
  208. int ha_isam::external_lock(THD *thd, int lock_type)
  209. {
  210.   if (!table->tmp_table)
  211.     return nisam_lock_database(file,lock_type);
  212.   return 0;
  213. }
  214. THR_LOCK_DATA **ha_isam::store_lock(THD *thd,
  215.     THR_LOCK_DATA **to,
  216.     enum thr_lock_type lock_type)
  217. {
  218.   if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
  219.     file->lock.type=lock_type;
  220.   *to++= &file->lock;
  221.   return to;
  222. }
  223. int ha_isam::create(const char *name, register TABLE *form,
  224.     HA_CREATE_INFO *create_info)
  225. {
  226.   uint options=form->db_options_in_use;
  227.   int error;
  228.   uint i,j,recpos,minpos,fieldpos,temp_length,length;
  229.   enum ha_base_keytype type;
  230.   char buff[FN_REFLEN];
  231.   KEY *pos;
  232.   N_KEYDEF keydef[MAX_KEY];
  233.   N_RECINFO *recinfo,*recinfo_pos;
  234.   DBUG_ENTER("ha_isam::create");
  235.   type=HA_KEYTYPE_BINARY; // Keep compiler happy
  236.   if (!(recinfo= (N_RECINFO*) my_malloc((form->fields*2+2)*sizeof(N_RECINFO),
  237. MYF(MY_WME))))
  238.     DBUG_RETURN(HA_ERR_OUT_OF_MEM);
  239.   pos=form->key_info;
  240.   for (i=0; i < form->keys ; i++, pos++)
  241.   {
  242.     keydef[i].base.flag= (pos->flags & HA_NOSAME);
  243.     for (j=0 ; (int7) j < pos->key_parts ; j++)
  244.     {
  245.       keydef[i].seg[j].base.flag=pos->key_part[j].key_part_flag;
  246.       Field *field=pos->key_part[j].field;
  247.       type=field->key_type();
  248.       if ((options & HA_OPTION_PACK_KEYS ||
  249.    (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
  250.   HA_SPACE_PACK_USED))) &&
  251.   pos->key_part[j].length > 8 &&
  252.   (type == HA_KEYTYPE_TEXT ||
  253.    type == HA_KEYTYPE_NUM ||
  254.    (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
  255.       {
  256. if (j == 0)
  257.   keydef[i].base.flag|=HA_PACK_KEY;
  258. if (!(field->flags & ZEROFILL_FLAG) &&
  259.     (field->type() == FIELD_TYPE_STRING ||
  260.      field->type() == FIELD_TYPE_VAR_STRING ||
  261.      ((int) (pos->key_part[j].length - field->decimals()))
  262.      >= 4))
  263.   keydef[i].seg[j].base.flag|=HA_SPACE_PACK;
  264.       }
  265.       keydef[i].seg[j].base.type=(int) type;
  266.       keydef[i].seg[j].base.start=  pos->key_part[j].offset;
  267.       keydef[i].seg[j].base.length= pos->key_part[j].length;
  268.     }
  269.     keydef[i].seg[j].base.type=(int) HA_KEYTYPE_END; /* End of key-parts */
  270.   }
  271.   recpos=0; recinfo_pos=recinfo;
  272.   while (recpos < (uint) form->reclength)
  273.   {
  274.     Field **field,*found=0;
  275.     minpos=form->reclength; length=0;
  276.     for (field=form->field ; *field ; field++)
  277.     {
  278.       if ((fieldpos=(*field)->offset()) >= recpos &&
  279.   fieldpos <= minpos)
  280.       {
  281. /* skip null fields */
  282. if (!(temp_length= (*field)->pack_length()))
  283.   continue; /* Skip null-fields */
  284. if (! found || fieldpos < minpos ||
  285.     (fieldpos == minpos && temp_length < length))
  286. {
  287.   minpos=fieldpos; found= *field; length=temp_length;
  288. }
  289.       }
  290.     }
  291.     DBUG_PRINT("loop",("found: %lx  recpos: %d  minpos: %d  length: %d",
  292.        found,recpos,minpos,length));
  293.     if (recpos != minpos)
  294.     { // Reserved space (Null bits?)
  295.       recinfo_pos->base.type=(int) FIELD_NORMAL;
  296.       recinfo_pos++->base.length= (uint16) (minpos-recpos);
  297.     }
  298.     if (! found)
  299.       break;
  300.     if (found->flags & BLOB_FLAG)
  301.     {
  302.       /* ISAM can only handle blob pointers of sizeof(char(*)) */
  303.       recinfo_pos->base.type= (int) FIELD_BLOB;
  304.       if (options & HA_OPTION_LONG_BLOB_PTR)
  305. length= length-portable_sizeof_char_ptr+sizeof(char*);
  306.     }
  307.     else if (!(options & HA_OPTION_PACK_RECORD))
  308.       recinfo_pos->base.type= (int) FIELD_NORMAL;
  309.     else if (found->zero_pack())
  310.       recinfo_pos->base.type= (int) FIELD_SKIP_ZERO;
  311.     else
  312.       recinfo_pos->base.type= (int) ((length <= 3 ||
  313.       (found->flags & ZEROFILL_FLAG)) ?
  314.      FIELD_NORMAL :
  315.      found->type() == FIELD_TYPE_STRING ||
  316.      found->type() == FIELD_TYPE_VAR_STRING ?
  317.      FIELD_SKIP_ENDSPACE :
  318.      FIELD_SKIP_PRESPACE);
  319.     recinfo_pos++ ->base.length=(uint16) length;
  320.     recpos=minpos+length;
  321.     DBUG_PRINT("loop",("length: %d  type: %d",
  322.        recinfo_pos[-1].base.length,recinfo_pos[-1].base.type));
  323.     if ((found->flags & BLOB_FLAG) && (options & HA_OPTION_LONG_BLOB_PTR) &&
  324. sizeof(char*) != portable_sizeof_char_ptr)
  325.     { // Not used space
  326.       recinfo_pos->base.type=(int) FIELD_ZERO;
  327.       recinfo_pos++->base.length=
  328. (uint16) (portable_sizeof_char_ptr-sizeof(char*));
  329.       recpos+= (portable_sizeof_char_ptr-sizeof(char*));
  330.     }
  331.   }
  332.   recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */
  333.   error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef,
  334.      recinfo,(ulong) form->max_rows, (ulong) form->min_rows,
  335.      0, 0, 0L);
  336.   my_free((gptr) recinfo,MYF(0));
  337.   DBUG_RETURN(error);
  338. }
  339. static key_range no_range= { (byte*) 0, 0, HA_READ_KEY_EXACT };
  340. ha_rows ha_isam::records_in_range(uint inx, key_range *min_key,
  341.                                   key_range *max_key)
  342. {
  343.   /* ISAM checks if 'key' pointer <> 0 to know if there is no range */
  344.   if (!min_key)
  345.     min_key= &no_range;
  346.   if (!max_key)
  347.     max_key= &no_range;
  348.   return (ha_rows) nisam_records_in_range(file,
  349.                                           (int) inx,
  350.                                           min_key->key, min_key->length,
  351.                                           min_key->flag,
  352.                                           max_key->key, max_key->length,
  353.                                           max_key->flag);
  354. }
  355. #endif /* HAVE_ISAM */