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)