14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
#define DRIZZLE_SERVER 1
20
#include <drizzled/server_includes.h>
21
#include <mysys/my_bit.h>
17
#ifdef USE_PRAGMA_IMPLEMENTATION
18
#pragma implementation // gcc: Class implementation
21
#define MYSQL_SERVER 1
22
#include "mysql_priv.h"
23
#include <mysql/plugin.h>
22
26
#include <myisampack.h>
23
27
#include "ha_myisam.h"
24
29
#include "myisamdef.h"
25
#include <drizzled/drizzled_error_messages.h>
26
#include <drizzled/util/test.h>
28
32
ulong myisam_recover_options= HA_RECOVER_NONE;
30
34
/* bits in myisam_recover_options */
31
35
const char *myisam_recover_names[] =
32
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
36
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
33
37
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
34
38
myisam_recover_names, NULL};
36
40
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
37
"nulls_ignored", NULL};
41
"nulls_ignored", NullS};
38
42
TYPELIB myisam_stats_method_typelib= {
39
43
array_elements(myisam_stats_method_names) - 1, "",
40
44
myisam_stats_method_names, NULL};
59
63
THD* thd = (THD*)param->thd;
60
64
Protocol *protocol= thd->protocol;
61
uint32_t length, msg_length;
65
uint length, msg_length;
62
66
char msgbuf[MI_MAX_MSG_BUF];
63
67
char name[NAME_LEN*2+2];
65
msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
69
msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
66
70
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
72
DBUG_PRINT(msg_type,("message: %s",msgbuf));
68
74
if (!thd->vio_ok())
70
76
sql_print_error(msgbuf);
126
int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
127
MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
132
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
133
MI_COLUMNDEF **recinfo_out, uint *records_out)
129
uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
135
uint i, j, recpos, minpos, fieldpos, temp_length, length;
130
136
enum ha_base_keytype type= HA_KEYTYPE_BINARY;
131
unsigned char *record;
133
139
MI_KEYDEF *keydef;
134
140
MI_COLUMNDEF *recinfo, *recinfo_pos;
135
141
HA_KEYSEG *keyseg;
136
142
TABLE_SHARE *share= table_arg->s;
137
uint32_t options= share->db_options_in_use;
143
uint options= share->db_options_in_use;
144
DBUG_ENTER("table2myisam");
138
145
if (!(my_multi_malloc(MYF(MY_WME),
139
146
recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
140
147
keydef_out, share->keys * sizeof(MI_KEYDEF),
142
149
(share->key_parts + share->keys) * sizeof(HA_KEYSEG),
144
return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
151
DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
145
152
keydef= *keydef_out;
146
153
recinfo= *recinfo_out;
147
154
pos= table_arg->key_info;
148
155
for (i= 0; i < share->keys; i++, pos++)
150
keydef[i].flag= ((uint16_t) pos->flags & (HA_NOSAME));
151
keydef[i].key_alg= HA_KEY_ALG_BTREE;
157
keydef[i].flag= ((uint16) pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
158
keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
159
(pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
152
161
keydef[i].block_length= pos->block_size;
153
162
keydef[i].seg= keyseg;
154
163
keydef[i].keysegs= pos->key_parts;
189
201
keydef[i].seg[j].null_bit= field->null_bit;
190
202
keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
191
(unsigned char*) table_arg->record[0]);
203
(uchar*) table_arg->record[0]);
195
207
keydef[i].seg[j].null_bit= 0;
196
208
keydef[i].seg[j].null_pos= 0;
198
if (field->type() == DRIZZLE_TYPE_BLOB)
210
if (field->type() == MYSQL_TYPE_BLOB ||
211
field->type() == MYSQL_TYPE_GEOMETRY)
200
213
keydef[i].seg[j].flag|= HA_BLOB_PART;
201
214
/* save number of bytes used to pack length */
202
215
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
203
216
share->blob_ptr_size);
218
else if (field->type() == MYSQL_TYPE_BIT)
220
keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
221
keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
222
keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
223
(uchar*) table_arg->record[0]);
206
226
keyseg+= pos->key_parts;
256
DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d",
257
(long) found, recpos, minpos, length));
236
258
if (recpos != minpos)
237
259
{ // Reserved space (Null bits?)
238
memset(recinfo_pos, 0, sizeof(*recinfo_pos));
260
bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
239
261
recinfo_pos->type= (int) FIELD_NORMAL;
240
recinfo_pos++->length= (uint16_t) (minpos - recpos);
262
recinfo_pos++->length= (uint16) (minpos - recpos);
245
267
if (found->flags & BLOB_FLAG)
246
268
recinfo_pos->type= (int) FIELD_BLOB;
247
else if (found->type() == DRIZZLE_TYPE_VARCHAR)
269
else if (found->type() == MYSQL_TYPE_VARCHAR)
248
270
recinfo_pos->type= FIELD_VARCHAR;
249
271
else if (!(options & HA_OPTION_PACK_RECORD))
250
272
recinfo_pos->type= (int) FIELD_NORMAL;
251
273
else if (found->zero_pack())
252
274
recinfo_pos->type= (int) FIELD_SKIP_ZERO;
254
recinfo_pos->type= (int) ((length <= 3) ? FIELD_NORMAL : FIELD_SKIP_PRESPACE);
276
recinfo_pos->type= (int) ((length <= 3 ||
277
(found->flags & ZEROFILL_FLAG)) ?
279
found->type() == MYSQL_TYPE_STRING ||
280
found->type() == MYSQL_TYPE_VAR_STRING ?
281
FIELD_SKIP_ENDSPACE :
282
FIELD_SKIP_PRESPACE);
255
283
if (found->null_ptr)
257
285
recinfo_pos->null_bit= found->null_bit;
258
286
recinfo_pos->null_pos= (uint) (found->null_ptr -
259
(unsigned char*) table_arg->record[0]);
287
(uchar*) table_arg->record[0]);
263
291
recinfo_pos->null_bit= 0;
264
292
recinfo_pos->null_pos= 0;
266
(recinfo_pos++)->length= (uint16_t) length;
294
(recinfo_pos++)->length= (uint16) length;
267
295
recpos= minpos + length;
296
DBUG_PRINT("loop", ("length: %d type: %d",
297
recinfo_pos[-1].length,recinfo_pos[-1].type));
269
299
*records_out= (uint) (recinfo_pos - recinfo);
314
344
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
315
uint32_t t1_keys, uint32_t t1_recs,
345
uint t1_keys, uint t1_recs,
316
346
MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
317
uint32_t t2_keys, uint32_t t2_recs, bool strict)
347
uint t2_keys, uint t2_recs, bool strict)
350
DBUG_ENTER("check_definition");
320
351
if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
353
DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
324
357
if (t1_recs != t2_recs)
359
DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
328
363
for (i= 0; i < t1_keys; i++)
330
365
HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
331
366
HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
367
if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
369
else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
370
t2_keyinfo[i].flag & HA_FULLTEXT)
372
DBUG_PRINT("error", ("Key %d has different definition", i));
373
DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
374
test(t1_keyinfo[i].flag & HA_FULLTEXT),
375
test(t2_keyinfo[i].flag & HA_FULLTEXT)));
378
if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
380
else if (t1_keyinfo[i].flag & HA_SPATIAL ||
381
t2_keyinfo[i].flag & HA_SPATIAL)
383
DBUG_PRINT("error", ("Key %d has different definition", i));
384
DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
385
test(t1_keyinfo[i].flag & HA_SPATIAL),
386
test(t2_keyinfo[i].flag & HA_SPATIAL)));
332
389
if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
333
390
t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
392
DBUG_PRINT("error", ("Key %d has different definition", i));
393
DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
394
t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
395
DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
396
t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
337
399
for (j= t1_keyinfo[i].keysegs; j--;)
339
uint8_t t1_keysegs_j__type= t1_keysegs[j].type;
401
uint8 t1_keysegs_j__type= t1_keysegs[j].type;
342
404
Table migration from 4.1 to 5.1. In 5.1 a *TEXT key part is
360
422
t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
361
423
t1_keysegs[j].length != t2_keysegs[j].length)
425
DBUG_PRINT("error", ("Key segment %d (key %d) has different "
426
"definition", j, i));
427
DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
429
t1_keysegs[j].type, t1_keysegs[j].language,
430
t1_keysegs[j].null_bit, t1_keysegs[j].length));
431
DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
433
t2_keysegs[j].type, t2_keysegs[j].language,
434
t2_keysegs[j].null_bit, t2_keysegs[j].length));
379
452
t1_rec->length != t2_rec->length ||
380
453
t1_rec->null_bit != t2_rec->null_bit)
455
DBUG_PRINT("error", ("Field %d has different definition", i));
456
DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
457
t1_rec->type, t1_rec->length, t1_rec->null_bit));
458
DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
459
t2_rec->type, t2_rec->length, t2_rec->null_bit));
452
532
sql_print_error("%s", message);
453
533
for (element= file->s->in_use; element; element= list_rest(element))
455
sql_print_error("%s", "Unknown thread accessing table");
535
THD *thd= (THD*) element->data;
536
sql_print_error("%s", thd ? thd_security_context(thd, buf, sizeof(buf), 0)
537
: "Unknown thread accessing table");
457
539
pthread_mutex_unlock(&file->s->intern_lock);
462
545
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
463
546
:handler(hton, table_arg), file(0),
464
int_table_flags(HA_NULL_IN_KEY |
465
HA_BINLOG_ROW_CAPABLE |
466
HA_BINLOG_STMT_CAPABLE |
473
HA_STATS_RECORDS_IS_EXACT |
474
HA_NEED_READ_RANGE_BUFFER |
547
int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
548
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
549
HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
550
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
551
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
552
HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT |
553
HA_NEED_READ_RANGE_BUFFER | HA_MRR_CANT_SORT),
476
554
can_enable_indexes(1)
500
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
578
const char *ha_myisam::index_type(uint key_number)
580
return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
582
(table->key_info[key_number].flags & HA_SPATIAL) ?
584
(table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
505
589
/* Name is here without an extension */
506
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
590
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
508
592
MI_KEYDEF *keyinfo;
509
593
MI_COLUMNDEF *recinfo= 0;
514
598
If the user wants to have memory mapped data files, add an
549
635
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
550
mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
636
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
552
638
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
553
639
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
554
mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
640
VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
555
641
if (!table->s->db_record_offset)
556
642
int_table_flags|=HA_REC_NOT_IN_SEQ;
557
643
if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
816
901
int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize)
819
uint32_t local_testflag=param.testflag;
904
uint local_testflag=param.testflag;
820
905
bool optimize_done= !do_optimize, statistics_done=0;
821
const char *old_proc_info= thd->get_proc_info();
906
const char *old_proc_info=thd->proc_info;
822
907
char fixed_name[FN_REFLEN];
823
908
MYISAM_SHARE* share = file->s;
824
909
ha_rows rows= file->state->records;
910
DBUG_ENTER("ha_myisam::repair");
827
913
Normally this method is entered with a properly opened table. If the
877
963
/* TODO: respect myisam_repair_threads variable */
878
snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
879
thd->set_proc_info(buf);
964
my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
965
thd_proc_info(thd, buf);
880
966
error = mi_repair_parallel(¶m, file, fixed_name,
881
967
param.testflag & T_QUICK);
882
thd->set_proc_info("Repair done"); // to reset proc_info, as
968
thd_proc_info(thd, "Repair done"); // to reset proc_info, as
883
969
// it was pointing to local buffer
887
thd->set_proc_info("Repair by sorting");
973
thd_proc_info(thd, "Repair by sorting");
888
974
error = mi_repair_by_sort(¶m, file, fixed_name,
889
975
param.testflag & T_QUICK);
894
thd->set_proc_info("Repair with keycache");
980
thd_proc_info(thd, "Repair with keycache");
895
981
param.testflag &= ~T_REP_BY_SORT;
896
982
error= mi_repair(¶m, file, fixed_name,
897
983
param.testflag & T_QUICK);
976
1062
const char *errmsg= 0;
977
1063
int error= HA_ADMIN_OK;
979
TableList *table_list= table->pos_in_table_list;
1065
TABLE_LIST *table_list= table->pos_in_table_list;
1066
DBUG_ENTER("ha_myisam::assign_to_keycache");
981
1068
table->keys_in_use_for_query.clear_all();
983
1070
if (table_list->process_index_hints(table))
984
return(HA_ADMIN_FAILED);
1071
DBUG_RETURN(HA_ADMIN_FAILED);
985
1072
map= ~(uint64_t) 0;
986
1073
if (!table->keys_in_use_for_query.is_clear_all())
987
1074
/* use all keys if there's no list specified by the user through hints */
988
map= table->keys_in_use_for_query.to_uint64_t();
1075
map= table->keys_in_use_for_query.to_ulonglong();
990
1077
if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
992
1079
char buf[STRING_BUFFER_USUAL_SIZE];
993
snprintf(buf, sizeof(buf),
1080
my_snprintf(buf, sizeof(buf),
994
1081
"Failed to flush to index file (errno: %d)", error);
996
1083
error= HA_ADMIN_CORRUPT;
1008
1095
param.testflag= 0;
1009
1096
mi_check_print_error(¶m, errmsg);
1103
Preload pages of the index file for a table into the key cache.
1106
int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
1111
TABLE_LIST *table_list= table->pos_in_table_list;
1112
my_bool ignore_leaves= table_list->ignore_leaves;
1113
char buf[ERRMSGSIZE+20];
1115
DBUG_ENTER("ha_myisam::preload_keys");
1117
table->keys_in_use_for_query.clear_all();
1119
if (table_list->process_index_hints(table))
1120
DBUG_RETURN(HA_ADMIN_FAILED);
1123
/* Check validity of the index references */
1124
if (!table->keys_in_use_for_query.is_clear_all())
1125
/* use all keys if there's no list specified by the user through hints */
1126
map= table->keys_in_use_for_query.to_ulonglong();
1128
mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
1129
(void *) &thd->variables.preload_buff_size);
1131
if ((error= mi_preload(file, map, ignore_leaves)))
1134
case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
1135
errmsg= "Indexes use different block sizes";
1137
case HA_ERR_OUT_OF_MEM:
1138
errmsg= "Failed to allocate buffer";
1141
my_snprintf(buf, ERRMSGSIZE,
1142
"Failed to read from index file (errno: %d)", my_errno);
1145
error= HA_ADMIN_FAILED;
1149
DBUG_RETURN(HA_ADMIN_OK);
1154
myisamchk_init(¶m);
1156
param.op_name= "preload_keys";
1157
param.db_name= table->s->db.str;
1158
param.table_name= table->s->table_name.str;
1160
mi_check_print_error(¶m, errmsg);
1193
1347
can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
1194
1348
file->s->base.keys);
1197
Only disable old index if the table was empty and we are inserting
1199
We should not do this for only a few rows as this is slower and
1200
we don't want to update the key statistics based of only a few rows.
1202
if (file->state->records == 0 && can_enable_indexes &&
1203
(!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
1204
mi_disable_non_unique_index(file,rows);
1350
if (!(specialflag & SPECIAL_SAFE_MODE))
1353
Only disable old index if the table was empty and we are inserting
1355
We should not do this for only a few rows as this is slower and
1356
we don't want to update the key statistics based of only a few rows.
1358
if (file->state->records == 0 && can_enable_indexes &&
1359
(!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
1360
mi_disable_non_unique_index(file,rows);
1206
1362
if (!file->bulk_insert &&
1207
1363
(!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1209
1365
mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
1330
1483
active_index=MAX_KEY;
1331
1484
//pushed_idx_cond_keyno= MAX_KEY;
1332
1485
mi_set_index_cond_func(file, NULL, 0);
1333
in_range_check_pushed_down= false;
1486
in_range_check_pushed_down= FALSE;
1334
1487
ds_mrr.dsmrr_close();
1339
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
1492
int ha_myisam::index_read_map(uchar *buf, const uchar *key,
1340
1493
key_part_map keypart_map,
1341
1494
enum ha_rkey_function find_flag)
1343
assert(inited==INDEX);
1496
DBUG_ASSERT(inited==INDEX);
1344
1497
ha_statistic_increment(&SSV::ha_read_key_count);
1345
1498
int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1346
1499
table->status=error ? STATUS_NOT_FOUND: 0;
1350
int ha_myisam::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
1503
int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
1351
1504
key_part_map keypart_map,
1352
1505
enum ha_rkey_function find_flag)
1360
int ha_myisam::index_read_last_map(unsigned char *buf, const unsigned char *key,
1513
int ha_myisam::index_read_last_map(uchar *buf, const uchar *key,
1361
1514
key_part_map keypart_map)
1363
assert(inited==INDEX);
1516
DBUG_ENTER("ha_myisam::index_read_last");
1517
DBUG_ASSERT(inited==INDEX);
1364
1518
ha_statistic_increment(&SSV::ha_read_key_count);
1365
1519
int error=mi_rkey(file, buf, active_index, key, keypart_map,
1366
1520
HA_READ_PREFIX_LAST);
1367
1521
table->status=error ? STATUS_NOT_FOUND: 0;
1371
int ha_myisam::index_next(unsigned char *buf)
1525
int ha_myisam::index_next(uchar *buf)
1373
assert(inited==INDEX);
1527
DBUG_ASSERT(inited==INDEX);
1374
1528
ha_statistic_increment(&SSV::ha_read_next_count);
1375
1529
int error=mi_rnext(file,buf,active_index);
1376
1530
table->status=error ? STATUS_NOT_FOUND: 0;
1380
int ha_myisam::index_prev(unsigned char *buf)
1534
int ha_myisam::index_prev(uchar *buf)
1382
assert(inited==INDEX);
1536
DBUG_ASSERT(inited==INDEX);
1383
1537
ha_statistic_increment(&SSV::ha_read_prev_count);
1384
1538
int error=mi_rprev(file,buf, active_index);
1385
1539
table->status=error ? STATUS_NOT_FOUND: 0;
1389
int ha_myisam::index_first(unsigned char *buf)
1543
int ha_myisam::index_first(uchar *buf)
1391
assert(inited==INDEX);
1545
DBUG_ASSERT(inited==INDEX);
1392
1546
ha_statistic_increment(&SSV::ha_read_first_count);
1393
1547
int error=mi_rfirst(file, buf, active_index);
1394
1548
table->status=error ? STATUS_NOT_FOUND: 0;
1398
int ha_myisam::index_last(unsigned char *buf)
1552
int ha_myisam::index_last(uchar *buf)
1400
assert(inited==INDEX);
1554
DBUG_ASSERT(inited==INDEX);
1401
1555
ha_statistic_increment(&SSV::ha_read_last_count);
1402
1556
int error=mi_rlast(file, buf, active_index);
1403
1557
table->status=error ? STATUS_NOT_FOUND: 0;
1407
int ha_myisam::index_next_same(unsigned char *buf,
1408
const unsigned char *key __attribute__((unused)),
1409
uint32_t length __attribute__((unused)))
1561
int ha_myisam::index_next_same(uchar *buf,
1562
const uchar *key __attribute__((unused)),
1563
uint length __attribute__((unused)))
1412
assert(inited==INDEX);
1566
DBUG_ASSERT(inited==INDEX);
1413
1567
ha_statistic_increment(&SSV::ha_read_next_count);
1613
int ha_myisam::create(const char *name, register Table *table_arg,
1771
int ha_myisam::create(const char *name, register TABLE *table_arg,
1614
1772
HA_CREATE_INFO *ha_create_info)
1617
uint32_t create_flags= 0, records;
1775
uint create_flags= 0, records, i;
1618
1776
char buff[FN_REFLEN];
1619
1777
MI_KEYDEF *keydef;
1620
1778
MI_COLUMNDEF *recinfo;
1621
1779
MI_CREATE_INFO create_info;
1622
1780
TABLE_SHARE *share= table_arg->s;
1623
uint32_t options= share->db_options_in_use;
1781
uint options= share->db_options_in_use;
1782
DBUG_ENTER("ha_myisam::create");
1783
for (i= 0; i < share->keys; i++)
1785
if (table_arg->key_info[i].flags & HA_USES_PARSER)
1787
create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
1624
1791
if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1625
return(error); /* purecov: inspected */
1626
memset(&create_info, 0, sizeof(create_info));
1792
DBUG_RETURN(error); /* purecov: inspected */
1793
bzero((char*) &create_info, sizeof(create_info));
1627
1794
create_info.max_rows= share->max_rows;
1628
1795
create_info.reloc_rows= share->min_rows;
1629
1796
create_info.with_auto_increment= share->next_number_key_offset == 0;
1668
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1669
uint64_t increment __attribute__((unused)),
1670
uint64_t nb_desired_values __attribute__((unused)),
1835
void ha_myisam::get_auto_increment(uint64_t offset, uint64_t increment,
1836
uint64_t nb_desired_values,
1671
1837
uint64_t *first_value,
1672
1838
uint64_t *nb_reserved_values)
1676
unsigned char key[MI_MAX_KEY_LENGTH];
1842
uchar key[MI_MAX_KEY_LENGTH];
1678
1844
if (!table->s->next_number_key_offset)
1679
1845
{ // Autoincrement at key-start
1680
1846
ha_myisam::info(HA_STATUS_AUTO);
1681
1847
*first_value= stats.auto_increment_value;
1682
1848
/* MyISAM has only table-level lock, so reserves to +inf */
1683
*nb_reserved_values= UINT64_MAX;
1849
*nb_reserved_values= ULONGLONG_MAX;
1742
ha_rows ha_myisam::records_in_range(uint32_t inx, key_range *min_key,
1908
ha_rows ha_myisam::records_in_range(uint inx, key_range *min_key,
1743
1909
key_range *max_key)
1745
1911
return (ha_rows) mi_records_in_range(file, (int) inx, min_key, max_key);
1749
uint32_t ha_myisam::checksum() const
1915
int ha_myisam::ft_read(uchar *buf)
1922
thread_safe_increment(table->in_use->status_var.ha_read_next_count,
1923
&LOCK_status); // why ?
1925
error=ft_handler->please->read_next(ft_handler,(char*) buf);
1927
table->status=error ? STATUS_NOT_FOUND: 0;
1931
uint ha_myisam::checksum() const
1751
1933
return (uint)file->state->checksum;
1755
1937
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1756
uint32_t table_changes)
1758
uint32_t options= table->s->db_options_in_use;
1940
uint options= table->s->db_options_in_use;
1760
1942
if (info->auto_increment_value != stats.auto_increment_value ||
1761
1943
info->data_file_name != data_file_name ||
1807
1992
return ds_mrr.dsmrr_next(this, range_info);
1810
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
1995
ha_rows ha_myisam::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
1811
1996
void *seq_init_param,
1812
uint32_t n_ranges, uint32_t *bufsz,
1813
uint32_t *flags, COST_VECT *cost)
1997
uint n_ranges, uint *bufsz,
1998
uint *flags, COST_VECT *cost)
1816
2001
This call is here because there is no location where this->table would
1825
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
1826
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
2010
int ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
2011
uint *bufsz, uint *flags, COST_VECT *cost)
1828
2013
ds_mrr.init(this, table);
1829
2014
return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
1835
2020
/* Index condition pushdown implementation*/
1838
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
2023
Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
1840
2025
pushed_idx_cond_keyno= keyno_arg;
1841
2026
pushed_idx_cond= idx_cond_arg;
1842
in_range_check_pushed_down= true;
2027
in_range_check_pushed_down= TRUE;
1843
2028
if (active_index == pushed_idx_cond_keyno)
1844
2029
mi_set_index_cond_func(file, index_cond_func_myisam, this);
2034
struct st_mysql_storage_engine myisam_storage_engine=
2035
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
1849
2037
mysql_declare_plugin(myisam)
1851
DRIZZLE_STORAGE_ENGINE_PLUGIN,
2039
MYSQL_STORAGE_ENGINE_PLUGIN,
2040
&myisam_storage_engine,
1855
2043
"Default engine as of MySQL 3.23 with great performance",
1856
2044
PLUGIN_LICENSE_GPL,
1857
2045
myisam_init, /* Plugin Init */
1858
myisam_deinit, /* Plugin Deinit */
2046
NULL, /* Plugin Deinit */
1859
2048
NULL, /* status variables */
1860
2049
NULL, /* system variables */
1861
2050
NULL /* config options */
1863
2052
mysql_declare_plugin_end;
2055
#ifdef HAVE_QUERY_CACHE
2057
@brief Register a named table with a call back function to the query cache.
2059
@param thd The thread handle
2060
@param table_key A pointer to the table name in the table cache
2061
@param key_length The length of the table name
2062
@param[out] engine_callback The pointer to the storage engine call back
2063
function, currently 0
2064
@param[out] engine_data Engine data will be set to 0.
2066
@note Despite the name of this function, it is used to check each statement
2067
before it is cached and not to register a table or callback function.
2069
@see handler::register_query_cache_table
2071
@return The error code. The engine_data and engine_callback will be set to 0.
2072
@retval TRUE Success
2073
@retval FALSE An error occured
2076
my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name,
2077
uint table_name_len,
2080
uint64_t *engine_data)
2082
DBUG_ENTER("ha_myisam::register_query_cache_table");
2084
No call back function is needed to determine if a cached statement
2087
*engine_callback= 0;
2090
No engine data is needed.
2094
if (file->s->concurrent_insert)
2097
If a concurrent INSERT has happened just before the currently
2098
processed SELECT statement, the total size of the table is
2101
To determine if the table size is known, the current thread's snap
2102
shot of the table size with the actual table size are compared.
2104
If the table size is unknown the SELECT statement can't be cached.
2106
When concurrent inserts are disabled at table open, mi_open()
2107
does not assign a get_status() function. In this case the local
2108
("current") status is never updated. We would wrongly think that
2109
we cannot cache the statement.
2111
uint64_t actual_data_file_length;
2112
uint64_t current_data_file_length;
2115
POSIX visibility rules specify that "2. Whatever memory values a
2116
thread can see when it unlocks a mutex <...> can also be seen by any
2117
thread that later locks the same mutex". In this particular case,
2118
concurrent insert thread had modified the data_file_length in
2119
MYISAM_SHARE before it has unlocked (or even locked)
2120
structure_guard_mutex. So, here we're guaranteed to see at least that
2121
value after we've locked the same mutex. We can see a later value
2122
(modified by some other thread) though, but it's ok, as we only want
2123
to know if the variable was changed, the actual new value doesn't matter
2125
actual_data_file_length= file->s->state.state.data_file_length;
2126
current_data_file_length= file->save_state.data_file_length;
2128
if (current_data_file_length != actual_data_file_length)
2130
/* Don't cache current statement. */
2135
/* It is ok to try to cache current statement. */