14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
#ifdef USE_PRAGMA_IMPLEMENTATION
18
#pragma implementation // gcc: Class implementation
21
#define DRIZZLE_SERVER 1
23
#include <drizzled/server_includes.h>
24
#include <mysys/my_bit.h>
25
#include <myisampack.h>
19
#include "drizzled/internal/my_bit.h"
20
#include "myisampack.h"
26
21
#include "ha_myisam.h"
27
#include "myisamdef.h"
28
#include <drizzled/drizzled_error_messages.h>
30
ulong myisam_recover_options= HA_RECOVER_NONE;
32
/* bits in myisam_recover_options */
33
const char *myisam_recover_names[] =
34
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
35
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
36
myisam_recover_names, NULL};
38
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
39
"nulls_ignored", NullS};
40
TYPELIB myisam_stats_method_typelib= {
41
array_elements(myisam_stats_method_names) - 1, "",
42
myisam_stats_method_names, NULL};
22
#include "myisam_priv.h"
23
#include "drizzled/my_getopt.h"
24
#include "drizzled/internal/my_bit.h"
25
#include "drizzled/internal/m_string.h"
26
#include "drizzled/util/test.h"
27
#include "drizzled/error.h"
28
#include "drizzled/errmsg_print.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/session.h"
31
#include "drizzled/set_var.h"
32
#include <drizzled/plugin.h>
33
#include "drizzled/plugin/client.h"
34
#include "drizzled/table.h"
35
#include "drizzled/field/timestamp.h"
36
#include "drizzled/memory/multi_malloc.h"
44
using namespace drizzled;
46
extern pthread_mutex_t LOCK_global_system_variables;
47
static const string engine_name("MyISAM");
49
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
51
static uint32_t repair_threads;
52
static uint32_t myisam_key_cache_block_size;
53
static uint32_t myisam_key_cache_size;
54
static uint32_t myisam_key_cache_division_limit;
55
static uint32_t myisam_key_cache_age_threshold;
56
static uint64_t max_sort_file_size;
57
static uint64_t sort_buffer_size;
45
59
/*****************************************************************************
47
61
*****************************************************************************/
49
static handler *myisam_create_handler(handlerton *hton,
53
return new (mem_root) ha_myisam(hton, table);
63
static const char *ha_myisam_exts[] = {
69
class MyisamEngine : public plugin::StorageEngine
72
MyisamEngine(string name_arg)
73
: plugin::StorageEngine(name_arg,
74
HTON_HAS_DATA_DICTIONARY |
75
HTON_CAN_INDEX_BLOBS |
76
HTON_STATS_RECORDS_IS_EXACT |
82
HTON_SKIP_STORE_LOCK |
88
virtual Cursor *create(TableShare &table,
89
memory::Root *mem_root)
91
return new (mem_root) ha_myisam(*this, table);
94
const char **bas_ext() const {
95
return ha_myisam_exts;
98
int doCreateTable(Session *, const char *table_name,
102
int doRenameTable(Session*, const char *from, const char *to);
104
int doDropTable(Session&, const string table_name);
106
int doGetTableDefinition(Session& session,
109
const char *table_name,
111
message::Table *table_proto);
113
/* Temp only engine, so do not return values. */
114
void doGetTableNames(CachedDirectory &, string& , set<string>&) { };
116
uint32_t max_supported_keys() const { return MI_MAX_KEY; }
117
uint32_t max_supported_key_length() const { return MI_MAX_KEY_LENGTH; }
118
uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
120
uint32_t index_flags(enum ha_key_alg) const
122
return (HA_READ_NEXT |
130
int MyisamEngine::doGetTableDefinition(Session&,
135
message::Table *table_proto)
138
ProtoCache::iterator iter;
140
pthread_mutex_lock(&proto_cache_mutex);
141
iter= proto_cache.find(path);
143
if (iter!= proto_cache.end())
146
table_proto->CopyFrom(((*iter).second));
149
pthread_mutex_unlock(&proto_cache_mutex);
56
// collect errors printed by mi_check routines
155
Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
58
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
59
const char *fmt, va_list args)
158
static void mi_check_print_msg(MI_CHECK *, const char* ,
159
const char *, va_list )
61
THD* thd = (THD*)param->thd;
62
Protocol *protocol= thd->protocol;
63
uint length, msg_length;
64
char msgbuf[MI_MAX_MSG_BUF];
65
char name[NAME_LEN*2+2];
67
msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
68
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
72
sql_print_error(msgbuf);
76
if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
79
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
82
length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
85
TODO: switch from protocol to push_warning here. The main reason we didn't
86
it yet is parallel repair. Due to following trace:
87
mi_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
89
Also we likely need to lock mutex here (in both cases with protocol and
92
protocol->prepare_for_resend();
93
protocol->store(name, length, system_charset_info);
94
protocol->store(param->op_name, system_charset_info);
95
protocol->store(msg_type, system_charset_info);
96
protocol->store(msgbuf, msg_length, system_charset_info);
97
if (protocol->write())
98
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
105
Convert TABLE object to MyISAM key and column definition
165
Convert Table object to MyISAM key and column definition
109
table_arg in TABLE object.
169
table_arg in Table object.
110
170
keydef_out out MyISAM key definition.
111
171
recinfo_out out MyISAM column definition.
112
172
records_out out Number of fields.
442
503
void _mi_report_crashed(MI_INFO *file, const char *message,
443
const char *sfile, uint sline)
504
const char *sfile, uint32_t sline)
506
Session *cur_session;
447
507
pthread_mutex_lock(&file->s->intern_lock);
448
if ((cur_thd= (THD*) file->in_use.data))
449
sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
508
if ((cur_session= file->in_use))
509
errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
510
cur_session->thread_id,
452
sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline);
513
errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
454
sql_print_error("%s", message);
455
for (element= file->s->in_use; element; element= list_rest(element))
515
errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
516
list<Session *>::iterator it= file->s->in_use->begin();
517
while (it != file->s->in_use->end())
457
sql_print_error("%s", "Unknown thread accessing table");
519
errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
459
522
pthread_mutex_unlock(&file->s->intern_lock);
464
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
465
:handler(hton, table_arg), file(0),
466
int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
467
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
468
HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
469
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
470
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
471
HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT |
472
HA_NEED_READ_RANGE_BUFFER | HA_MRR_CANT_SORT),
473
can_enable_indexes(1)
476
handler *ha_myisam::clone(MEM_ROOT *mem_root)
525
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
526
TableShare &table_arg)
527
: Cursor(engine_arg, table_arg),
529
can_enable_indexes(true),
533
Cursor *ha_myisam::clone(memory::Root *mem_root)
478
ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
535
ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
480
537
new_handler->file->state= file->state;
481
538
return new_handler;
485
static const char *ha_myisam_exts[] = {
491
const char **ha_myisam::bas_ext() const
493
return ha_myisam_exts;
497
const char *ha_myisam::index_type(uint key_number __attribute__((unused)))
541
const char *ha_myisam::index_type(uint32_t )
502
546
/* Name is here without an extension */
503
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
547
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
505
549
MI_KEYDEF *keyinfo;
506
550
MI_COLUMNDEF *recinfo= 0;
511
555
If the user wants to have memory mapped data files, add an
612
648
return mi_write(file,buf);
615
int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
617
if (!file) return HA_ADMIN_INTERNAL_ERROR;
620
MYISAM_SHARE* share = file->s;
621
const char *old_proc_info=thd->proc_info;
623
thd_proc_info(thd, "Checking table");
624
myisamchk_init(¶m);
626
param.op_name = "check";
627
param.db_name= table->s->db.str;
628
param.table_name= table->alias;
629
param.testflag = check_opt->flags | T_CHECK | T_SILENT;
630
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
632
if (!(table->db_stat & HA_READ_ONLY))
633
param.testflag|= T_STATISTICS;
634
param.using_global_keycache = 1;
636
if (!mi_is_crashed(file) &&
637
(((param.testflag & T_CHECK_ONLY_CHANGED) &&
638
!(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
639
STATE_CRASHED_ON_REPAIR)) &&
640
share->state.open_count == 0) ||
641
((param.testflag & T_FAST) && (share->state.open_count ==
642
(uint) (share->global_changed ? 1 : 0)))))
643
return HA_ADMIN_ALREADY_DONE;
645
error = chk_status(¶m, file); // Not fatal
646
error = chk_size(¶m, file);
648
error |= chk_del(¶m, file, param.testflag);
650
error = chk_key(¶m, file);
653
if ((!(param.testflag & T_QUICK) &&
655
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
656
(param.testflag & (T_EXTEND | T_MEDIUM)))) ||
659
uint old_testflag=param.testflag;
660
param.testflag|=T_MEDIUM;
661
if (!(error= init_io_cache(¶m.read_cache, file->dfile,
662
my_default_record_cache_size, READ_CACHE,
663
share->pack.header_length, 1, MYF(MY_WME))))
665
error= chk_data_link(¶m, file, param.testflag & T_EXTEND);
666
end_io_cache(&(param.read_cache));
668
param.testflag= old_testflag;
673
if ((share->state.changed & (STATE_CHANGED |
674
STATE_CRASHED_ON_REPAIR |
675
STATE_CRASHED | STATE_NOT_ANALYZED)) ||
676
(param.testflag & T_STATISTICS) ||
679
file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
680
pthread_mutex_lock(&share->intern_lock);
681
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
682
STATE_CRASHED_ON_REPAIR);
683
if (!(table->db_stat & HA_READ_ONLY))
684
error=update_state_info(¶m,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
686
pthread_mutex_unlock(&share->intern_lock);
687
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
691
else if (!mi_is_crashed(file) && !thd->killed)
693
mi_mark_crashed(file);
694
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
697
thd_proc_info(thd, old_proc_info);
698
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
703
analyze the key distribution in the table
704
As the table may be only locked for read, we have to take into account that
705
two threads may do an analyze at the same time!
708
int ha_myisam::analyze(THD *thd,
709
HA_CHECK_OPT* check_opt __attribute__((unused)))
713
MYISAM_SHARE* share = file->s;
715
myisamchk_init(¶m);
717
param.op_name= "analyze";
718
param.db_name= table->s->db.str;
719
param.table_name= table->alias;
720
param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
721
T_DONT_CHECK_CHECKSUM);
722
param.using_global_keycache = 1;
723
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
725
if (!(share->state.changed & STATE_NOT_ANALYZED))
726
return HA_ADMIN_ALREADY_DONE;
728
error = chk_key(¶m, file);
731
pthread_mutex_lock(&share->intern_lock);
732
error=update_state_info(¶m,file,UPDATE_STAT);
733
pthread_mutex_unlock(&share->intern_lock);
735
else if (!mi_is_crashed(file) && !thd->killed)
736
mi_mark_crashed(file);
737
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
741
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
745
ha_rows start_records;
747
if (!file) return HA_ADMIN_INTERNAL_ERROR;
749
myisamchk_init(¶m);
751
param.op_name= "repair";
752
param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
753
T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
754
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
755
param.sort_buffer_length= check_opt->sort_buffer_size;
756
start_records=file->state->records;
757
while ((error=repair(thd,param,0)) && param.retry_repair)
759
param.retry_repair=0;
760
if (test_all_bits(param.testflag,
761
(uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
763
param.testflag&= ~T_RETRY_WITHOUT_QUICK;
764
sql_print_information("Retrying repair of: '%s' without quick",
768
param.testflag&= ~T_QUICK;
769
if ((param.testflag & T_REP_BY_SORT))
771
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
772
sql_print_information("Retrying repair of: '%s' with keycache",
778
if (!error && start_records != file->state->records &&
779
!(check_opt->flags & T_VERY_SILENT))
781
char llbuff[22],llbuff2[22];
782
sql_print_information("Found %s of %s rows when repairing '%s'",
783
llstr(file->state->records, llbuff),
784
llstr(start_records, llbuff2),
790
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
793
if (!file) return HA_ADMIN_INTERNAL_ERROR;
796
myisamchk_init(¶m);
798
param.op_name= "optimize";
799
param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
800
T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
801
param.sort_buffer_length= check_opt->sort_buffer_size;
802
if ((error= repair(thd,param,1)) && param.retry_repair)
804
sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
805
my_errno, param.db_name, param.table_name);
806
param.testflag&= ~T_REP_BY_SORT;
807
error= repair(thd,param,1);
813
int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize)
816
uint local_testflag=param.testflag;
652
int ha_myisam::repair(Session *session, MI_CHECK ¶m, bool do_optimize)
655
uint32_t local_testflag= param.testflag;
817
656
bool optimize_done= !do_optimize, statistics_done=0;
818
const char *old_proc_info=thd->proc_info;
657
const char *old_proc_info= session->get_proc_info();
819
658
char fixed_name[FN_REFLEN];
820
659
MYISAM_SHARE* share = file->s;
821
660
ha_rows rows= file->state->records;
1494
1215
if (flag & HA_STATUS_CONST)
1496
TABLE_SHARE *share= table->s;
1217
TableShare *share= table->s;
1497
1218
stats.max_data_file_length= misam_info.max_data_file_length;
1498
1219
stats.max_index_file_length= misam_info.max_index_file_length;
1499
1220
stats.create_time= misam_info.create_time;
1500
1221
ref_length= misam_info.reflength;
1501
1222
share->db_options_in_use= misam_info.options;
1502
stats.block_size= myisam_block_size; /* record block size */
1223
stats.block_size= myisam_key_cache_block_size; /* record block size */
1504
1225
/* Update share */
1505
1226
if (share->tmp_table == NO_TMP_TABLE)
1506
1227
pthread_mutex_lock(&share->mutex);
1507
share->keys_in_use.set_prefix(share->keys);
1508
share->keys_in_use.intersect_extended(misam_info.key_map);
1509
share->keys_for_keyread.intersect(share->keys_in_use);
1228
set_prefix(share->keys_in_use, share->keys);
1230
* Due to bug 394932 (32-bit solaris build failure), we need
1231
* to convert the uint64_t key_map member of the misam_info
1232
* structure in to a std::bitset so that we can logically and
1233
* it with the share->key_in_use key_map.
1236
string binary_key_map;
1237
uint64_t num= misam_info.key_map;
1239
* Convert the uint64_t to a binary
1240
* string representation of it.
1244
uint64_t bin_digit= num % 2;
1248
binary_key_map.append(ostr.str());
1250
* Now we have the binary string representation of the
1251
* flags, we need to fill that string representation out
1252
* with the appropriate number of bits. This is needed
1253
* since key_map is declared as a std::bitset of a certain bit
1254
* width that depends on the MAX_INDEXES variable.
1256
if (MAX_INDEXES <= 64)
1258
size_t len= 72 - binary_key_map.length();
1259
string all_zeros(len, '0');
1260
binary_key_map.insert(binary_key_map.begin(),
1266
size_t len= (MAX_INDEXES + 7) / 8 * 8;
1267
string all_zeros(len, '0');
1268
binary_key_map.insert(binary_key_map.begin(),
1272
key_map tmp_map(binary_key_map);
1273
share->keys_in_use&= tmp_map;
1274
share->keys_for_keyread&= share->keys_in_use;
1510
1275
share->db_record_offset= misam_info.record_offset;
1511
1276
if (share->key_parts)
1512
1277
memcpy(table->key_info[0].rec_per_key,
1573
1330
return mi_delete_all_rows(file);
1576
int ha_myisam::delete_table(const char *name)
1333
int MyisamEngine::doDropTable(Session&, const string table_path)
1578
return mi_delete_table(name);
1335
ProtoCache::iterator iter;
1337
pthread_mutex_lock(&proto_cache_mutex);
1338
iter= proto_cache.find(table_path.c_str());
1340
if (iter!= proto_cache.end())
1341
proto_cache.erase(iter);
1343
pthread_mutex_unlock(&proto_cache_mutex);
1345
return mi_delete_table(table_path.c_str());
1582
int ha_myisam::external_lock(THD *thd, int lock_type)
1349
int ha_myisam::external_lock(Session *session, int lock_type)
1584
file->in_use.data= thd;
1351
file->in_use= session;
1585
1352
return mi_lock_database(file, !table->s->tmp_table ?
1586
1353
lock_type : ((lock_type == F_UNLCK) ?
1587
1354
F_UNLCK : F_EXTRA_LCK));
1590
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
1592
enum thr_lock_type lock_type)
1594
if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
1595
file->lock.type=lock_type;
1600
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
1602
ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
1603
if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
1605
create_info->auto_increment_value= stats.auto_increment_value;
1607
create_info->data_file_name=data_file_name;
1608
create_info->index_file_name=index_file_name;
1612
int ha_myisam::create(const char *name, register TABLE *table_arg,
1613
HA_CREATE_INFO *ha_create_info)
1357
int MyisamEngine::doCreateTable(Session *, const char *table_name,
1359
message::Table& create_proto)
1616
uint create_flags= 0, records;
1362
uint32_t create_flags= 0, create_records;
1617
1363
char buff[FN_REFLEN];
1618
1364
MI_KEYDEF *keydef;
1619
1365
MI_COLUMNDEF *recinfo;
1620
1366
MI_CREATE_INFO create_info;
1621
TABLE_SHARE *share= table_arg->s;
1622
uint options= share->db_options_in_use;
1623
if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1624
return(error); /* purecov: inspected */
1367
TableShare *share= table_arg.s;
1368
uint32_t options= share->db_options_in_use;
1369
if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1625
1371
memset(&create_info, 0, sizeof(create_info));
1626
create_info.max_rows= share->max_rows;
1627
create_info.reloc_rows= share->min_rows;
1372
create_info.max_rows= create_proto.options().max_rows();
1373
create_info.reloc_rows= create_proto.options().min_rows();
1628
1374
create_info.with_auto_increment= share->next_number_key_offset == 0;
1629
create_info.auto_increment= (ha_create_info->auto_increment_value ?
1630
ha_create_info->auto_increment_value -1 :
1375
create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1376
create_proto.options().auto_increment_value() -1 :
1632
create_info.data_file_length= ((uint64_t) share->max_rows *
1633
share->avg_row_length);
1634
create_info.data_file_name= ha_create_info->data_file_name;
1635
create_info.index_file_name= ha_create_info->index_file_name;
1378
create_info.data_file_length= (create_proto.options().max_rows() *
1379
create_proto.options().avg_row_length());
1380
create_info.data_file_name= NULL;
1381
create_info.index_file_name= NULL;
1636
1382
create_info.language= share->table_charset->number;
1638
if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1384
if (create_proto.type() == message::Table::TEMPORARY)
1639
1385
create_flags|= HA_CREATE_TMP_TABLE;
1640
if (ha_create_info->options & HA_CREATE_KEEP_FILES)
1641
create_flags|= HA_CREATE_KEEP_FILES;
1642
1386
if (options & HA_OPTION_PACK_RECORD)
1643
1387
create_flags|= HA_PACK_RECORD;
1644
if (options & HA_OPTION_CHECKSUM)
1645
create_flags|= HA_CREATE_CHECKSUM;
1646
if (options & HA_OPTION_DELAY_KEY_WRITE)
1647
create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1649
/* TODO: Check that the following fn_format is really needed */
1650
error= mi_create(fn_format(buff, name, "", "",
1389
/* TODO: Check that the following internal::fn_format is really needed */
1390
error= mi_create(internal::fn_format(buff, table_name, "", "",
1651
1391
MY_UNPACK_FILENAME|MY_APPEND_EXT),
1652
1392
share->keys, keydef,
1393
create_records, recinfo,
1654
1394
0, (MI_UNIQUEDEF*) 0,
1655
1395
&create_info, create_flags);
1656
my_free((uchar*) recinfo, MYF(0));
1396
free((unsigned char*) recinfo);
1398
pthread_mutex_lock(&proto_cache_mutex);
1399
proto_cache.insert(make_pair(table_name, create_proto));
1400
pthread_mutex_unlock(&proto_cache_mutex);
1661
int ha_myisam::rename_table(const char * from, const char * to)
1406
int MyisamEngine::doRenameTable(Session*,
1407
const char *from, const char *to)
1663
1409
return mi_rename(from,to);
1667
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1668
uint64_t increment __attribute__((unused)),
1669
uint64_t nb_desired_values __attribute__((unused)),
1413
void ha_myisam::get_auto_increment(uint64_t ,
1670
1416
uint64_t *first_value,
1671
1417
uint64_t *nb_reserved_values)
1675
uchar key[MI_MAX_KEY_LENGTH];
1421
unsigned char key[MI_MAX_KEY_LENGTH];
1677
1423
if (!table->s->next_number_key_offset)
1678
1424
{ // Autoincrement at key-start
1741
ha_rows ha_myisam::records_in_range(uint inx, key_range *min_key,
1487
ha_rows ha_myisam::records_in_range(uint32_t inx, key_range *min_key,
1742
1488
key_range *max_key)
1744
1490
return (ha_rows) mi_records_in_range(file, (int) inx, min_key, max_key);
1748
uint ha_myisam::checksum() const
1494
uint32_t ha_myisam::checksum() const
1750
1496
return (uint)file->state->checksum;
1499
static MyisamEngine *engine= NULL;
1754
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1501
static int myisam_init(plugin::Registry ®istry)
1757
uint options= table->s->db_options_in_use;
1759
if (info->auto_increment_value != stats.auto_increment_value ||
1760
info->data_file_name != data_file_name ||
1761
info->index_file_name != index_file_name ||
1762
table_changes == IS_EQUAL_NO ||
1763
table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
1764
return COMPATIBLE_DATA_NO;
1766
if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1767
HA_OPTION_DELAY_KEY_WRITE)) !=
1768
(info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1769
HA_OPTION_DELAY_KEY_WRITE)))
1770
return COMPATIBLE_DATA_NO;
1771
return COMPATIBLE_DATA_YES;
1504
engine= new MyisamEngine(engine_name);
1505
registry.add(engine);
1507
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
1509
/* call ha_init_key_cache() on all key caches to init them */
1510
error= init_key_cache(dflt_key_cache,
1511
myisam_key_cache_block_size,
1512
myisam_key_cache_size,
1513
myisam_key_cache_division_limit,
1514
myisam_key_cache_age_threshold);
1517
exit(1); /* Memory Allocation Failure */
1774
int myisam_deinit(void *hton __attribute__((unused)))
1522
static int myisam_deinit(plugin::Registry ®istry)
1524
registry.remove(engine);
1527
pthread_mutex_destroy(&THR_LOCK_myisam);
1528
end_key_cache(dflt_key_cache, 1); // Can never fail
1776
1530
return mi_panic(HA_PANIC_CLOSE);
1779
static int myisam_init(void *p)
1781
handlerton *myisam_hton;
1783
myisam_hton= (handlerton *)p;
1784
myisam_hton->state= SHOW_OPTION_YES;
1785
myisam_hton->db_type= DB_TYPE_MYISAM;
1786
myisam_hton->create= myisam_create_handler;
1787
myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1793
/****************************************************************************
1794
* MyISAM MRR implementation: use DS-MRR
1795
***************************************************************************/
1797
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
1798
uint n_ranges, uint mode,
1799
HANDLER_BUFFER *buf)
1801
return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
1802
seq, seq_init_param, n_ranges, mode, buf);
1805
int ha_myisam::multi_range_read_next(char **range_info)
1807
return ds_mrr.dsmrr_next(this, range_info);
1810
ha_rows ha_myisam::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
1811
void *seq_init_param,
1812
uint n_ranges, uint *bufsz,
1813
uint *flags, COST_VECT *cost)
1816
This call is here because there is no location where this->table would
1818
TODO: consider moving it into some per-query initialization call.
1820
ds_mrr.init(this, table);
1821
return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
1825
int ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
1826
uint *bufsz, uint *flags, COST_VECT *cost)
1828
ds_mrr.init(this, table);
1829
return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
1832
/* MyISAM MRR implementation ends */
1835
/* Index condition pushdown implementation*/
1838
Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
1840
pushed_idx_cond_keyno= keyno_arg;
1841
pushed_idx_cond= idx_cond_arg;
1842
in_range_check_pushed_down= true;
1843
if (active_index == pushed_idx_cond_keyno)
1844
mi_set_index_cond_func(file, index_cond_func_myisam, this);
1849
mysql_declare_plugin(myisam)
1851
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1533
static void sys_var_key_cache_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1535
uint32_t tmp= *static_cast<const uint32_t *>(save);
1538
struct my_option option_limits;
1539
plugin_opt_set_limits(&option_limits, var);
1540
option_limits.name= "myisam_key_cache_size";
1542
if (dflt_key_cache->in_init)
1545
myisam_key_cache_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1547
/* If key cache didn't existed initialize it, else resize it */
1548
dflt_key_cache->in_init= 1;
1550
error= ! resize_key_cache(dflt_key_cache,
1551
myisam_key_cache_block_size,
1552
myisam_key_cache_size,
1553
myisam_key_cache_division_limit,
1554
myisam_key_cache_age_threshold);
1555
dflt_key_cache->in_init= 0;
1558
static void sys_var_key_cache_block_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1560
uint32_t tmp= *static_cast<const uint32_t *>(save);
1563
struct my_option option_limits;
1564
plugin_opt_set_limits(&option_limits, var);
1565
option_limits.name= "myisam_key_cache_block_size";
1567
if (dflt_key_cache->in_init)
1570
myisam_key_cache_block_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1572
dflt_key_cache->in_init= 1;
1574
error= ! resize_key_cache(dflt_key_cache,
1575
myisam_key_cache_block_size,
1576
myisam_key_cache_size,
1577
myisam_key_cache_division_limit,
1578
myisam_key_cache_age_threshold);
1580
dflt_key_cache->in_init= 0;
1583
static void sys_var_key_cache_division_limit_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1585
uint32_t tmp= *static_cast<const uint32_t *>(save);
1588
struct my_option option_limits;
1589
plugin_opt_set_limits(&option_limits, var);
1590
option_limits.name= "myisam_key_cache_division_limit";
1592
if (dflt_key_cache->in_init)
1595
myisam_key_cache_division_limit= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1597
dflt_key_cache->in_init= 1;
1599
error= ! resize_key_cache(dflt_key_cache,
1600
myisam_key_cache_block_size,
1601
myisam_key_cache_size,
1602
myisam_key_cache_division_limit,
1603
myisam_key_cache_age_threshold);
1605
dflt_key_cache->in_init= 0;
1608
static void sys_var_key_cache_age_threshold_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1610
uint32_t tmp= *static_cast<const uint32_t *>(save);
1613
struct my_option option_limits;
1614
plugin_opt_set_limits(&option_limits, var);
1615
option_limits.name= "myisam_key_cache_age_threshold";
1617
if (dflt_key_cache->in_init)
1620
myisam_key_cache_age_threshold= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1622
dflt_key_cache->in_init= 1;
1624
error= ! resize_key_cache(dflt_key_cache,
1625
myisam_key_cache_block_size,
1626
myisam_key_cache_size,
1627
myisam_key_cache_division_limit,
1628
myisam_key_cache_age_threshold);
1630
dflt_key_cache->in_init= 0;
1633
static DRIZZLE_SYSVAR_UINT(key_cache_block_size,
1634
myisam_key_cache_block_size,
1635
PLUGIN_VAR_RQCMDARG,
1636
N_("Block size to be used for MyISAM index pages."),
1638
sys_var_key_cache_block_size_update,
1639
KEY_CACHE_BLOCK_SIZE,
1644
static DRIZZLE_SYSVAR_UINT(key_cache_age_threshold, myisam_key_cache_age_threshold,
1645
PLUGIN_VAR_RQCMDARG,
1646
N_("This characterizes the number of hits a hot block has to be untouched "
1647
"until it is considered aged enough to be downgraded to a warm block. "
1648
"This specifies the percentage ratio of that number of hits to the "
1649
"total number of blocks in key cache"),
1651
sys_var_key_cache_age_threshold_update,
1657
static DRIZZLE_SYSVAR_UINT(key_cache_division_limit, myisam_key_cache_division_limit,
1658
PLUGIN_VAR_RQCMDARG,
1659
N_("The minimum percentage of warm blocks in key cache"),
1661
sys_var_key_cache_division_limit_update,
1667
static DRIZZLE_SYSVAR_UINT(key_cache_size,
1668
myisam_key_cache_size,
1669
PLUGIN_VAR_RQCMDARG,
1670
N_("The size of the buffer used for index blocks for MyISAM tables. "
1671
"Increase this to get better index handling (for all reads and multiple "
1672
"writes) to as much as you can afford;"),
1674
sys_var_key_cache_size_update,
1680
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
1681
PLUGIN_VAR_RQCMDARG,
1682
N_("Number of threads to use when repairing MyISAM tables. The value of "
1683
"1 disables parallel repair."),
1684
NULL, NULL, 1, 1, UINT32_MAX, 0);
1686
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1687
PLUGIN_VAR_RQCMDARG,
1688
N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
1689
NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
1691
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
1692
PLUGIN_VAR_RQCMDARG,
1693
N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
1694
NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
1696
extern uint32_t data_pointer_size;
1697
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
1698
PLUGIN_VAR_RQCMDARG,
1699
N_("Default pointer size to be used for MyISAM tables."),
1700
NULL, NULL, 6, 2, 7, 0);
1702
static drizzle_sys_var* sys_variables[]= {
1703
DRIZZLE_SYSVAR(key_cache_block_size),
1704
DRIZZLE_SYSVAR(key_cache_size),
1705
DRIZZLE_SYSVAR(key_cache_division_limit),
1706
DRIZZLE_SYSVAR(key_cache_age_threshold),
1707
DRIZZLE_SYSVAR(repair_threads),
1708
DRIZZLE_SYSVAR(max_sort_file_size),
1709
DRIZZLE_SYSVAR(sort_buffer_size),
1710
DRIZZLE_SYSVAR(data_pointer_size),
1715
DRIZZLE_DECLARE_PLUGIN