18 #define MYSQL_SERVER 1 
   20 #include "probes_mysql.h" 
   22 #include "sql_plugin.h" 
   25 #include <myisampack.h> 
   26 #include "ha_myisam.h" 
   28 #include "myisamdef.h" 
   30 #include "sql_table.h"                           
   31 #include "sql_class.h"                           
   38 ulonglong myisam_recover_options;
 
   39 static ulong opt_myisam_block_size;
 
   42 static bool myisam_is_supported_system_table(
const char *db,
 
   44                                       bool is_sql_layer_system_table);
 
   47 const char *myisam_recover_names[] =
 
   48 { 
"DEFAULT", 
"BACKUP", 
"FORCE", 
"QUICK", 
"OFF", NullS};
 
   49 TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,
"",
 
   50                                  myisam_recover_names, NULL};
 
   52 const char *myisam_stats_method_names[] = {
"nulls_unequal", 
"nulls_equal",
 
   53                                            "nulls_ignored", NullS};
 
   54 TYPELIB myisam_stats_method_typelib= {
 
   55   array_elements(myisam_stats_method_names) - 1, 
"",
 
   56   myisam_stats_method_names, NULL};
 
   58 static MYSQL_SYSVAR_ULONG(block_size, opt_myisam_block_size,
 
   59   PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_RQCMDARG,
 
   60   "Block size to be used for MyISAM index pages", NULL, NULL,
 
   61   MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
 
   62   MI_MIN_KEY_BLOCK_LENGTH);
 
   64 static MYSQL_SYSVAR_ULONG(data_pointer_size, myisam_data_pointer_size,
 
   65   PLUGIN_VAR_RQCMDARG, 
"Default pointer size to be used for MyISAM tables",
 
   66   NULL, NULL, 6, 2, 7, 1);
 
   68 #define MB (1024*1024) 
   69 static MYSQL_SYSVAR_ULONGLONG(max_sort_file_size, myisam_max_temp_length,
 
   70   PLUGIN_VAR_RQCMDARG, 
"Don't use the fast sort index method to created " 
   71   "index if the temporary file would get bigger than this", NULL, NULL,
 
   72   LONG_MAX/MB*MB, 0, MAX_FILE_SIZE, MB);
 
   74 static MYSQL_SYSVAR_SET(recover_options, myisam_recover_options,
 
   75   PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_READONLY,
 
   76   "Syntax: myisam-recover-options[=option[,option...]], where option can be " 
   77   "DEFAULT, BACKUP, FORCE, QUICK, or OFF",
 
   78   NULL, NULL, 0, &myisam_recover_typelib);
 
   80 static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG,
 
   81   "If larger than 1, when repairing a MyISAM table all indexes will be " 
   82   "created in parallel, with one thread per index. The value of 1 " 
   83   "disables parallel repair", NULL, NULL,
 
   86 static MYSQL_THDVAR_ULONGLONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG,
 
   87   "The buffer that is allocated when sorting the index when doing " 
   88   "a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE", NULL, NULL,
 
   89   8192 * 1024, (
long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), SIZE_T_MAX, 1);
 
   91 static MYSQL_SYSVAR_BOOL(use_mmap, opt_myisam_use_mmap, PLUGIN_VAR_NOCMDARG,
 
   92   "Use memory mapping for reading and writing MyISAM tables", NULL, NULL, FALSE);
 
   94 static MYSQL_SYSVAR_ULONGLONG(mmap_size, myisam_mmap_size,
 
   95   PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY, 
"Restricts the total memory " 
   96   "used for memory mapping of MySQL tables", NULL, NULL,
 
   97   SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 1);
 
   99 static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG,
 
  100   "Specifies how MyISAM index statistics collection code should " 
  101   "treat NULLs. Possible values of name are NULLS_UNEQUAL (default " 
  102   "behavior for 4.1 and later), NULLS_EQUAL (emulate 4.0 behavior), " 
  103   "and NULLS_IGNORED", NULL, NULL,
 
  104   MI_STATS_METHOD_NULLS_NOT_EQUAL, &myisam_stats_method_typelib);
 
  114 static void debug_wait_for_kill(
const char *info)
 
  116   DBUG_ENTER(
"debug_wait_for_kill");
 
  117   const char *prev_info;
 
  120   prev_info= thd_proc_info(thd, info);
 
  123   DBUG_PRINT(
"info", (
"Exit debug_wait_for_kill"));
 
  124   thd_proc_info(thd, prev_info);
 
  137   return new (mem_root) 
