14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19
#include "drizzled/internal/my_bit.h"
20
#include "myisampack.h"
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>
21
26
#include "ha_myisam.h"
22
#include "myisam_priv.h"
23
#include "drizzled/option.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"
37
#include "drizzled/plugin/daemon.h"
45
using namespace drizzled;
47
extern pthread_mutex_t LOCK_global_system_variables;
48
static const string engine_name("MyISAM");
50
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
52
static uint32_t repair_threads;
53
static uint32_t myisam_key_cache_block_size;
54
static uint32_t myisam_key_cache_size;
55
static uint32_t myisam_key_cache_division_limit;
56
static uint32_t myisam_key_cache_age_threshold;
57
static uint64_t max_sort_file_size;
58
static uint64_t sort_buffer_size;
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", NULL};
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", NULL};
40
TYPELIB myisam_stats_method_typelib= {
41
array_elements(myisam_stats_method_names) - 1, "",
42
myisam_stats_method_names, NULL};
60
45
/*****************************************************************************
62
47
*****************************************************************************/
64
static const char *ha_myisam_exts[] = {
70
class MyisamEngine : public plugin::StorageEngine
73
MyisamEngine(const MyisamEngine&);
74
MyisamEngine& operator=(const MyisamEngine&);
76
explicit MyisamEngine(string name_arg) :
77
plugin::StorageEngine(name_arg,
78
HTON_CAN_INDEX_BLOBS |
79
HTON_STATS_RECORDS_IS_EXACT |
85
HTON_SKIP_STORE_LOCK |
88
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
91
virtual ~MyisamEngine()
93
pthread_mutex_destroy(&THR_LOCK_myisam);
94
end_key_cache(dflt_key_cache, 1); // Can never fail
96
mi_panic(HA_PANIC_CLOSE);
99
virtual Cursor *create(TableShare &table,
100
memory::Root *mem_root)
102
return new (mem_root) ha_myisam(*this, table);
105
const char **bas_ext() const {
106
return ha_myisam_exts;
109
int doCreateTable(Session&,
111
drizzled::TableIdentifier &identifier,
114
int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
116
int doDropTable(Session&, drizzled::TableIdentifier &identifier);
118
int doGetTableDefinition(Session& session,
119
drizzled::TableIdentifier &identifier,
120
message::Table &table_message);
122
/* Temp only engine, so do not return values. */
123
void doGetTableNames(CachedDirectory &, SchemaIdentifier &, set<string>&) { };
125
uint32_t max_supported_keys() const { return MI_MAX_KEY; }
126
uint32_t max_supported_key_length() const { return MI_MAX_KEY_LENGTH; }
127
uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
129
uint32_t index_flags(enum ha_key_alg) const
131
return (HA_READ_NEXT |
137
bool doDoesTableExist(Session& session, TableIdentifier &identifier);
139
void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
140
drizzled::SchemaIdentifier &schema_identifier,
141
drizzled::TableIdentifiers &set_of_identifiers);
144
void MyisamEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
145
drizzled::SchemaIdentifier&,
146
drizzled::TableIdentifiers&)
150
bool MyisamEngine::doDoesTableExist(Session &session, TableIdentifier &identifier)
152
return session.doesTableMessageExist(identifier);
155
int MyisamEngine::doGetTableDefinition(Session &session,
156
drizzled::TableIdentifier &identifier,
157
message::Table &table_message)
159
if (session.getTableMessage(identifier, table_message))
165
Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
168
static void mi_check_print_msg(MI_CHECK *, const char* ,
169
const char *, va_list )
49
static handler *myisam_create_handler(handlerton *hton,
53
return new (mem_root) ha_myisam(hton, table);
56
// collect errors printed by mi_check routines
58
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
59
const char *fmt, va_list args)
61
THD* thd = (THD*)param->thd;
62
Protocol *protocol= thd->protocol;
63
uint32_t 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,NULL) -
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",
513
442
void _mi_report_crashed(MI_INFO *file, const char *message,
514
443
const char *sfile, uint32_t sline)
516
Session *cur_session;
517
447
pthread_mutex_lock(&file->s->intern_lock);
518
if ((cur_session= file->in_use))
519
errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
520
cur_session->thread_id,
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,
523
errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
452
sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline);
525
errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
526
list<Session *>::iterator it= file->s->in_use->begin();
527
while (it != file->s->in_use->end())
454
sql_print_error("%s", message);
455
for (element= file->s->in_use; element; element= list_rest(element))
529
errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
457
sql_print_error("%s", "Unknown thread accessing table");
532
459
pthread_mutex_unlock(&file->s->intern_lock);
535
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
536
TableShare &table_arg)
537
: Cursor(engine_arg, table_arg),
539
can_enable_indexes(true),
543
Cursor *ha_myisam::clone(memory::Root *mem_root)
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 |
467
HA_BINLOG_ROW_CAPABLE |
468
HA_BINLOG_STMT_CAPABLE |
475
HA_STATS_RECORDS_IS_EXACT |
476
HA_NEED_READ_RANGE_BUFFER |
478
can_enable_indexes(1)
481
handler *ha_myisam::clone(MEM_ROOT *mem_root)
545
ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
483
ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
547
485
new_handler->file->state= file->state;
548
486
return new_handler;
551
const char *ha_myisam::index_type(uint32_t )
490
static const char *ha_myisam_exts[] = {
496
const char **ha_myisam::bas_ext() const
498
return ha_myisam_exts;
502
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
658
617
return mi_write(file,buf);
662
int ha_myisam::repair(Session *session, MI_CHECK ¶m, bool do_optimize)
665
uint32_t local_testflag= param.testflag;
620
int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
622
if (!file) return HA_ADMIN_INTERNAL_ERROR;
625
MYISAM_SHARE* share = file->s;
626
const char *old_proc_info= thd->get_proc_info();
628
thd_proc_info(thd, "Checking table");
629
myisamchk_init(¶m);
631
param.op_name = "check";
632
param.db_name= table->s->db.str;
633
param.table_name= table->alias;
634
param.testflag = check_opt->flags | T_CHECK | T_SILENT;
635
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
637
if (!(table->db_stat & HA_READ_ONLY))
638
param.testflag|= T_STATISTICS;
639
param.using_global_keycache = 1;
641
if (!mi_is_crashed(file) &&
642
(((param.testflag & T_CHECK_ONLY_CHANGED) &&
643
!(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
644
STATE_CRASHED_ON_REPAIR)) &&
645
share->state.open_count == 0) ||
646
((param.testflag & T_FAST) && (share->state.open_count ==
647
(uint) (share->global_changed ? 1 : 0)))))
648
return HA_ADMIN_ALREADY_DONE;
650
error = chk_status(¶m, file); // Not fatal
651
error = chk_size(¶m, file);
653
error |= chk_del(¶m, file, param.testflag);
655
error = chk_key(¶m, file);
658
if ((!(param.testflag & T_QUICK) &&
660
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
661
(param.testflag & (T_EXTEND | T_MEDIUM)))) ||
664
uint32_t old_testflag=param.testflag;
665
param.testflag|=T_MEDIUM;
666
if (!(error= init_io_cache(¶m.read_cache, file->dfile,
667
my_default_record_cache_size, READ_CACHE,
668
share->pack.header_length, 1, MYF(MY_WME))))
670
error= chk_data_link(¶m, file, param.testflag & T_EXTEND);
671
end_io_cache(&(param.read_cache));
673
param.testflag= old_testflag;
678
if ((share->state.changed & (STATE_CHANGED |
679
STATE_CRASHED_ON_REPAIR |
680
STATE_CRASHED | STATE_NOT_ANALYZED)) ||
681
(param.testflag & T_STATISTICS) ||
684
file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
685
pthread_mutex_lock(&share->intern_lock);
686
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
687
STATE_CRASHED_ON_REPAIR);
688
if (!(table->db_stat & HA_READ_ONLY))
689
error=update_state_info(¶m,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
691
pthread_mutex_unlock(&share->intern_lock);
692
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
696
else if (!mi_is_crashed(file) && !thd->killed)
698
mi_mark_crashed(file);
699
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
702
thd_proc_info(thd, old_proc_info);
703
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
708
analyze the key distribution in the table
709
As the table may be only locked for read, we have to take into account that
710
two threads may do an analyze at the same time!
713
int ha_myisam::analyze(THD *thd,
714
HA_CHECK_OPT* check_opt __attribute__((unused)))
718
MYISAM_SHARE* share = file->s;
720
myisamchk_init(¶m);
722
param.op_name= "analyze";
723
param.db_name= table->s->db.str;
724
param.table_name= table->alias;
725
param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
726
T_DONT_CHECK_CHECKSUM);
727
param.using_global_keycache = 1;
728
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
730
if (!(share->state.changed & STATE_NOT_ANALYZED))
731
return HA_ADMIN_ALREADY_DONE;
733
error = chk_key(¶m, file);
736
pthread_mutex_lock(&share->intern_lock);
737
error=update_state_info(¶m,file,UPDATE_STAT);
738
pthread_mutex_unlock(&share->intern_lock);
740
else if (!mi_is_crashed(file) && !thd->killed)
741
mi_mark_crashed(file);
742
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
746
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
750
ha_rows start_records;
752
if (!file) return HA_ADMIN_INTERNAL_ERROR;
754
myisamchk_init(¶m);
756
param.op_name= "repair";
757
param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
758
T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
759
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
760
param.sort_buffer_length= check_opt->sort_buffer_size;
761
start_records=file->state->records;
762
while ((error=repair(thd,param,0)) && param.retry_repair)
764
param.retry_repair=0;
765
if (test_all_bits(param.testflag,
766
(uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
768
param.testflag&= ~T_RETRY_WITHOUT_QUICK;
769
sql_print_information("Retrying repair of: '%s' without quick",
773
param.testflag&= ~T_QUICK;
774
if ((param.testflag & T_REP_BY_SORT))
776
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
777
sql_print_information("Retrying repair of: '%s' with keycache",
783
if (!error && start_records != file->state->records &&
784
!(check_opt->flags & T_VERY_SILENT))
786
char llbuff[22],llbuff2[22];
787
sql_print_information("Found %s of %s rows when repairing '%s'",
788
llstr(file->state->records, llbuff),
789
llstr(start_records, llbuff2),
795
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
798
if (!file) return HA_ADMIN_INTERNAL_ERROR;
801
myisamchk_init(¶m);
803
param.op_name= "optimize";
804
param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
805
T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
806
param.sort_buffer_length= check_opt->sort_buffer_size;
807
if ((error= repair(thd,param,1)) && param.retry_repair)
809
sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
810
my_errno, param.db_name, param.table_name);
811
param.testflag&= ~T_REP_BY_SORT;
812
error= repair(thd,param,1);
818
int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize)
821
uint32_t local_testflag=param.testflag;
666
822
bool optimize_done= !do_optimize, statistics_done=0;
667
const char *old_proc_info= session->get_proc_info();
823
const char *old_proc_info= thd->get_proc_info();
668
824
char fixed_name[FN_REFLEN];
669
825
MYISAM_SHARE* share = file->s;
670
826
ha_rows rows= file->state->records;
1225
1501
if (flag & HA_STATUS_CONST)
1227
TableShare *share= table->s;
1503
TABLE_SHARE *share= table->s;
1228
1504
stats.max_data_file_length= misam_info.max_data_file_length;
1229
1505
stats.max_index_file_length= misam_info.max_index_file_length;
1230
1506
stats.create_time= misam_info.create_time;
1231
1507
ref_length= misam_info.reflength;
1232
1508
share->db_options_in_use= misam_info.options;
1233
stats.block_size= myisam_key_cache_block_size; /* record block size */
1509
stats.block_size= myisam_block_size; /* record block size */
1235
1511
/* Update share */
1236
if (share->tmp_table == message::Table::STANDARD)
1512
if (share->tmp_table == NO_TMP_TABLE)
1237
1513
pthread_mutex_lock(&share->mutex);
1238
set_prefix(share->keys_in_use, share->keys);
1240
* Due to bug 394932 (32-bit solaris build failure), we need
1241
* to convert the uint64_t key_map member of the misam_info
1242
* structure in to a std::bitset so that we can logically and
1243
* it with the share->key_in_use key_map.
1246
string binary_key_map;
1247
uint64_t num= misam_info.key_map;
1249
* Convert the uint64_t to a binary
1250
* string representation of it.
1254
uint64_t bin_digit= num % 2;
1258
binary_key_map.append(ostr.str());
1260
* Now we have the binary string representation of the
1261
* flags, we need to fill that string representation out
1262
* with the appropriate number of bits. This is needed
1263
* since key_map is declared as a std::bitset of a certain bit
1264
* width that depends on the MAX_INDEXES variable.
1266
if (MAX_INDEXES <= 64)
1268
size_t len= 72 - binary_key_map.length();
1269
string all_zeros(len, '0');
1270
binary_key_map.insert(binary_key_map.begin(),
1276
size_t len= (MAX_INDEXES + 7) / 8 * 8;
1277
string all_zeros(len, '0');
1278
binary_key_map.insert(binary_key_map.begin(),
1282
key_map tmp_map(binary_key_map);
1283
share->keys_in_use&= tmp_map;
1284
share->keys_for_keyread&= share->keys_in_use;
1514
share->keys_in_use.set_prefix(share->keys);
1515
share->keys_in_use.intersect_extended(misam_info.key_map);
1516
share->keys_for_keyread.intersect(share->keys_in_use);
1285
1517
share->db_record_offset= misam_info.record_offset;
1286
1518
if (share->key_parts)
1287
1519
memcpy(table->key_info[0].rec_per_key,
1288
1520
misam_info.rec_per_key,
1289
1521
sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1290
if (share->tmp_table == message::Table::STANDARD)
1522
if (share->tmp_table == NO_TMP_TABLE)
1291
1523
pthread_mutex_unlock(&share->mutex);
1340
1576
return mi_delete_all_rows(file);
1343
int MyisamEngine::doDropTable(Session &session,
1344
drizzled::TableIdentifier &identifier)
1579
int ha_myisam::delete_table(const char *name)
1346
session.removeTableMessage(identifier);
1348
return mi_delete_table(identifier.getPath().c_str());
1581
return mi_delete_table(name);
1352
int ha_myisam::external_lock(Session *session, int lock_type)
1585
int ha_myisam::external_lock(THD *thd, int lock_type)
1354
file->in_use= session;
1587
file->in_use.data= thd;
1355
1588
return mi_lock_database(file, !table->s->tmp_table ?
1356
1589
lock_type : ((lock_type == F_UNLCK) ?
1357
1590
F_UNLCK : F_EXTRA_LCK));
1360
int MyisamEngine::doCreateTable(Session &session,
1362
drizzled::TableIdentifier &identifier,
1363
message::Table& create_proto)
1593
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
1595
enum thr_lock_type lock_type)
1597
if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
1598
file->lock.type=lock_type;
1603
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
1605
ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
1606
if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
1608
create_info->auto_increment_value= stats.auto_increment_value;
1610
create_info->data_file_name=data_file_name;
1611
create_info->index_file_name=index_file_name;
1615
int ha_myisam::create(const char *name, register Table *table_arg,
1616
HA_CREATE_INFO *ha_create_info)
1366
uint32_t create_flags= 0, create_records;
1619
uint32_t create_flags= 0, records;
1367
1620
char buff[FN_REFLEN];
1368
1621
MI_KEYDEF *keydef;
1369
1622
MI_COLUMNDEF *recinfo;
1370
1623
MI_CREATE_INFO create_info;
1371
TableShare *share= table_arg.s;
1624
TABLE_SHARE *share= table_arg->s;
1372
1625
uint32_t options= share->db_options_in_use;
1373
if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1626
if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1627
return(error); /* purecov: inspected */
1375
1628
memset(&create_info, 0, sizeof(create_info));
1376
create_info.max_rows= create_proto.options().max_rows();
1377
create_info.reloc_rows= create_proto.options().min_rows();
1629
create_info.max_rows= share->max_rows;
1630
create_info.reloc_rows= share->min_rows;
1378
1631
create_info.with_auto_increment= share->next_number_key_offset == 0;
1379
create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1380
create_proto.options().auto_increment_value() -1 :
1632
create_info.auto_increment= (ha_create_info->auto_increment_value ?
1633
ha_create_info->auto_increment_value -1 :
1382
create_info.data_file_length= (create_proto.options().max_rows() *
1383
create_proto.options().avg_row_length());
1384
create_info.data_file_name= NULL;
1385
create_info.index_file_name= NULL;
1635
create_info.data_file_length= ((uint64_t) share->max_rows *
1636
share->avg_row_length);
1637
create_info.data_file_name= ha_create_info->data_file_name;
1638
create_info.index_file_name= ha_create_info->index_file_name;
1386
1639
create_info.language= share->table_charset->number;
1388
if (create_proto.type() == message::Table::TEMPORARY)
1641
if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1389
1642
create_flags|= HA_CREATE_TMP_TABLE;
1643
if (ha_create_info->options & HA_CREATE_KEEP_FILES)
1644
create_flags|= HA_CREATE_KEEP_FILES;
1390
1645
if (options & HA_OPTION_PACK_RECORD)
1391
1646
create_flags|= HA_PACK_RECORD;
1647
if (options & HA_OPTION_CHECKSUM)
1648
create_flags|= HA_CREATE_CHECKSUM;
1649
if (options & HA_OPTION_DELAY_KEY_WRITE)
1650
create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1393
/* TODO: Check that the following internal::fn_format is really needed */
1394
error= mi_create(internal::fn_format(buff, identifier.getPath().c_str(), "", "",
1395
MY_UNPACK_FILENAME|MY_APPEND_EXT),
1652
/* TODO: Check that the following fn_format is really needed */
1653
error= mi_create(fn_format(buff, name, "", "",
1654
MY_UNPACK_FILENAME|MY_APPEND_EXT),
1396
1655
share->keys, keydef,
1397
create_records, recinfo,
1398
1657
0, (MI_UNIQUEDEF*) 0,
1399
1658
&create_info, create_flags);
1400
1659
free((unsigned char*) recinfo);
1402
session.storeTableMessage(identifier, create_proto);
1408
int MyisamEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
1664
int ha_myisam::rename_table(const char * from, const char * to)
1410
session.renameTableMessage(from, to);
1412
return mi_rename(from.getPath().c_str(), to.getPath().c_str());
1666
return mi_rename(from,to);
1416
void ha_myisam::get_auto_increment(uint64_t ,
1670
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1671
uint64_t increment __attribute__((unused)),
1672
uint64_t nb_desired_values __attribute__((unused)),
1419
1673
uint64_t *first_value,
1420
1674
uint64_t *nb_reserved_values)
1499
1753
return (uint)file->state->checksum;
1502
static MyisamEngine *engine= NULL;
1504
static int myisam_init(plugin::Context &context)
1506
engine= new MyisamEngine(engine_name);
1507
context.add(engine);
1509
/* call ha_init_key_cache() on all key caches to init them */
1510
int 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 */
1757
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1758
uint32_t table_changes)
1760
uint32_t options= table->s->db_options_in_use;
1762
if (info->auto_increment_value != stats.auto_increment_value ||
1763
info->data_file_name != data_file_name ||
1764
info->index_file_name != index_file_name ||
1765
table_changes == IS_EQUAL_NO ||
1766
table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
1767
return COMPATIBLE_DATA_NO;
1769
if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1770
HA_OPTION_DELAY_KEY_WRITE)) !=
1771
(info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1772
HA_OPTION_DELAY_KEY_WRITE)))
1773
return COMPATIBLE_DATA_NO;
1774
return COMPATIBLE_DATA_YES;
1777
int myisam_deinit(void *hton __attribute__((unused)))
1779
return mi_panic(HA_PANIC_CLOSE);
1782
static int myisam_init(void *p)
1784
handlerton *myisam_hton;
1786
myisam_hton= (handlerton *)p;
1787
myisam_hton->state= SHOW_OPTION_YES;
1788
myisam_hton->create= myisam_create_handler;
1789
myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1523
static void sys_var_key_cache_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1525
uint32_t tmp= *static_cast<const uint32_t *>(save);
1528
struct option option_limits;
1529
plugin_opt_set_limits(&option_limits, var);
1530
option_limits.name= "myisam_key_cache_size";
1532
if (dflt_key_cache->in_init)
1535
myisam_key_cache_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1537
/* If key cache didn't existed initialize it, else resize it */
1538
dflt_key_cache->in_init= 1;
1540
error= ! resize_key_cache(dflt_key_cache,
1541
myisam_key_cache_block_size,
1542
myisam_key_cache_size,
1543
myisam_key_cache_division_limit,
1544
myisam_key_cache_age_threshold);
1545
dflt_key_cache->in_init= 0;
1548
static void sys_var_key_cache_block_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1550
uint32_t tmp= *static_cast<const uint32_t *>(save);
1553
struct option option_limits;
1554
plugin_opt_set_limits(&option_limits, var);
1555
option_limits.name= "myisam_key_cache_block_size";
1557
if (dflt_key_cache->in_init)
1560
myisam_key_cache_block_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1562
dflt_key_cache->in_init= 1;
1564
error= ! resize_key_cache(dflt_key_cache,
1565
myisam_key_cache_block_size,
1566
myisam_key_cache_size,
1567
myisam_key_cache_division_limit,
1568
myisam_key_cache_age_threshold);
1570
dflt_key_cache->in_init= 0;
1573
static void sys_var_key_cache_division_limit_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1575
uint32_t tmp= *static_cast<const uint32_t *>(save);
1578
struct option option_limits;
1579
plugin_opt_set_limits(&option_limits, var);
1580
option_limits.name= "myisam_key_cache_division_limit";
1582
if (dflt_key_cache->in_init)
1585
myisam_key_cache_division_limit= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1587
dflt_key_cache->in_init= 1;
1589
error= ! resize_key_cache(dflt_key_cache,
1590
myisam_key_cache_block_size,
1591
myisam_key_cache_size,
1592
myisam_key_cache_division_limit,
1593
myisam_key_cache_age_threshold);
1595
dflt_key_cache->in_init= 0;
1598
static void sys_var_key_cache_age_threshold_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1600
uint32_t tmp= *static_cast<const uint32_t *>(save);
1603
struct option option_limits;
1604
plugin_opt_set_limits(&option_limits, var);
1605
option_limits.name= "myisam_key_cache_age_threshold";
1607
if (dflt_key_cache->in_init)
1610
myisam_key_cache_age_threshold= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1612
dflt_key_cache->in_init= 1;
1614
error= ! resize_key_cache(dflt_key_cache,
1615
myisam_key_cache_block_size,
1616
myisam_key_cache_size,
1617
myisam_key_cache_division_limit,
1618
myisam_key_cache_age_threshold);
1620
dflt_key_cache->in_init= 0;
1623
static DRIZZLE_SYSVAR_UINT(key_cache_block_size,
1624
myisam_key_cache_block_size,
1625
PLUGIN_VAR_RQCMDARG,
1626
N_("Block size to be used for MyISAM index pages."),
1628
sys_var_key_cache_block_size_update,
1629
KEY_CACHE_BLOCK_SIZE,
1634
static DRIZZLE_SYSVAR_UINT(key_cache_age_threshold, myisam_key_cache_age_threshold,
1635
PLUGIN_VAR_RQCMDARG,
1636
N_("This characterizes the number of hits a hot block has to be untouched "
1637
"until it is considered aged enough to be downgraded to a warm block. "
1638
"This specifies the percentage ratio of that number of hits to the "
1639
"total number of blocks in key cache"),
1641
sys_var_key_cache_age_threshold_update,
1647
static DRIZZLE_SYSVAR_UINT(key_cache_division_limit, myisam_key_cache_division_limit,
1648
PLUGIN_VAR_RQCMDARG,
1649
N_("The minimum percentage of warm blocks in key cache"),
1651
sys_var_key_cache_division_limit_update,
1657
static DRIZZLE_SYSVAR_UINT(key_cache_size,
1658
myisam_key_cache_size,
1659
PLUGIN_VAR_RQCMDARG,
1660
N_("The size of the buffer used for index blocks for MyISAM tables. "
1661
"Increase this to get better index handling (for all reads and multiple "
1662
"writes) to as much as you can afford;"),
1664
sys_var_key_cache_size_update,
1670
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
1671
PLUGIN_VAR_RQCMDARG,
1672
N_("Number of threads to use when repairing MyISAM tables. The value of "
1673
"1 disables parallel repair."),
1674
NULL, NULL, 1, 1, UINT32_MAX, 0);
1676
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1677
PLUGIN_VAR_RQCMDARG,
1678
N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
1679
NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
1681
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
1682
PLUGIN_VAR_RQCMDARG,
1683
N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
1684
NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
1686
extern uint32_t data_pointer_size;
1687
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
1688
PLUGIN_VAR_RQCMDARG,
1689
N_("Default pointer size to be used for MyISAM tables."),
1690
NULL, NULL, 6, 2, 7, 0);
1692
static drizzle_sys_var* sys_variables[]= {
1693
DRIZZLE_SYSVAR(key_cache_block_size),
1694
DRIZZLE_SYSVAR(key_cache_size),
1695
DRIZZLE_SYSVAR(key_cache_division_limit),
1696
DRIZZLE_SYSVAR(key_cache_age_threshold),
1697
DRIZZLE_SYSVAR(repair_threads),
1698
DRIZZLE_SYSVAR(max_sort_file_size),
1699
DRIZZLE_SYSVAR(sort_buffer_size),
1700
DRIZZLE_SYSVAR(data_pointer_size),
1705
DRIZZLE_DECLARE_PLUGIN
1795
/****************************************************************************
1796
* MyISAM MRR implementation: use DS-MRR
1797
***************************************************************************/
1799
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
1800
uint32_t n_ranges, uint32_t mode,
1801
HANDLER_BUFFER *buf)
1803
return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
1804
seq, seq_init_param, n_ranges, mode, buf);
1807
int ha_myisam::multi_range_read_next(char **range_info)
1809
return ds_mrr.dsmrr_next(this, range_info);
1812
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
1813
void *seq_init_param,
1814
uint32_t n_ranges, uint32_t *bufsz,
1815
uint32_t *flags, COST_VECT *cost)
1818
This call is here because there is no location where this->table would
1820
TODO: consider moving it into some per-query initialization call.
1822
ds_mrr.init(this, table);
1823
return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
1827
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
1828
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
1830
ds_mrr.init(this, table);
1831
return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
1834
/* MyISAM MRR implementation ends */
1837
/* Index condition pushdown implementation*/
1840
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
1842
pushed_idx_cond_keyno= keyno_arg;
1843
pushed_idx_cond= idx_cond_arg;
1844
in_range_check_pushed_down= true;
1845
if (active_index == pushed_idx_cond_keyno)
1846
mi_set_index_cond_func(file, index_cond_func_myisam, this);
1851
mysql_declare_plugin(myisam)
1853
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1711
1857
"Default engine as of MySQL 3.23 with great performance",
1712
1858
PLUGIN_LICENSE_GPL,
1713
1859
myisam_init, /* Plugin Init */
1714
sys_variables, /* system variables */
1860
myisam_deinit, /* Plugin Deinit */
1861
NULL, /* status variables */
1862
NULL, /* system variables */
1715
1863
NULL /* config options */
1717
DRIZZLE_DECLARE_PLUGIN_END;
1865
mysql_declare_plugin_end;