ha_myisam(hton, table);
 
  142 static void mi_check_print_msg(
MI_CHECK *param, 
const char* msg_type,
 
  143                                const char *
fmt, va_list args)
 
  145   THD* thd = (THD*)param->thd;
 
  147   size_t length, msg_length;
 
  148   char msgbuf[MI_MAX_MSG_BUF];
 
  149   char name[NAME_LEN*2+2];
 
  151   msg_length= my_vsnprintf(msgbuf, 
sizeof(msgbuf), 
fmt, args);
 
  152   msgbuf[
sizeof(msgbuf) - 1] = 0; 
 
  154   DBUG_PRINT(msg_type,(
"message: %s",msgbuf));
 
  158     sql_print_error(
"%s", msgbuf);
 
  162   if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
 
  165     my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
 
  168   length=(uint) (strxmov(
name, param->db_name,
".",param->table_name,NullS) -
 
  178   if (param->need_print_msg_lock)
 
  181   protocol->prepare_for_resend();
 
  182   protocol->store(
name, length, system_charset_info);
 
  183   protocol->store(param->op_name, system_charset_info);
 
  184   protocol->store(msg_type, system_charset_info);
 
  185   protocol->store(msgbuf, msg_length, system_charset_info);
 
  186   if (protocol->write())
 
  187     sql_print_error(
"Failed on my_net_write, writing to stderr instead: %s\n",
 
  190   if (param->need_print_msg_lock)
 
  224   uint 
i, j, recpos, minpos, fieldpos, temp_length, length;
 
  225   enum ha_base_keytype 
type= HA_KEYTYPE_BINARY;
 
  232   uint options= share->db_options_in_use;
 
  233   DBUG_ENTER(
"table2myisam");
 
  234   if (!(my_multi_malloc(MYF(MY_WME),
 
  235           recinfo_out, (share->fields * 2 + 2) * 
sizeof(
MI_COLUMNDEF),
 
  236           keydef_out, share->keys * 
sizeof(
MI_KEYDEF),
 
  238           (share->key_parts + share->keys) * 
sizeof(
HA_KEYSEG),
 
  240     DBUG_RETURN(HA_ERR_OUT_OF_MEM); 
 
  242   recinfo= *recinfo_out;
 
  243   pos= table_arg->key_info;
 
  244   for (i= 0; i < share->keys; i++, pos++)
 
  246     keydef[
i].flag= ((uint16) pos->
flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
 
  247     keydef[
i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
 
  248       (pos->
flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
 
  250     keydef[i].block_length= pos->block_size;
 
  251     keydef[i].seg= keyseg;
 
  255       Field *field= pos->key_part[j].field;
 
  256       type= field->key_type();
 
  257       keydef[
i].seg[j].flag= pos->key_part[j].key_part_flag;
 
  259       if (options & HA_OPTION_PACK_KEYS ||
 
  260           (pos->
flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
 
  261                          HA_SPACE_PACK_USED)))
 
  263         if (pos->key_part[j].length > 8 &&
 
  264             (type == HA_KEYTYPE_TEXT ||
 
  265              type == HA_KEYTYPE_NUM ||
 
  266              (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
 
  270             keydef[
i].flag|= HA_PACK_KEY;
 
  271           if (!(field->flags & ZEROFILL_FLAG) &&
 
  272               (field->type() == MYSQL_TYPE_STRING ||
 
  273                field->type() == MYSQL_TYPE_VAR_STRING ||
 
  274                ((int) (pos->key_part[j].length - field->decimals())) >= 4))
 
  275             keydef[
i].seg[j].flag|= HA_SPACE_PACK;
 
  277         else if (j == 0 && (!(pos->
flags & HA_NOSAME) || pos->
key_length > 16))
 
  278           keydef[
i].flag|= HA_BINARY_PACK_KEY;
 
  280       keydef[
i].seg[j].type= (int) type;
 
  281       keydef[
i].seg[j].start= pos->key_part[j].offset;
 
  282       keydef[
i].seg[j].length= pos->key_part[j].length;
 
  283       keydef[
i].seg[j].bit_start= keydef[
i].seg[j].bit_end=
 
  284         keydef[
i].seg[j].bit_length= 0;
 
  285       keydef[
i].seg[j].bit_pos= 0;
 
  286       keydef[
i].seg[j].language= field->charset_for_protocol()->number;
 
  290         keydef[
i].seg[j].null_bit= field->null_bit;
 
  291         keydef[
i].seg[j].null_pos= field->null_offset();
 
  295         keydef[
i].seg[j].null_bit= 0;
 
  296         keydef[
i].seg[j].null_pos= 0;
 
  298       if (field->type() == MYSQL_TYPE_BLOB ||
 
  299           field->type() == MYSQL_TYPE_GEOMETRY)
 
  301         keydef[
i].seg[j].flag|= HA_BLOB_PART;
 
  303         keydef[
i].seg[j].bit_start= (uint) (field->pack_length() -
 
  304                                             portable_sizeof_char_ptr);
 
  306       else if (field->type() == MYSQL_TYPE_BIT)
 
  308         keydef[
i].seg[j].bit_length= ((
Field_bit *) field)->bit_len;
 
  309         keydef[
i].seg[j].bit_start= ((
Field_bit *) field)->bit_ofs;
 
  310         keydef[
i].seg[j].bit_pos= (uint) (((
Field_bit *) field)->bit_ptr -
 
  311                                           (uchar*) table_arg->record[0]);
 
  316   if (table_arg->found_next_number_field)
 
  317     keydef[share->next_number_index].flag|= HA_AUTO_KEY;
 
  318   record= table_arg->record[0];
 
  320   recinfo_pos= recinfo;
 
  321   while (recpos < (uint) share->reclength)
 
  323     Field **field, *found= 0;
 
  324     minpos= share->reclength;
 
  327     for (field= table_arg->field; *field; field++)
 
  329       if ((fieldpos= (*field)->offset(record)) >= recpos &&
 
  333         if (!(temp_length= (*field)->pack_length_in_rec()))
 
  335         if (! found || fieldpos < minpos ||
 
  336             (fieldpos == minpos && temp_length < length))
 
  344     DBUG_PRINT(
"loop", (
"found: 0x%lx  recpos: %d  minpos: %d  length: %d",
 
  345                         (
long) found, recpos, minpos, length));
 
  346     if (recpos != minpos)
 
  348       memset(recinfo_pos, 0, 
sizeof(*recinfo_pos));
 
  349       recinfo_pos->type= (int) FIELD_NORMAL;
 
  350       recinfo_pos++->length= (uint16) (minpos - recpos);
 
  355     if (found->flags & BLOB_FLAG)
 
  356       recinfo_pos->type= (int) FIELD_BLOB;
 
  357     else if (found->type() == MYSQL_TYPE_VARCHAR)
 
  358       recinfo_pos->type= FIELD_VARCHAR;
 
  359     else if (!(options & HA_OPTION_PACK_RECORD))
 
  360       recinfo_pos->type= (
int) FIELD_NORMAL;
 
  361     else if (found->zero_pack())
 
  362       recinfo_pos->type= (
int) FIELD_SKIP_ZERO;
 
  364       recinfo_pos->type= (int) ((length <= 3 ||
 
  365                                  (found->flags & ZEROFILL_FLAG)) ?
 
  367                                   found->type() == MYSQL_TYPE_STRING ||
 
  368                                   found->type() == MYSQL_TYPE_VAR_STRING ?
 
  369                                   FIELD_SKIP_ENDSPACE :
 
  370                                   FIELD_SKIP_PRESPACE);
 
  373       recinfo_pos->null_bit= found->null_bit;
 
  374       recinfo_pos->null_pos= found->null_offset();
 
  378       recinfo_pos->null_bit= 0;
 
  379       recinfo_pos->null_pos= 0;
 
  381     (recinfo_pos++)->length= (uint16) length;
 
  382     recpos= minpos + length;
 
  383     DBUG_PRINT(
"loop", (
"length: %d  type: %d",
 
  384                         recinfo_pos[-1].length,recinfo_pos[-1].type));
 
  386   *records_out= (uint) (recinfo_pos - recinfo);
 
  437                      uint t1_keys, uint t1_recs,
 
  439                      uint t2_keys, uint t2_recs, 
bool strict, 
TABLE *table_arg)
 
  442   DBUG_ENTER(
"check_definition");
 
  443   my_bool mysql_40_compat= table_arg && table_arg->s->frm_version < FRM_VER_TRUE_VARCHAR;
 
  444   if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
 
  446     DBUG_PRINT(
"error", (
"Number of keys differs: t1_keys=%u, t2_keys=%u",
 
  450   if (t1_recs != t2_recs)
 
  452     DBUG_PRINT(
"error", (
"Number of recs differs: t1_recs=%u, t2_recs=%u",
 
  456   for (i= 0; i < t1_keys; i++)
 
  460     if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
 
  462     else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
 
  463              t2_keyinfo[i].flag & HA_FULLTEXT)
 
  465        DBUG_PRINT(
"error", (
"Key %d has different definition", i));
 
  466        DBUG_PRINT(
"error", (
"t1_fulltext= %d, t2_fulltext=%d",
 
  467                             test(t1_keyinfo[i].flag & HA_FULLTEXT),
 
  468                             test(t2_keyinfo[i].flag & HA_FULLTEXT)));
 
  471     if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
 
  473     else if (t1_keyinfo[i].flag & HA_SPATIAL ||
 
  474              t2_keyinfo[i].flag & HA_SPATIAL)
 
  476        DBUG_PRINT(
"error", (
"Key %d has different definition", i));
 
  477        DBUG_PRINT(
"error", (
"t1_spatial= %d, t2_spatial=%d",
 
  478                             test(t1_keyinfo[i].flag & HA_SPATIAL),
 
  479                             test(t2_keyinfo[i].flag & HA_SPATIAL)));
 
  482     if ((!mysql_40_compat &&
 
  483         t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg) ||
 
  484         t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs)
 
  486       DBUG_PRINT(
"error", (
"Key %d has different definition", i));
 
  487       DBUG_PRINT(
"error", (
"t1_keysegs=%d, t1_key_alg=%d",
 
  488                            t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
 
  489       DBUG_PRINT(
"error", (
"t2_keysegs=%d, t2_key_alg=%d",
 
  490                            t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
 
  493     for (j=  t1_keyinfo[i].keysegs; j--;)
 
  495       uint8 t1_keysegs_j__type= t1_keysegs[j].type;
 
  503       if ((t1_keysegs[j].flag & HA_BLOB_PART) &&
 
  504           (t2_keysegs[j].flag & HA_BLOB_PART))
 
  506         if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
 
  507             (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
 
  508           t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; 
 
  509         else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
 
  510                  (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
 
  511           t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; 
 
  514       if ((!mysql_40_compat &&
 
  515           t1_keysegs[j].language != t2_keysegs[j].language) ||
 
  516           t1_keysegs_j__type != t2_keysegs[j].type ||
 
  517           t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
 
  518           t1_keysegs[j].length != t2_keysegs[j].length ||
 
  519           t1_keysegs[j].start != t2_keysegs[j].start)
 
  521         DBUG_PRINT(
"error", (
"Key segment %d (key %d) has different " 
  522                              "definition", j, i));
 
  523         DBUG_PRINT(
"error", (
"t1_type=%d, t1_language=%d, t1_null_bit=%d, " 
  525                              t1_keysegs[j].type, t1_keysegs[j].language,
 
  526                              t1_keysegs[j].null_bit, t1_keysegs[j].length));
 
  527         DBUG_PRINT(
"error", (
"t2_type=%d, t2_language=%d, t2_null_bit=%d, " 
  529                              t2_keysegs[j].type, t2_keysegs[j].language,
 
  530                              t2_keysegs[j].null_bit, t2_keysegs[j].length));
 
  536   for (i= 0; i < t1_recs; i++)
 
  544     if ((t1_rec->type != t2_rec->type &&
 
  545          !(t1_rec->type == (
int) FIELD_SKIP_ZERO &&
 
  546            t1_rec->length == 1 &&
 
  547            t2_rec->type == (
int) FIELD_NORMAL)) ||
 
  548         t1_rec->length != t2_rec->length ||
 
  549         t1_rec->null_bit != t2_rec->null_bit)
 
  551       DBUG_PRINT(
"error", (
"Field %d has different definition", i));
 
  552       DBUG_PRINT(
"error", (
"t1_type=%d, t1_length=%d, t1_null_bit=%d",
 
  553                            t1_rec->type, t1_rec->length, t1_rec->null_bit));
 
  554       DBUG_PRINT(
"error", (
"t2_type=%d, t2_length=%d, t2_null_bit=%d",
 
  555                            t2_rec->type, t2_rec->length, t2_rec->null_bit));
 
  565 volatile int *killed_ptr(
MI_CHECK *param)
 
  568   return (
int*) &(((THD *)(param->thd))->killed);
 
  571 void mi_check_print_error(
MI_CHECK *param, 
const char *fmt,...)
 
  573   param->error_printed|=1;
 
  574   param->out_flag|= O_DATA_LOST;
 
  577   mi_check_print_msg(param, 
"error", fmt, args);
 
  581 void mi_check_print_info(
MI_CHECK *param, 
const char *fmt,...)
 
  585   mi_check_print_msg(param, 
"info", fmt, args);
 
  589 void mi_check_print_warning(
MI_CHECK *param, 
const char *fmt,...)
 
  591   param->warning_printed=1;
 
  592   param->out_flag|= O_DATA_LOST;
 
  595   mi_check_print_msg(param, 
"warning", fmt, args);
 
  616                         const char *sfile, uint sline)
 
  622   if ((cur_thd= (THD*) file->in_use.data))
 
  623     sql_print_error(
"Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
 
  626     sql_print_error(
"Got an error from unknown thread, %s:%d", sfile, sline);
 
  628     sql_print_error(
"%s", message);
 
  629   for (element= file->s->in_use; element; element= list_rest(element))
 
  631     THD *thd= (THD*) element->data;
 
  632     sql_print_error(
"%s", thd ? thd_security_context(thd, buf, 
sizeof(buf), 0)
 
  633                               : 
"Unknown thread accessing table");
 
  642   :
handler(hton, table_arg), file(0),
 
  643   int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
 
  644                   HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
 
  645                   HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
 
  646                   HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
 
  647                   HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
 
  648                   HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_REPAIR),
 
  649    can_enable_indexes(1)
 
  657     new_handler->file->state= file->state;
 
  662 static const char *ha_myisam_exts[] = {
 
  670   return ha_myisam_exts;
 
  693 static bool myisam_is_supported_system_table(
const char *db,
 
  695                                       bool is_sql_layer_system_table)
 
  698   if (is_sql_layer_system_table)
 
  710 const char *ha_myisam::index_type(uint key_number)
 
  712   return ((table->key_info[key_number].
flags & HA_FULLTEXT) ? 
 
  714           (table->key_info[key_number].
flags & HA_SPATIAL) ?
 
  716           (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
 
  723 int ha_myisam::open(
const char *name, 
int mode, uint test_if_locked)
 
  745   if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_myisam_use_mmap)
 
  746     test_if_locked|= HA_OPEN_MMAP;
 
  748   if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
 
  749     return (my_errno ? my_errno : -1);
 
  750   if (!table->s->tmp_table) 
 
  752     if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
  755       DBUG_PRINT(
"error", (
"Failed to convert TABLE object to MyISAM " 
  756                            "key and column definition"));
 
  760     if (check_definition(keyinfo, recinfo, table->s->keys, recs,
 
  761                          file->s->keyinfo, file->s->rec,
 
  762                          file->s->base.keys, file->s->base.fields,
 
  766       my_errno= HA_ERR_CRASHED;
 
  772   if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
 
  773     (void) mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
 
  775   info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
  776   if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
 
  777     (void) mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
 
  778   if (!table->s->db_record_offset)
 
  779     int_table_flags|=HA_REC_NOT_IN_SEQ;
 
  780   if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
  781     int_table_flags|=HA_HAS_CHECKSUM;
 
  783   for (i= 0; i < table->s->keys; i++)
 
  786     if (table->key_info[i].
flags & HA_USES_PARSER)
 
  787       file->s->keyinfo[
i].parser=
 
  789     table->key_info[
i].block_size= file->s->keyinfo[
i].block_length;
 
  805 int ha_myisam::close(
void)
 
  809   return mi_close(tmp);
 
  812 int ha_myisam::write_row(uchar *buf)
 
  814   ha_statistic_increment(&SSV::ha_write_count);
 
  820   if (table->next_number_field && buf == table->record[0])
 
  823     if ((error= update_auto_increment()))
 
  826   return mi_write(file,buf);
 
  831   if (!file) 
return HA_ADMIN_INTERNAL_ERROR;
 
  835   const char *old_proc_info=thd->proc_info;
 
  837   thd_proc_info(thd, 
"Checking table");
 
  838   myisamchk_init(¶m);
 
  840   param.op_name =   
"check";
 
  841   param.db_name=    table->s->db.str;
 
  842   param.table_name= table->alias;
 
  843   param.testflag = check_opt->flags | T_CHECK | T_SILENT;
 
  844   param.stats_method= (enum_mi_stats_method)THDVAR(thd, stats_method);
 
  846   if (!(table->db_stat & HA_READ_ONLY))
 
  847     param.testflag|= T_STATISTICS;
 
  848   param.using_global_keycache = 1;
 
  850   if (!mi_is_crashed(file) &&
 
  851       (((param.testflag & T_CHECK_ONLY_CHANGED) &&
 
  852         !(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
 
  853                                   STATE_CRASHED_ON_REPAIR)) &&
 
  854         share->state.open_count == 0) ||
 
  855        ((param.testflag & T_FAST) && (share->state.open_count ==
 
  856                                       (uint) (share->global_changed ? 1 : 0)))))
 
  857     return HA_ADMIN_ALREADY_DONE;
 
  859   error = chk_status(¶m, file);             
 
  860   error = chk_size(¶m, file);
 
  862     error |= chk_del(¶m, file, param.testflag);
 
  864     error = chk_key(¶m, file);
 
  867     if ((!(param.testflag & T_QUICK) &&
 
  869            (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
 
  870           (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
 
  873       uint old_testflag=param.testflag;
 
  874       param.testflag|=T_MEDIUM;
 
  875       if (!(error= init_io_cache(¶m.read_cache, file->dfile,
 
  876                                  my_default_record_cache_size, READ_CACHE,
 
  877                                  share->pack.header_length, 1, MYF(MY_WME))))
 
  879         error= chk_data_link(¶m, file, param.testflag & T_EXTEND);
 
  880         end_io_cache(&(param.read_cache));
 
  882       param.testflag= old_testflag;
 
  887     if ((share->state.changed & (STATE_CHANGED |
 
  888                                  STATE_CRASHED_ON_REPAIR |
 
  889                                  STATE_CRASHED | STATE_NOT_ANALYZED)) ||
 
  890         (param.testflag & T_STATISTICS) ||
 
  893       file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
  895       share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
 
  896                                STATE_CRASHED_ON_REPAIR);
 
  897       if (!(table->db_stat & HA_READ_ONLY))
 
  898         error=update_state_info(¶m,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
 
  901       info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 
  905   else if (!mi_is_crashed(file) && !thd->killed)
 
  907     mi_mark_crashed(file);
 
  908     file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
  911   thd_proc_info(thd, old_proc_info);
 
  912   return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
  922 int ha_myisam::analyze(THD *thd, 
HA_CHECK_OPT* check_opt)
 
  928   myisamchk_init(¶m);
 
  930   param.op_name=    
"analyze";
 
  931   param.db_name=    table->s->db.str;
 
  932   param.table_name= table->alias;
 
  933   param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
 
  934                    T_DONT_CHECK_CHECKSUM);
 
  935   param.using_global_keycache = 1;
 
  936   param.stats_method= (enum_mi_stats_method)THDVAR(thd, stats_method);
 
  938   if (!(share->state.changed & STATE_NOT_ANALYZED))
 
  939     return HA_ADMIN_ALREADY_DONE;
 
  941   error = chk_key(¶m, file);
 
  945     error=update_state_info(¶m,file,UPDATE_STAT);
 
  948   else if (!mi_is_crashed(file) && !thd->killed)
 
  949     mi_mark_crashed(file);
 
  950   return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
  958   ha_rows start_records;
 
  960   if (!file) 
return HA_ADMIN_INTERNAL_ERROR;
 
  962   myisamchk_init(¶m);
 
  964   param.op_name=  
"repair";
 
  965   param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
 
  966                    T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
 
  967                    (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
 
  968   param.sort_buffer_length=  THDVAR(thd, sort_buffer_size);
 
  969   start_records=file->state->records;
 
  970   while ((error=repair(thd,param,0)) && param.retry_repair)
 
  972     param.retry_repair=0;
 
  973     if (test_all_bits(param.testflag,
 
  974                       (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
 
  976       param.testflag&= ~T_RETRY_WITHOUT_QUICK;
 
  977       sql_print_information(
"Retrying repair of: '%s' without quick",
 
  981     param.testflag&= ~T_QUICK;
 
  982     if ((param.testflag & T_REP_BY_SORT))
 
  984       param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
 
  985       sql_print_information(
"Retrying repair of: '%s' with keycache",
 
  991   if (!error && start_records != file->state->records &&
 
  992       !(check_opt->flags & T_VERY_SILENT))
 
  994     char llbuff[22],llbuff2[22];
 
  995     sql_print_information(
"Found %s of %s rows when repairing '%s'",
 
  996                           llstr(file->state->records, llbuff),
 
  997                           llstr(start_records, llbuff2),
 
 1003 int ha_myisam::optimize(THD* thd, 
HA_CHECK_OPT *check_opt)
 
 1006   if (!file) 
return HA_ADMIN_INTERNAL_ERROR;
 
 1009   myisamchk_init(¶m);
 
 1011   param.op_name= 
"optimize";
 
 1012   param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
 
 1013                    T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
 
 1014   param.sort_buffer_length=  THDVAR(thd, sort_buffer_size);
 
 1015   if ((error= repair(thd,param,1)) && param.retry_repair)
 
 1017     sql_print_warning(
"Warning: Optimize table got errno %d on %s.%s, retrying",
 
 1018                       my_errno, param.db_name, param.table_name);
 
 1019     param.testflag&= ~T_REP_BY_SORT;
 
 1020     error= repair(thd,param,1);
 
 1026 int ha_myisam::repair(THD *thd, 
MI_CHECK ¶m, 
bool do_optimize)
 
 1029   uint local_testflag=param.testflag;
 
 1030   bool optimize_done= !do_optimize, statistics_done=0;
 
 1031   bool has_old_locks= thd->locked_tables_mode || file->lock_type != F_UNLCK;
 
 1032   const char *old_proc_info=thd->proc_info;
 
 1033   char fixed_name[FN_REFLEN];
 
 1035   ha_rows rows= file->state->records;
 
 1036   DBUG_ENTER(
"ha_myisam::repair");
 
 1038   param.db_name=    table->s->db.str;
 
 1039   param.table_name= table->alias;
 
 1040   param.tmpfile_createflag = O_RDWR | O_TRUNC;
 
 1041   param.using_global_keycache = 1;
 
 1043   param.tmpdir= &mysql_tmpdir_list;
 
 1045   strmov(fixed_name,file->filename);
 
 1051   if (!has_old_locks &&
 
 1052       mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
 
 1054     char errbuf[MYSYS_STRERROR_SIZE];
 
 1055     mi_check_print_error(¶m, ER(ER_CANT_LOCK), my_errno,
 
 1056                          my_strerror(errbuf, 
sizeof(errbuf), my_errno));
 
 1057     DBUG_RETURN(HA_ADMIN_FAILED);
 
 1061       ((file->state->del || share->state.split != file->state->records) &&
 
 1062        (!(param.testflag & T_QUICK) ||
 
 1063         !(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
 
 1065     ulonglong 
key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
 
 1066                         mi_get_mask_all_keys_active(share->base.keys) :
 
 1067                         share->state.key_map);
 
 1068     uint testflag=param.testflag;
 
 1070     bool remap= 
test(share->file_map);
 
 1079       mi_munmap_file(file);
 
 1081     if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
 
 1082         (local_testflag & T_REP_BY_SORT))
 
 1084       local_testflag|= T_STATISTICS;
 
 1085       param.testflag|= T_STATISTICS;            
 
 1087       if (THDVAR(thd, repair_threads)>1)
 
 1091         my_snprintf(buf, 40, 
"Repair with %d threads", my_count_bits(key_map));
 
 1092         thd_proc_info(thd, buf);
 
 1093         error = mi_repair_parallel(¶m, file, fixed_name,
 
 1094             param.testflag & T_QUICK);
 
 1095         thd_proc_info(thd, 
"Repair done"); 
 
 1100         thd_proc_info(thd, 
"Repair by sorting");
 
 1101         error = mi_repair_by_sort(¶m, file, fixed_name,
 
 1102             param.testflag & T_QUICK);
 
 1107       thd_proc_info(thd, 
"Repair with keycache");
 
 1108       param.testflag &= ~T_REP_BY_SORT;
 
 1109       error=  mi_repair(¶m, file, fixed_name,
 
 1110                         param.testflag & T_QUICK);
 
 1114       mi_dynmap_file(file, file->state->data_file_length);
 
 1116     param.testflag=testflag;
 
 1121     if ((local_testflag & T_SORT_INDEX) &&
 
 1122         (share->state.changed & STATE_NOT_SORTED_PAGES))
 
 1125       thd_proc_info(thd, 
"Sorting index");
 
 1126       error=mi_sort_index(¶m,file,fixed_name);
 
 1128     if (!statistics_done && (local_testflag & T_STATISTICS))
 
 1130       if (share->state.changed & STATE_NOT_ANALYZED)
 
 1133         thd_proc_info(thd, 
"Analyzing");
 
 1134         error = chk_key(¶m, file);
 
 1137         local_testflag&= ~T_STATISTICS;         
 
 1140   thd_proc_info(thd, 
"Saving state");
 
 1143     if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
 
 1145       share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
 
 1146                                STATE_CRASHED_ON_REPAIR);
 
 1147       file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
 1153     if (file->state != &file->s->state.state)
 
 1154       file->s->state.state = *file->state;
 
 1155     if (file->s->base.auto_key)
 
 1156       update_auto_increment_key(¶m, file, 1);
 
 1158       error = update_state_info(¶m, file,
 
 1159                                 UPDATE_TIME | UPDATE_OPEN_COUNT |
 
 1161                                  T_STATISTICS ? UPDATE_STAT : 0));
 
 1162     info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 
 1164     if (rows != file->state->records && ! (param.testflag & T_VERY_SILENT))
 
 1166       char llbuff[22],llbuff2[22];
 
 1167       mi_check_print_warning(¶m,
"Number of rows changed from %s to %s",
 
 1169                              llstr(file->state->records,llbuff2));
 
 1174     mi_mark_crashed_on_repair(file);
 
 1175     file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
 1176     update_state_info(¶m, file, 0);
 
 1178   thd_proc_info(thd, old_proc_info);
 
 1180     mi_lock_database(file,F_UNLCK);
 
 1181   DBUG_RETURN(error ? HA_ADMIN_FAILED :
 
 1182               !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
 
 1190 int ha_myisam::assign_to_keycache(THD* thd, 
HA_CHECK_OPT *check_opt)
 
 1192   KEY_CACHE *new_key_cache= check_opt->key_cache;
 
 1193   const char *errmsg= 0;
 
 1194   int error= HA_ADMIN_OK;
 
 1196   TABLE_LIST *table_list= table->pos_in_table_list;
 
 1197   DBUG_ENTER(
"ha_myisam::assign_to_keycache");
 
 1199   table->keys_in_use_for_query.clear_all();
 
 1201   if (table_list->process_index_hints(table))
 
 1202     DBUG_RETURN(HA_ADMIN_FAILED);
 
 1203   map= ~(ulonglong) 0;
 
 1204   if (!table->keys_in_use_for_query.is_clear_all())
 
 1206     map= table->keys_in_use_for_query.to_ulonglong();
 
 1208   if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
 
 1210     char buf[STRING_BUFFER_USUAL_SIZE];
 
 1211     my_snprintf(buf, 
sizeof(buf),
 
 1212                 "Failed to flush to index file (errno: %d)", error);
 
 1214     error= HA_ADMIN_CORRUPT;
 
 1217   if (error != HA_ADMIN_OK)
 
 1221     myisamchk_init(¶m);
 
 1223     param.op_name=    
"assign_to_keycache";
 
 1224     param.db_name=    table->s->db.str;
 
 1225     param.table_name= table->s->table_name.str;
 
 1227     mi_check_print_error(¶m, errmsg);
 
 1237 int ha_myisam::preload_keys(THD* thd, 
HA_CHECK_OPT *check_opt)
 
 1242   TABLE_LIST *table_list= table->pos_in_table_list;
 
 1243   my_bool ignore_leaves= table_list->ignore_leaves;
 
 1244   char buf[MYSQL_ERRMSG_SIZE];
 
 1246   DBUG_ENTER(
"ha_myisam::preload_keys");
 
 1248   table->keys_in_use_for_query.clear_all();
 
 1250   if (table_list->process_index_hints(table))
 
 1251     DBUG_RETURN(HA_ADMIN_FAILED);
 
 1253   map= ~(ulonglong) 0;
 
 1255   if (!table->keys_in_use_for_query.is_clear_all())
 
 1257     map= table->keys_in_use_for_query.to_ulonglong();
 
 1259   mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
 
 1260            (
void *) &thd->variables.preload_buff_size);
 
 1262   if ((error= mi_preload(file, map, ignore_leaves)))
 
 1265     case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
 
 1266       errmsg= 
"Indexes use different block sizes";
 
 1268     case HA_ERR_OUT_OF_MEM:
 
 1269       errmsg= 
"Failed to allocate buffer";
 
 1272       my_snprintf(buf, 
sizeof(buf),
 
 1273                   "Failed to read from index file (errno: %d)", my_errno);
 
 1276     error= HA_ADMIN_FAILED;
 
 1280   DBUG_RETURN(HA_ADMIN_OK);
 
 1285     myisamchk_init(¶m);
 
 1287     param.op_name=    
"preload_keys";
 
 1288     param.db_name=    table->s->db.str;
 
 1289     param.table_name= table->s->table_name.str;
 
 1291     mi_check_print_error(¶m, errmsg);
 
 1317 int ha_myisam::disable_indexes(uint mode)
 
 1321   if (mode == HA_KEY_SWITCH_ALL)
 
 1324     error= mi_disable_indexes(file);
 
 1326   else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
 
 1328     mi_extra(file, HA_EXTRA_NO_KEYS, 0);
 
 1329     info(HA_STATUS_CONST);                        
 
 1335     error= HA_ERR_WRONG_COMMAND;
 
 1369 int ha_myisam::enable_indexes(uint mode)
 
 1373   DBUG_EXECUTE_IF(
"wait_in_enable_indexes",
 
 1374                   debug_wait_for_kill(
"wait_in_enable_indexes"); );
 
 1376   if (mi_is_all_keys_active(file->s->state.key_map, file->s->base.keys))
 
 1382   if (mode == HA_KEY_SWITCH_ALL)
 
 1384     error= mi_enable_indexes(file);
 
 1391   else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
 
 1393     THD *thd=current_thd;
 
 1395     const char *save_proc_info=thd->proc_info;
 
 1396     thd_proc_info(thd, 
"Creating index");
 
 1397     myisamchk_init(¶m);
 
 1398     param.op_name= 
"recreating_index";
 
 1399     param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
 
 1400                      T_CREATE_MISSING_KEYS);
 
 1401     param.myf_rw&= ~MY_WAIT_IF_FULL;
 
 1402     param.sort_buffer_length=  THDVAR(thd, sort_buffer_size);
 
 1403     param.stats_method= (enum_mi_stats_method)THDVAR(thd, stats_method);
 
 1404     param.tmpdir=&mysql_tmpdir_list;
 
 1405     if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
 
 1407       sql_print_warning(
"Warning: Enabling keys got errno %d on %s.%s, retrying",
 
 1408                         my_errno, param.db_name, param.table_name);
 
 1415       if (!(param.testflag & T_RETRY_WITHOUT_QUICK))
 
 1417         param.testflag&= ~T_REP_BY_SORT;
 
 1418         error= (repair(thd,param,0) != HA_ADMIN_OK);
 
 1428     info(HA_STATUS_CONST);
 
 1429     thd_proc_info(thd, save_proc_info);
 
 1434     error= HA_ERR_WRONG_COMMAND;
 
 1455 int ha_myisam::indexes_are_disabled(
void)
 
 1458   return mi_indexes_are_disabled(file);
 
 1476 void ha_myisam::start_bulk_insert(ha_rows rows)
 
 1478   DBUG_ENTER(
"ha_myisam::start_bulk_insert");
 
 1479   THD *thd= current_thd;
 
 1480   ulong 
size= min(thd->variables.read_buff_size,
 
 1481                   (ulong) (table->s->avg_row_length*rows));
 
 1482   DBUG_PRINT(
"info",(
"start_bulk_insert: rows %lu size %lu",
 
 1483                      (ulong) rows, size));
 
 1486   if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
 
 1487     mi_extra(file, HA_EXTRA_WRITE_CACHE, (
void*) &size);
 
 1489   can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
 
 1490                                             file->s->base.keys);
 
 1499   if (file->state->records == 0 && can_enable_indexes &&
 
 1500       (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
 
 1501     mi_disable_non_unique_index(file,rows);
 
 1503     if (!file->bulk_insert &&
 
 1504         (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
 
 1506       mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
 
 1524 int ha_myisam::end_bulk_insert()
 
 1526   mi_end_bulk_insert(file);
 
 1527   int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0);
 
 1530     if (can_enable_indexes)
 
 1539       if (((err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE)) != 0) && 
 
 1540                                                   current_thd->killed)
 
 1544         file->s->state.changed&= ~(STATE_CRASHED|STATE_CRASHED_ON_REPAIR);
 
 1552 bool ha_myisam::check_and_repair(THD *thd)
 
 1557   DBUG_ENTER(
"ha_myisam::check_and_repair");
 
 1560   check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
 
 1562   if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
 
 1563     check_opt.flags|=T_QUICK;
 
 1564   sql_print_warning(
"Checking table:   '%s'",table->s->path.str);
 
 1566   const CSET_STRING query_backup= thd->query_string;
 
 1567   thd->set_query(table->s->table_name.str,
 
 1568                  (uint) table->s->table_name.length, system_charset_info);
 
 1570   if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
 
 1572     sql_print_warning(
"Recovering table: '%s'",table->s->path.str);
 
 1574       ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
 
 1575        (marked_crashed                             ? 0 : T_QUICK) |
 
 1576        (myisam_recover_options & HA_RECOVER_FORCE  ? 0 : T_SAFE_REPAIR) |
 
 1578     if (repair(thd, &check_opt))
 
 1581   thd->set_query(query_backup);
 
 1585 bool ha_myisam::is_crashed()
 const 
 1587   return (file->s->state.changed & STATE_CRASHED ||
 
 1588           (my_disable_locking && file->s->state.open_count));
 
 1591 int ha_myisam::update_row(
const uchar *old_data, uchar *new_data)
 
 1593   ha_statistic_increment(&SSV::ha_update_count);
 
 1594   return mi_update(file,old_data,new_data);
 
 1597 int ha_myisam::delete_row(
const uchar *buf)
 
 1599   ha_statistic_increment(&SSV::ha_delete_count);
 
 1600   return mi_delete(file,buf);
 
 1605 ICP_RESULT index_cond_func_myisam(
void *arg)
 
 1609   if (h->end_range && h->compare_key_icp(h->end_range) > 0)
 
 1610     return ICP_OUT_OF_RANGE; 
 
 1612   return (ICP_RESULT) 
test(h->pushed_idx_cond->val_int());
 
 1618 int ha_myisam::index_init(uint idx, 
bool sorted)
 
 1621   if (pushed_idx_cond_keyno == idx)
 
 1622     mi_set_index_cond_func(file, index_cond_func_myisam, 
this);
 
 1627 int ha_myisam::index_end()
 
 1629   active_index=MAX_KEY;
 
 1631   mi_set_index_cond_func(file, NULL, 0);
 
 1632   in_range_check_pushed_down= FALSE;
 
 1633   ds_mrr.dsmrr_close();
 
 1637 int ha_myisam::rnd_end()
 
 1639   ds_mrr.dsmrr_close();
 
 1644                               key_part_map keypart_map,
 
 1645                               enum ha_rkey_function find_flag)
 
 1647   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1648   DBUG_ASSERT(inited==INDEX);
 
 1649   ha_statistic_increment(&SSV::ha_read_key_count);
 
 1650   int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
 
 1651   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1652   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1657                                   key_part_map keypart_map,
 
 1658                                   enum ha_rkey_function find_flag)
 
 1660   DBUG_ASSERT(pushed_idx_cond == NULL);
 
 1661   DBUG_ASSERT(pushed_idx_cond_keyno == MAX_KEY);
 
 1662   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1663   ha_statistic_increment(&SSV::ha_read_key_count);
 
 1664   int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
 
 1665   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1666   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1671                                    key_part_map keypart_map)
 
 1673   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1674   DBUG_ENTER(
"ha_myisam::index_read_last");
 
 1675   DBUG_ASSERT(inited==INDEX);
 
 1676   ha_statistic_increment(&SSV::ha_read_key_count);
 
 1677   int error=mi_rkey(file, buf, active_index, key, keypart_map,
 
 1678                     HA_READ_PREFIX_LAST);
 
 1679   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1680   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1686   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1687   DBUG_ASSERT(inited==INDEX);
 
 1688   ha_statistic_increment(&SSV::ha_read_next_count);
 
 1689   int error=mi_rnext(file,buf,active_index);
 
 1690   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1691   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1697   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1698   DBUG_ASSERT(inited==INDEX);
 
 1699   ha_statistic_increment(&SSV::ha_read_prev_count);
 
 1700   int error=mi_rprev(file,buf, active_index);
 
 1701   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1702   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1708   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1709   DBUG_ASSERT(inited==INDEX);
 
 1710   ha_statistic_increment(&SSV::ha_read_first_count);
 
 1711   int error=mi_rfirst(file, buf, active_index);
 
 1712   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1713   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1719   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1720   DBUG_ASSERT(inited==INDEX);
 
 1721   ha_statistic_increment(&SSV::ha_read_last_count);
 
 1722   int error=mi_rlast(file, buf, active_index);
 
 1723   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1724   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1729                                const uchar *key __attribute__((unused)),
 
 1730                                uint length __attribute__((unused)))
 
 1733   DBUG_ASSERT(inited==INDEX);
 
 1734   MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
 
 1735   ha_statistic_increment(&SSV::ha_read_next_count);
 
 1738     error= mi_rnext_same(file,buf);
 
 1739   } 
while (error == HA_ERR_RECORD_DELETED);
 
 1740   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1741   MYSQL_INDEX_READ_ROW_DONE(error);
 
 1749     return mi_scan_init(file);
 
 1750   return mi_reset(file);                        
 
 1755   MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
 
 1757   ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
 1758   int error=mi_scan(file, buf);
 
 1759   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1760   MYSQL_READ_ROW_DONE(error);
 
 1771   MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
 
 1773   ha_statistic_increment(&SSV::ha_read_rnd_count);
 
 1774   int error=mi_rrnd(file, buf, my_get_ptr(pos,
ref_length));
 
 1775   table->status=error ? STATUS_NOT_FOUND: 0;
 
 1776   MYSQL_READ_ROW_DONE(error);
 
 1781 void ha_myisam::position(
const uchar *record)
 
 1783   my_off_t row_position= mi_position(file);
 
 1787 int ha_myisam::info(uint flag)
 
 1790   char name_buff[FN_REFLEN];
 
 1792   (void) mi_status(file,&misam_info,flag);
 
 1793   if (flag & HA_STATUS_VARIABLE)
 
 1795     stats.records=           misam_info.records;
 
 1796     stats.deleted=           misam_info.deleted;
 
 1797     stats.data_file_length=  misam_info.data_file_length;
 
 1798     stats.index_file_length= misam_info.index_file_length;
 
 1799     stats.delete_length=     misam_info.delete_length;
 
 1800     stats.check_time=        (ulong) misam_info.check_time;
 
 1801     stats.mean_rec_length=   misam_info.mean_reclength;
 
 1803   if (flag & HA_STATUS_CONST)
 
 1806     stats.max_data_file_length=  misam_info.max_data_file_length;
 
 1807     stats.max_index_file_length= misam_info.max_index_file_length;
 
 1808     stats.create_time= misam_info.create_time;
 
 1817     stats.mrr_length_per_rec= misam_info.reflength + 8; 
 
 1819     share->db_options_in_use= misam_info.options;
 
 1820     stats.block_size= myisam_block_size;        
 
 1828     share->keys_in_use.set_prefix(share->keys);
 
 1829     share->keys_in_use.intersect_extended(misam_info.key_map);
 
 1830     share->keys_for_keyread.intersect(share->keys_in_use);
 
 1831     share->db_record_offset= misam_info.record_offset;
 
 1833     if (share->key_parts)
 
 1835              (
char*) misam_info.rec_per_key,
 
 1836              sizeof(table->key_info[0].
rec_per_key[0])*share->key_parts);
 
 1842     data_file_name= index_file_name= 0;
 
 1843     fn_format(name_buff, file->filename, 
"", MI_NAME_DEXT,
 
 1844               MY_APPEND_EXT | MY_UNPACK_FILENAME);
 
 1845     if (strcmp(name_buff, misam_info.data_file_name))
 
 1846       data_file_name=misam_info.data_file_name;
 
 1847     fn_format(name_buff, file->filename, 
"", MI_NAME_IEXT,
 
 1848               MY_APPEND_EXT | MY_UNPACK_FILENAME);
 
 1849     if (strcmp(name_buff, misam_info.index_file_name))
 
 1850       index_file_name=misam_info.index_file_name;
 
 1852   if (flag & HA_STATUS_ERRKEY)
 
 1854     errkey  = misam_info.errkey;
 
 1855     my_store_ptr(dup_ref, 
ref_length, misam_info.dupp_key_pos);
 
 1857   if (flag & HA_STATUS_TIME)
 
 1858     stats.update_time = (ulong) misam_info.update_time;
 
 1859   if (flag & HA_STATUS_AUTO)
 
 1860     stats.auto_increment_value= misam_info.auto_increment;
 
 1866 int ha_myisam::extra(
enum ha_extra_function operation)
 
 1868   if (operation == HA_EXTRA_MMAP && !opt_myisam_use_mmap)
 
 1870   return mi_extra(file, operation, 0);
 
 1876   DBUG_ASSERT(pushed_idx_cond == NULL);
 
 1877   DBUG_ASSERT(pushed_idx_cond_keyno == MAX_KEY);
 
 1878   mi_set_index_cond_func(file, NULL, 0);
 
 1880   return mi_reset(file);
 
 1885 int ha_myisam::extra_opt(
enum ha_extra_function operation, ulong cache_size)
 
 1887   return mi_extra(file, operation, (
void*) &cache_size);
 
 1892   return mi_delete_all_rows(file);
 
 1909   file->s->state.auto_increment= value;
 
 1915   return mi_delete_table(name);
 
 1919 int ha_myisam::external_lock(THD *thd, 
int lock_type)
 
 1921   file->in_use.data= thd;
 
 1922   return mi_lock_database(file, !table->s->tmp_table ?
 
 1923                           lock_type : ((lock_type == F_UNLCK) ?
 
 1924                                        F_UNLCK : F_EXTRA_LCK));
 
 1929                                       enum thr_lock_type lock_type)
 
 1931   if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
 1932     file->lock.type=lock_type;
 
 1939   ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
 
 1940   if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
 1942     create_info->auto_increment_value= 
stats.auto_increment_value;
 
 1944   create_info->data_file_name=data_file_name;
 
 1945   create_info->index_file_name=index_file_name;
 
 1949 int ha_myisam::create(
const char *name, 
register TABLE *table_arg,
 
 1954   char buff[FN_REFLEN];
 
 1959   uint options= share->db_options_in_use;
 
 1960   DBUG_ENTER(
"ha_myisam::create");
 
 1961   for (i= 0; i < share->keys; i++)
 
 1963     if (table_arg->key_info[i].
flags & HA_USES_PARSER)
 
 1965       create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
 
 1969   if ((error= table2myisam(table_arg, &keydef, &recinfo, &
records)))
 
 1971   memset(&create_info, 0, 
sizeof(create_info));
 
 1972   create_info.max_rows= share->max_rows;
 
 1973   create_info.reloc_rows= share->min_rows;
 
 1974   create_info.with_auto_increment= share->next_number_key_offset == 0;
 
 1975   create_info.auto_increment= (ha_create_info->auto_increment_value ?
 
 1976                                ha_create_info->auto_increment_value -1 :
 
 1978   create_info.data_file_length= ((ulonglong) share->max_rows *
 
 1979                                  share->avg_row_length);
 
 1980   create_info.language= share->table_charset->number;
 
 1982 #ifdef HAVE_READLINK 
 1985     create_info.data_file_name= ha_create_info->data_file_name;
 
 1986     create_info.index_file_name= ha_create_info->index_file_name;
 
 1991     if (ha_create_info->data_file_name)
 
 1992       push_warning_printf(table_arg->in_use, Sql_condition::WARN_LEVEL_WARN,
 
 1993                           WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
 
 1995     if (ha_create_info->index_file_name)
 
 1996       push_warning_printf(table_arg->in_use, Sql_condition::WARN_LEVEL_WARN,
 
 1997                           WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
 
 2001   if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
 2002     create_flags|= HA_CREATE_TMP_TABLE;
 
 2003   if (ha_create_info->options & HA_CREATE_KEEP_FILES)
 
 2004     create_flags|= HA_CREATE_KEEP_FILES;
 
 2005   if (options & HA_OPTION_PACK_RECORD)
 
 2006     create_flags|= HA_PACK_RECORD;
 
 2007   if (options & HA_OPTION_CHECKSUM)
 
 2008     create_flags|= HA_CREATE_CHECKSUM;
 
 2009   if (options & HA_OPTION_DELAY_KEY_WRITE)
 
 2010     create_flags|= HA_CREATE_DELAY_KEY_WRITE;
 
 2013   error= mi_create(fn_format(buff, name, 
"", 
"",
 
 2014                              MY_UNPACK_FILENAME|MY_APPEND_EXT),
 
 2015                    share->keys, keydef,
 
 2018                    &create_info, create_flags);
 
 2026   return mi_rename(from,to);
 
 2031                                    ulonglong nb_desired_values,
 
 2032                                    ulonglong *first_value,
 
 2033                                    ulonglong *nb_reserved_values)
 
 2037   uchar key[MI_MAX_KEY_LENGTH];
 
 2039   if (!table->s->next_number_key_offset)
 
 2041     ha_myisam::info(HA_STATUS_AUTO);
 
 2042     *first_value= 
stats.auto_increment_value;
 
 2044     *nb_reserved_values= ULONGLONG_MAX;
 
 2049   mi_flush_bulk_insert(file, table->s->next_number_index);
 
 2051   (void) 
extra(HA_EXTRA_KEYREAD);
 
 2052   key_copy(key, table->record[0],
 
 2053            table->key_info + table->s->next_number_index,
 
 2054            table->s->next_number_key_offset);
 
 2055   error= mi_rkey(file, table->record[1], (
int) table->s->next_number_index,
 
 2056                  key, make_prev_keypart_map(table->s->next_number_keypart),
 
 2057                  HA_READ_PREFIX_LAST);
 
 2063     nr= ((ulonglong) table->next_number_field->
 
 2064          val_int_offset(table->s->rec_buff_length)+1);
 
 2066   extra(HA_EXTRA_NO_KEYREAD);
 
 2074   *nb_reserved_values= 1;
 
 2103 ha_rows ha_myisam::records_in_range(uint inx, 
key_range *min_key,
 
 2106   return (ha_rows) mi_records_in_range(file, (
int) inx, min_key, max_key);
 
 2110 int ha_myisam::ft_read(uchar *buf)
 
 2117   thread_safe_increment(table->in_use->status_var.ha_read_next_count,
 
 2120   error=ft_handler->please->read_next(ft_handler,(
char*) buf);
 
 2122   table->status=error ? STATUS_NOT_FOUND: 0;
 
 2126 uint ha_myisam::checksum()
 const 
 2128   return (uint)file->state->checksum;
 
 2135   uint options= table->s->db_options_in_use;
 
 2137   if (info->auto_increment_value != 
stats.auto_increment_value ||
 
 2138       info->data_file_name != data_file_name ||
 
 2139       info->index_file_name != index_file_name ||
 
 2140       table_changes == IS_EQUAL_NO ||
 
 2141       table_changes & IS_EQUAL_PACK_LENGTH) 
 
 2142     return COMPATIBLE_DATA_NO;
 
 2144   if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
 2145                   HA_OPTION_DELAY_KEY_WRITE)) !=
 
 2146       (info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
 2147                               HA_OPTION_DELAY_KEY_WRITE)))
 
 2148     return COMPATIBLE_DATA_NO;
 
 2149   return COMPATIBLE_DATA_YES;
 
 2152 extern int mi_panic(
enum ha_panic_function flag);
 
 2153 int myisam_panic(
handlerton *hton, ha_panic_function flag)
 
 2155   return mi_panic(flag);
 
 2158 static int myisam_init(
void *p)
 
 2162 #ifdef HAVE_PSI_INTERFACE 
 2163   init_myisam_psi_keys();
 
 2167   if (myisam_recover_options)
 
 2168     ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
 
 2170     myisam_recover_options= HA_RECOVER_OFF;
 
 2172   myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
 
 2175   myisam_hton->state= SHOW_OPTION_YES;
 
 2176   myisam_hton->db_type= DB_TYPE_MYISAM;
 
 2177   myisam_hton->create= myisam_create_handler;
 
 2178   myisam_hton->panic= myisam_panic;
 
 2179   myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
 
 2191                                      uint n_ranges, uint mode, 
 
 2194   return ds_mrr.
dsmrr_init(
this, seq, seq_init_param, n_ranges, mode, buf);
 
 2199   return ds_mrr.dsmrr_next(range_info);
 
 2203                                                void *seq_init_param, 
 
 2204                                                uint n_ranges, uint *bufsz,
 
 2212   ds_mrr.init(
this, table);
 
 2213   return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
 
 2218                                          uint *bufsz, uint *
flags,
 
 2221   ds_mrr.init(
this, table);
 
 2222   return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 
 2240   const KEY *key= &table_share->key_info[keyno_arg];
 
 2245     if (key_part->key_part_flag & HA_BLOB_PART)
 
 2248       return idx_cond_arg;
 
 2252   pushed_idx_cond_keyno= keyno_arg;
 
 2253   pushed_idx_cond= idx_cond_arg;
 
 2254   in_range_check_pushed_down= TRUE;
 
 2255   if (active_index == pushed_idx_cond_keyno)
 
 2256     mi_set_index_cond_func(file, index_cond_func_myisam, 
this);
 
 2262   MYSQL_SYSVAR(block_size),
 
 2263   MYSQL_SYSVAR(data_pointer_size),
 
 2264   MYSQL_SYSVAR(max_sort_file_size),
 
 2265   MYSQL_SYSVAR(recover_options),
 
 2266   MYSQL_SYSVAR(repair_threads),
 
 2267   MYSQL_SYSVAR(sort_buffer_size),
 
 2268   MYSQL_SYSVAR(use_mmap),
 
 2269   MYSQL_SYSVAR(mmap_size),
 
 2270   MYSQL_SYSVAR(stats_method),
 
 2275 { MYSQL_HANDLERTON_INTERFACE_VERSION };
 
 2277 mysql_declare_plugin(myisam)
 
 2279   MYSQL_STORAGE_ENGINE_PLUGIN,
 
 2280   &myisam_storage_engine,
 
 2283   "MyISAM storage engine",
 
 2293 mysql_declare_plugin_end;
 
 2296 #ifdef HAVE_QUERY_CACHE 
 2318                                               uint table_name_len,
 
 2321                                               ulonglong *engine_data)
 
 2323   DBUG_ENTER(
"ha_myisam::register_query_cache_table");
 
 2328   *engine_callback= 0;
 
 2335   if (file->s->concurrent_insert)
 
 2352     ulonglong actual_data_file_length;
 
 2353     ulonglong current_data_file_length;
 
 2366     actual_data_file_length= file->s->state.state.data_file_length;
 
 2367     current_data_file_length= file->save_state.data_file_length;
 
 2369     if (current_data_file_length != actual_data_file_length)
 
 2382   if (file->state->uncacheable)