~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Monty Taylor
  • Date: 2008-08-16 21:06:22 UTC
  • Revision ID: monty@inaugust.com-20080816210622-zpnn13unyinqzn72
Updated po files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
 
17
 
 
18
 
#include "config.h"
19
 
#include "drizzled/internal/my_bit.h"
20
 
#include "myisampack.h"
 
17
#ifdef USE_PRAGMA_IMPLEMENTATION
 
18
#pragma implementation                          // gcc: Class implementation
 
19
#endif
 
20
 
 
21
#define DRIZZLE_SERVER 1
 
22
 
 
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/internal/my_bit.h"
24
 
#include "drizzled/internal/m_string.h"
25
 
#include "drizzled/util/test.h"
26
 
#include "drizzled/error.h"
27
 
#include "drizzled/errmsg_print.h"
28
 
#include "drizzled/gettext.h"
29
 
#include "drizzled/session.h"
30
 
#include "drizzled/plugin/client.h"
31
 
#include "drizzled/table.h"
32
 
#include "drizzled/field/timestamp.h"
33
 
#include "drizzled/memory/multi_malloc.h"
34
 
 
35
 
#include <string>
36
 
#include <sstream>
37
 
#include <map>
38
 
#include <algorithm>
39
 
 
40
 
using namespace std;
41
 
 
42
 
static const string engine_name("MyISAM");
43
 
 
44
 
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
45
 
 
46
 
static uint32_t repair_threads;
47
 
static uint32_t block_size;
48
 
static uint64_t max_sort_file_size;
49
 
static uint64_t sort_buffer_size;
 
27
#include "myisamdef.h"
 
28
#include <drizzled/drizzled_error_messages.h>
 
29
 
 
30
ulong myisam_recover_options= HA_RECOVER_NONE;
 
31
 
 
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};
 
37
 
 
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};
 
43
 
50
44
 
51
45
/*****************************************************************************
52
46
** MyISAM tables
53
47
*****************************************************************************/
54
48
 
55
 
static const char *ha_myisam_exts[] = {
56
 
  ".MYI",
57
 
  ".MYD",
58
 
  NULL
59
 
};
60
 
 
61
 
class MyisamEngine : public drizzled::plugin::StorageEngine
62
 
{
63
 
public:
64
 
  MyisamEngine(string name_arg)
65
 
   : drizzled::plugin::StorageEngine(name_arg,
66
 
                                     HTON_HAS_DATA_DICTIONARY |
67
 
                                     HTON_CAN_INDEX_BLOBS |
68
 
                                     HTON_STATS_RECORDS_IS_EXACT |
69
 
                                     HTON_TEMPORARY_ONLY |
70
 
                                     HTON_NULL_IN_KEY |
71
 
                                     HTON_MRR_CANT_SORT |
72
 
                                     HTON_HAS_RECORDS |
73
 
                                     HTON_DUPLICATE_POS |
74
 
                                     HTON_AUTO_PART_KEY |
75
 
                                     HTON_NEED_READ_RANGE_BUFFER |
76
 
                                     HTON_SKIP_STORE_LOCK |
77
 
                                     HTON_FILE_BASED ) {}
78
 
 
79
 
  ~MyisamEngine()
80
 
  { }
81
 
 
82
 
  virtual Cursor *create(TableShare &table,
83
 
                         drizzled::memory::Root *mem_root)
84
 
  {
85
 
    return new (mem_root) ha_myisam(*this, table);
86
 
  }
87
 
 
88
 
  const char **bas_ext() const {
89
 
    return ha_myisam_exts;
90
 
  }
91
 
 
92
 
  int doCreateTable(Session *, const char *table_name,
93
 
                    Table& table_arg,
94
 
                    drizzled::message::Table&);
95
 
 
96
 
  int doRenameTable(Session*, const char *from, const char *to);
97
 
 
98
 
  int doDropTable(Session&, const string table_name);
99
 
 
100
 
  int doGetTableDefinition(Session& session,
101
 
                           const char* path,
102
 
                           const char *db,
103
 
                           const char *table_name,
104
 
                           const bool is_tmp,
105
 
                           drizzled::message::Table *table_proto);
106
 
 
107
 
  /* Temp only engine, so do not return values. */
108
 
  void doGetTableNames(drizzled::CachedDirectory &, string& , set<string>&) { };
109
 
 
110
 
  uint32_t max_supported_keys()          const { return MI_MAX_KEY; }
111
 
  uint32_t max_supported_key_length()    const { return MI_MAX_KEY_LENGTH; }
112
 
  uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
113
 
 
114
 
  uint32_t index_flags(enum  ha_key_alg) const
115
 
  {
116
 
    return (HA_READ_NEXT |
117
 
            HA_READ_PREV |
118
 
            HA_READ_RANGE |
119
 
            HA_READ_ORDER |
120
 
            HA_KEYREAD_ONLY);
121
 
  }
122
 
};
123
 
 
124
 
int MyisamEngine::doGetTableDefinition(Session&,
125
 
                                       const char* path,
126
 
                                       const char *,
127
 
                                       const char *,
128
 
                                       const bool,
129
 
                                       drizzled::message::Table *table_proto)
130
 
{
131
 
  int error= ENOENT;
132
 
  ProtoCache::iterator iter;
133
 
 
134
 
  pthread_mutex_lock(&proto_cache_mutex);
135
 
  iter= proto_cache.find(path);
136
 
 
137
 
  if (iter!= proto_cache.end())
138
 
  {
139
 
    if (table_proto)
140
 
      table_proto->CopyFrom(((*iter).second));
141
 
    error= EEXIST;
142
 
  }
143
 
  pthread_mutex_unlock(&proto_cache_mutex);
144
 
 
145
 
  return error;
 
49
static handler *myisam_create_handler(handlerton *hton,
 
50
                                      TABLE_SHARE *table, 
 
51
                                      MEM_ROOT *mem_root)
 
52
{
 
53
  return new (mem_root) ha_myisam(hton, table);
146
54
}
147
55
 
148
 
/* 
149
 
  Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
150
 
*/
 
56
// collect errors printed by mi_check routines
151
57
 
152
 
static void mi_check_print_msg(MI_CHECK *,      const char* ,
153
 
                               const char *, va_list )
 
58
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
 
59
                               const char *fmt, va_list args)
154
60
{
 
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];
 
66
 
 
67
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
 
68
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
 
69
 
 
70
  if (!thd->vio_ok())
 
71
  {
 
72
    sql_print_error(msgbuf);
 
73
    return;
 
74
  }
 
75
 
 
76
  if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
 
77
                         T_AUTO_REPAIR))
 
78
  {
 
79
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
 
80
    return;
 
81
  }
 
82
  length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
 
83
                 name);
 
84
  /*
 
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.
 
88
 
 
89
    Also we likely need to lock mutex here (in both cases with protocol and
 
90
    push_warning).
 
91
  */
 
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",
 
99
                    msgbuf);
 
100
  return;
155
101
}
156
102
 
157
103
 
158
104
/*
159
 
  Convert Table object to MyISAM key and column definition
 
105
  Convert TABLE object to MyISAM key and column definition
160
106
 
161
107
  SYNOPSIS
162
108
    table2myisam()
163
 
      table_arg   in     Table object.
 
109
      table_arg   in     TABLE object.
164
110
      keydef_out  out    MyISAM key definition.
165
111
      recinfo_out out    MyISAM column definition.
166
112
      records_out out    Number of fields.
171
117
    table conformance in merge engine.
172
118
 
173
119
    The caller needs to free *recinfo_out after use. Since *recinfo_out
174
 
    and *keydef_out are allocated with a multi_malloc, *keydef_out
 
120
    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
175
121
    is freed automatically when *recinfo_out is freed.
176
122
 
177
123
  RETURN VALUE
179
125
    !0 error code
180
126
*/
181
127
 
182
 
static int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
183
 
                        MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
 
128
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
 
129
                 MI_COLUMNDEF **recinfo_out, uint *records_out)
184
130
{
185
 
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
 
131
  uint i, j, recpos, minpos, fieldpos, temp_length, length;
186
132
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
187
 
  unsigned char *record;
 
133
  uchar *record;
188
134
  KEY *pos;
189
135
  MI_KEYDEF *keydef;
190
136
  MI_COLUMNDEF *recinfo, *recinfo_pos;
191
137
  HA_KEYSEG *keyseg;
192
 
  TableShare *share= table_arg->s;
193
 
  uint32_t options= share->db_options_in_use;
194
 
  if (!(drizzled::memory::multi_malloc(false,
 
138
  TABLE_SHARE *share= table_arg->s;
 
139
  uint options= share->db_options_in_use;
 
140
  if (!(my_multi_malloc(MYF(MY_WME),
195
141
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
196
142
          keydef_out, share->keys * sizeof(MI_KEYDEF),
197
 
          &keyseg, (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
198
 
          NULL)))
199
 
    return(HA_ERR_OUT_OF_MEM);
 
143
          &keyseg,
 
144
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
145
          NullS)))
 
146
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
200
147
  keydef= *keydef_out;
201
148
  recinfo= *recinfo_out;
202
149
  pos= table_arg->key_info;
219
166
      {
220
167
        if (pos->key_part[j].length > 8 &&
221
168
            (type == HA_KEYTYPE_TEXT ||
 
169
             type == HA_KEYTYPE_NUM ||
222
170
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
223
171
        {
224
172
          /* No blobs here */
242
190
      {
243
191
        keydef[i].seg[j].null_bit= field->null_bit;
244
192
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
245
 
                                           (unsigned char*) table_arg->record[0]);
 
193
                                           (uchar*) table_arg->record[0]);
246
194
      }
247
195
      else
248
196
      {
264
212
  record= table_arg->record[0];
265
213
  recpos= 0;
266
214
  recinfo_pos= recinfo;
267
 
  while (recpos < (uint) share->stored_rec_length)
 
215
  while (recpos < (uint) share->reclength)
268
216
  {
269
217
    Field **field, *found= 0;
270
218
    minpos= share->reclength;
310
258
    {
311
259
      recinfo_pos->null_bit= found->null_bit;
312
260
      recinfo_pos->null_pos= (uint) (found->null_ptr -
313
 
                                     (unsigned char*) table_arg->record[0]);
 
261
                                     (uchar*) table_arg->record[0]);
314
262
    }
315
263
    else
316
264
    {
324
272
  return(0);
325
273
}
326
274
 
327
 
int ha_myisam::reset_auto_increment(uint64_t value)
328
 
{
329
 
  file->s->state.auto_increment= value;
330
 
  return 0;
331
 
}
332
275
 
333
276
/*
334
277
  Check for underlying table conformance
370
313
      (should be corretly detected in table2myisam).
371
314
*/
372
315
 
373
 
static int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
374
 
                            uint32_t t1_keys, uint32_t t1_recs,
375
 
                            MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
376
 
                            uint32_t t2_keys, uint32_t t2_recs, bool strict)
 
316
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
 
317
                     uint t1_keys, uint t1_recs,
 
318
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
 
319
                     uint t2_keys, uint t2_recs, bool strict)
377
320
{
378
 
  uint32_t i, j;
 
321
  uint i, j;
379
322
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
380
323
  {
381
324
    return(1);
408
351
      {
409
352
        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
410
353
            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
411
 
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1;
 
354
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
412
355
        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
413
356
                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
414
 
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1;
 
357
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
415
358
      }
416
359
 
417
360
      if (t1_keysegs_j__type != t2_keysegs[j].type ||
450
393
volatile int *killed_ptr(MI_CHECK *param)
451
394
{
452
395
  /* In theory Unsafe conversion, but should be ok for now */
453
 
  return (int*) &(((Session *)(param->session))->killed);
 
396
  return (int*) &(((THD *)(param->thd))->killed);
454
397
}
455
398
 
456
399
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
497
440
*/
498
441
 
499
442
void _mi_report_crashed(MI_INFO *file, const char *message,
500
 
                        const char *sfile, uint32_t sline)
 
443
                        const char *sfile, uint sline)
501
444
{
502
 
  Session *cur_session;
 
445
  THD *cur_thd;
 
446
  LIST *element;
503
447
  pthread_mutex_lock(&file->s->intern_lock);
504
 
  if ((cur_session= file->in_use))
505
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
506
 
                    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,
507
450
                    sfile, sline);
508
451
  else
509
 
    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);
510
453
  if (message)
511
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
512
 
  list<Session *>::iterator it= file->s->in_use->begin();
513
 
  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))
514
456
  {
515
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
516
 
    ++it;
 
457
    sql_print_error("%s", "Unknown thread accessing table");
517
458
  }
518
459
  pthread_mutex_unlock(&file->s->intern_lock);
519
460
}
520
461
 
521
462
}
522
463
 
523
 
ha_myisam::ha_myisam(drizzled::plugin::StorageEngine &engine_arg,
524
 
                     TableShare &table_arg)
525
 
  : Cursor(engine_arg, table_arg),
526
 
  file(0),
527
 
  can_enable_indexes(true),
528
 
  is_ordered(true)
529
 
{ }
 
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)
 
474
{}
530
475
 
531
 
Cursor *ha_myisam::clone(drizzled::memory::Root *mem_root)
 
476
handler *ha_myisam::clone(MEM_ROOT *mem_root)
532
477
{
533
 
  ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
 
478
  ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
534
479
  if (new_handler)
535
480
    new_handler->file->state= file->state;
536
481
  return new_handler;
537
482
}
538
483
 
539
 
const char *ha_myisam::index_type(uint32_t )
 
484
 
 
485
static const char *ha_myisam_exts[] = {
 
486
  ".MYI",
 
487
  ".MYD",
 
488
  NullS
 
489
};
 
490
 
 
491
const char **ha_myisam::bas_ext() const
 
492
{
 
493
  return ha_myisam_exts;
 
494
}
 
495
 
 
496
 
 
497
const char *ha_myisam::index_type(uint key_number __attribute__((unused)))
540
498
{
541
499
  return "BTREE";
542
500
}
543
501
 
544
502
/* Name is here without an extension */
545
 
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
 
503
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
546
504
{
547
505
  MI_KEYDEF *keyinfo;
548
506
  MI_COLUMNDEF *recinfo= 0;
549
 
  uint32_t recs;
550
 
  uint32_t i;
 
507
  uint recs;
 
508
  uint i;
551
509
 
552
510
  /*
553
511
    If the user wants to have memory mapped data files, add an
564
522
    open of a table that is in use by other threads already (if the
565
523
    MyISAM share exists already).
566
524
  */
567
 
  if (!(file=mi_open(name, mode, test_if_locked)))
568
 
    return (errno ? errno : -1);
569
 
 
 
525
  if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
 
526
    return (my_errno ? my_errno : -1);
570
527
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
571
528
  {
572
 
    if ((errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
529
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
573
530
    {
 
531
      /* purecov: begin inspected */
574
532
      goto err;
 
533
      /* purecov: end */
575
534
    }
576
535
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
577
536
                         file->s->keyinfo, file->s->rec,
578
537
                         file->s->base.keys, file->s->base.fields, true))
579
538
    {
580
 
      errno= HA_ERR_CRASHED;
 
539
      /* purecov: begin inspected */
 
540
      my_errno= HA_ERR_CRASHED;
581
541
      goto err;
 
542
      /* purecov: end */
582
543
    }
583
544
  }
584
 
 
 
545
  
585
546
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
586
 
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
 
547
    VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
587
548
 
588
549
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
589
550
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
590
 
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
 
551
    VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
591
552
  if (!table->s->db_record_offset)
592
 
    is_ordered= false;
593
 
 
594
 
 
595
 
  keys_with_parts.reset();
 
553
    int_table_flags|=HA_REC_NOT_IN_SEQ;
 
554
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
555
    int_table_flags|=HA_HAS_CHECKSUM;
 
556
  
 
557
  keys_with_parts.clear_all();
596
558
  for (i= 0; i < table->s->keys; i++)
597
559
  {
598
560
    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
601
563
    KEY_PART_INFO *kp_end= kp + table->key_info[i].key_parts;
602
564
    for (; kp != kp_end; kp++)
603
565
    {
604
 
      if (!kp->field->part_of_key.test(i))
 
566
      if (!kp->field->part_of_key.is_set(i))
605
567
      {
606
 
        keys_with_parts.set(i);
 
568
        keys_with_parts.set_bit(i);
607
569
        break;
608
570
      }
609
571
    }
610
572
  }
611
 
  errno= 0;
 
573
  my_errno= 0;
612
574
  goto end;
613
575
 err:
614
576
  this->close();
615
577
 end:
616
578
  /*
617
 
    Both recinfo and keydef are allocated by multi_malloc(), thus only
 
579
    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
618
580
    recinfo must be freed.
619
581
  */
620
582
  if (recinfo)
621
 
    free((unsigned char*) recinfo);
622
 
  return errno;
 
583
    my_free((uchar*) recinfo, MYF(0));
 
584
  return my_errno;
623
585
}
624
586
 
625
587
int ha_myisam::close(void)
629
591
  return mi_close(tmp);
630
592
}
631
593
 
632
 
int ha_myisam::write_row(unsigned char *buf)
 
594
int ha_myisam::write_row(uchar *buf)
633
595
{
634
596
  ha_statistic_increment(&SSV::ha_write_count);
635
597
 
 
598
  /* If we have a timestamp column, update it to the current time */
 
599
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
600
    table->timestamp_field->set_time();
 
601
 
636
602
  /*
637
603
    If we have an auto_increment column and we are writing a changed row
638
604
    or a new row, then update the auto_increment value in the record.
646
612
  return mi_write(file,buf);
647
613
}
648
614
 
649
 
 
650
 
int ha_myisam::repair(Session *session, MI_CHECK &param, bool do_optimize)
651
 
{
652
 
  int error=0;
653
 
  uint32_t local_testflag= param.testflag;
 
615
int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
 
616
{
 
617
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
618
  int error;
 
619
  MI_CHECK param;
 
620
  MYISAM_SHARE* share = file->s;
 
621
  const char *old_proc_info=thd->proc_info;
 
622
 
 
623
  thd_proc_info(thd, "Checking table");
 
624
  myisamchk_init(&param);
 
625
  param.thd = thd;
 
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;
 
631
 
 
632
  if (!(table->db_stat & HA_READ_ONLY))
 
633
    param.testflag|= T_STATISTICS;
 
634
  param.using_global_keycache = 1;
 
635
 
 
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;
 
644
 
 
645
  error = chk_status(&param, file);             // Not fatal
 
646
  error = chk_size(&param, file);
 
647
  if (!error)
 
648
    error |= chk_del(&param, file, param.testflag);
 
649
  if (!error)
 
650
    error = chk_key(&param, file);
 
651
  if (!error)
 
652
  {
 
653
    if ((!(param.testflag & T_QUICK) &&
 
654
         ((share->options &
 
655
           (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
 
656
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
 
657
        mi_is_crashed(file))
 
658
    {
 
659
      uint old_testflag=param.testflag;
 
660
      param.testflag|=T_MEDIUM;
 
661
      if (!(error= init_io_cache(&param.read_cache, file->dfile,
 
662
                                 my_default_record_cache_size, READ_CACHE,
 
663
                                 share->pack.header_length, 1, MYF(MY_WME))))
 
664
      {
 
665
        error= chk_data_link(&param, file, param.testflag & T_EXTEND);
 
666
        end_io_cache(&(param.read_cache));
 
667
      }
 
668
      param.testflag= old_testflag;
 
669
    }
 
670
  }
 
671
  if (!error)
 
672
  {
 
673
    if ((share->state.changed & (STATE_CHANGED |
 
674
                                 STATE_CRASHED_ON_REPAIR |
 
675
                                 STATE_CRASHED | STATE_NOT_ANALYZED)) ||
 
676
        (param.testflag & T_STATISTICS) ||
 
677
        mi_is_crashed(file))
 
678
    {
 
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(&param,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
 
685
                                UPDATE_STAT);
 
686
      pthread_mutex_unlock(&share->intern_lock);
 
687
      info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 
688
           HA_STATUS_CONST);
 
689
    }
 
690
  }
 
691
  else if (!mi_is_crashed(file) && !thd->killed)
 
692
  {
 
693
    mi_mark_crashed(file);
 
694
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
695
  }
 
696
 
 
697
  thd_proc_info(thd, old_proc_info);
 
698
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
699
}
 
700
 
 
701
 
 
702
/*
 
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!
 
706
*/
 
707
 
 
708
int ha_myisam::analyze(THD *thd,
 
709
                       HA_CHECK_OPT* check_opt __attribute__((unused)))
 
710
{
 
711
  int error=0;
 
712
  MI_CHECK param;
 
713
  MYISAM_SHARE* share = file->s;
 
714
 
 
715
  myisamchk_init(&param);
 
716
  param.thd = thd;
 
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;
 
724
 
 
725
  if (!(share->state.changed & STATE_NOT_ANALYZED))
 
726
    return HA_ADMIN_ALREADY_DONE;
 
727
 
 
728
  error = chk_key(&param, file);
 
729
  if (!error)
 
730
  {
 
731
    pthread_mutex_lock(&share->intern_lock);
 
732
    error=update_state_info(&param,file,UPDATE_STAT);
 
733
    pthread_mutex_unlock(&share->intern_lock);
 
734
  }
 
735
  else if (!mi_is_crashed(file) && !thd->killed)
 
736
    mi_mark_crashed(file);
 
737
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
738
}
 
739
 
 
740
 
 
741
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
 
742
{
 
743
  int error;
 
744
  MI_CHECK param;
 
745
  ha_rows start_records;
 
746
 
 
747
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
748
 
 
749
  myisamchk_init(&param);
 
750
  param.thd = thd;
 
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)
 
758
  {
 
759
    param.retry_repair=0;
 
760
    if (test_all_bits(param.testflag,
 
761
                      (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
 
762
    {
 
763
      param.testflag&= ~T_RETRY_WITHOUT_QUICK;
 
764
      sql_print_information("Retrying repair of: '%s' without quick",
 
765
                            table->s->path.str);
 
766
      continue;
 
767
    }
 
768
    param.testflag&= ~T_QUICK;
 
769
    if ((param.testflag & T_REP_BY_SORT))
 
770
    {
 
771
      param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
 
772
      sql_print_information("Retrying repair of: '%s' with keycache",
 
773
                            table->s->path.str);
 
774
      continue;
 
775
    }
 
776
    break;
 
777
  }
 
778
  if (!error && start_records != file->state->records &&
 
779
      !(check_opt->flags & T_VERY_SILENT))
 
780
  {
 
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),
 
785
                          table->s->path.str);
 
786
  }
 
787
  return error;
 
788
}
 
789
 
 
790
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
 
791
{
 
792
  int error;
 
793
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
794
  MI_CHECK param;
 
795
 
 
796
  myisamchk_init(&param);
 
797
  param.thd = thd;
 
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)
 
803
  {
 
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);
 
808
  }
 
809
  return error;
 
810
}
 
811
 
 
812
 
 
813
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
 
814
{
 
815
  int error=0;
 
816
  uint local_testflag=param.testflag;
654
817
  bool optimize_done= !do_optimize, statistics_done=0;
655
 
  const char *old_proc_info= session->get_proc_info();
 
818
  const char *old_proc_info=thd->proc_info;
656
819
  char fixed_name[FN_REFLEN];
657
820
  MYISAM_SHARE* share = file->s;
658
821
  ha_rows rows= file->state->records;
667
830
  */
668
831
  if (file->dfile == -1)
669
832
  {
670
 
    errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' failed. "
 
833
    sql_print_information("Retrying repair of: '%s' failed. "
671
834
                          "Please try REPAIR EXTENDED or myisamchk",
672
835
                          table->s->path.str);
673
836
    return(HA_ADMIN_FAILED);
677
840
  param.table_name= table->alias;
678
841
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
679
842
  param.using_global_keycache = 1;
680
 
  param.session= session;
 
843
  param.thd= thd;
 
844
  param.tmpdir= &mysql_tmpdir_list;
681
845
  param.out_flag= 0;
682
 
  param.sort_buffer_length= (size_t)sort_buffer_size;
683
 
  strcpy(fixed_name,file->filename);
 
846
  stpcpy(fixed_name,file->filename);
684
847
 
685
 
  // Don't lock tables if we have used LOCK Table
686
 
  if (mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
 
848
  // Don't lock tables if we have used LOCK TABLE
 
849
  if (!thd->locked_tables && 
 
850
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
687
851
  {
688
 
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
 
852
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
689
853
    return(HA_ADMIN_FAILED);
690
854
  }
691
855
 
697
861
    uint64_t key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
698
862
                        mi_get_mask_all_keys_active(share->base.keys) :
699
863
                        share->state.key_map);
700
 
    uint32_t testflag=param.testflag;
 
864
    uint testflag=param.testflag;
701
865
    if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
702
866
        (local_testflag & T_REP_BY_SORT))
703
867
    {
704
868
      local_testflag|= T_STATISTICS;
705
869
      param.testflag|= T_STATISTICS;            // We get this for free
706
870
      statistics_done=1;
707
 
      if (repair_threads > 1)
 
871
      if (thd->variables.myisam_repair_threads>1)
708
872
      {
709
873
        char buf[40];
710
874
        /* TODO: respect myisam_repair_threads variable */
711
875
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
712
 
        session->set_proc_info(buf);
 
876
        thd_proc_info(thd, buf);
713
877
        error = mi_repair_parallel(&param, file, fixed_name,
714
878
            param.testflag & T_QUICK);
715
 
        session->set_proc_info("Repair done"); // to reset proc_info, as
 
879
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
716
880
                                      // it was pointing to local buffer
717
881
      }
718
882
      else
719
883
      {
720
 
        session->set_proc_info("Repair by sorting");
 
884
        thd_proc_info(thd, "Repair by sorting");
721
885
        error = mi_repair_by_sort(&param, file, fixed_name,
722
886
            param.testflag & T_QUICK);
723
887
      }
724
888
    }
725
889
    else
726
890
    {
727
 
      session->set_proc_info("Repair with keycache");
 
891
      thd_proc_info(thd, "Repair with keycache");
728
892
      param.testflag &= ~T_REP_BY_SORT;
729
893
      error=  mi_repair(&param, file, fixed_name,
730
894
                        param.testflag & T_QUICK);
738
902
        (share->state.changed & STATE_NOT_SORTED_PAGES))
739
903
    {
740
904
      optimize_done=1;
741
 
      session->set_proc_info("Sorting index");
 
905
      thd_proc_info(thd, "Sorting index");
742
906
      error=mi_sort_index(&param,file,fixed_name);
743
907
    }
744
908
    if (!statistics_done && (local_testflag & T_STATISTICS))
746
910
      if (share->state.changed & STATE_NOT_ANALYZED)
747
911
      {
748
912
        optimize_done=1;
749
 
        session->set_proc_info("Analyzing");
 
913
        thd_proc_info(thd, "Analyzing");
750
914
        error = chk_key(&param, file);
751
915
      }
752
916
      else
753
917
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
754
918
    }
755
919
  }
756
 
  session->set_proc_info("Saving state");
 
920
  thd_proc_info(thd, "Saving state");
757
921
  if (!error)
758
922
  {
759
923
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
791
955
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
792
956
    update_state_info(&param, file, 0);
793
957
  }
794
 
  session->set_proc_info(old_proc_info);
795
 
  mi_lock_database(file,F_UNLCK);
796
 
 
 
958
  thd_proc_info(thd, old_proc_info);
 
959
  if (!thd->locked_tables)
 
960
    mi_lock_database(file,F_UNLCK);
797
961
  return(error ? HA_ADMIN_FAILED :
798
962
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
799
963
}
800
964
 
801
965
 
802
966
/*
 
967
  Assign table indexes to a specific key cache.
 
968
*/
 
969
 
 
970
int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
 
971
{
 
972
  KEY_CACHE *new_key_cache= check_opt->key_cache;
 
973
  const char *errmsg= 0;
 
974
  int error= HA_ADMIN_OK;
 
975
  uint64_t map;
 
976
  TABLE_LIST *table_list= table->pos_in_table_list;
 
977
 
 
978
  table->keys_in_use_for_query.clear_all();
 
979
 
 
980
  if (table_list->process_index_hints(table))
 
981
    return(HA_ADMIN_FAILED);
 
982
  map= ~(uint64_t) 0;
 
983
  if (!table->keys_in_use_for_query.is_clear_all())
 
984
    /* use all keys if there's no list specified by the user through hints */
 
985
    map= table->keys_in_use_for_query.to_uint64_t();
 
986
 
 
987
  if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
 
988
  { 
 
989
    char buf[STRING_BUFFER_USUAL_SIZE];
 
990
    snprintf(buf, sizeof(buf),
 
991
                "Failed to flush to index file (errno: %d)", error);
 
992
    errmsg= buf;
 
993
    error= HA_ADMIN_CORRUPT;
 
994
  }
 
995
 
 
996
  if (error != HA_ADMIN_OK)
 
997
  {
 
998
    /* Send error to user */
 
999
    MI_CHECK param;
 
1000
    myisamchk_init(&param);
 
1001
    param.thd= thd;
 
1002
    param.op_name=    "assign_to_keycache";
 
1003
    param.db_name=    table->s->db.str;
 
1004
    param.table_name= table->s->table_name.str;
 
1005
    param.testflag= 0;
 
1006
    mi_check_print_error(&param, errmsg);
 
1007
  }
 
1008
  return(error);
 
1009
}
 
1010
 
 
1011
 
 
1012
/*
803
1013
  Disable indexes, making it persistent if requested.
804
1014
 
805
1015
  SYNOPSIS
819
1029
    HA_ERR_WRONG_COMMAND  mode not implemented.
820
1030
*/
821
1031
 
822
 
int ha_myisam::disable_indexes(uint32_t mode)
 
1032
int ha_myisam::disable_indexes(uint mode)
823
1033
{
824
1034
  int error;
825
1035
 
858
1068
    Enable indexes, which might have been disabled by disable_index() before.
859
1069
    The modes without _SAVE work only if both data and indexes are empty,
860
1070
    since the MyISAM repair would enable them persistently.
861
 
    To be sure in these cases, call Cursor::delete_all_rows() before.
 
1071
    To be sure in these cases, call handler::delete_all_rows() before.
862
1072
 
863
1073
  IMPLEMENTATION
864
1074
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
871
1081
    HA_ERR_WRONG_COMMAND  mode not implemented.
872
1082
*/
873
1083
 
874
 
int ha_myisam::enable_indexes(uint32_t mode)
 
1084
int ha_myisam::enable_indexes(uint mode)
875
1085
{
876
1086
  int error;
877
1087
 
892
1102
  }
893
1103
  else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
894
1104
  {
895
 
    Session *session=current_session;
 
1105
    THD *thd=current_thd;
896
1106
    MI_CHECK param;
897
 
    const char *save_proc_info= session->get_proc_info();
898
 
    session->set_proc_info("Creating index");
 
1107
    const char *save_proc_info=thd->proc_info;
 
1108
    thd_proc_info(thd, "Creating index");
899
1109
    myisamchk_init(&param);
900
1110
    param.op_name= "recreating_index";
901
1111
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
902
1112
                     T_CREATE_MISSING_KEYS);
903
1113
    param.myf_rw&= ~MY_WAIT_IF_FULL;
904
 
    param.sort_buffer_length=  (size_t)sort_buffer_size;
905
 
    param.stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
906
 
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
 
1114
    param.sort_buffer_length=  thd->variables.myisam_sort_buff_size;
 
1115
    param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
 
1116
    param.tmpdir=&mysql_tmpdir_list;
 
1117
    if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
907
1118
    {
908
 
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
909
 
                        errno, param.db_name, param.table_name);
 
1119
      sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
 
1120
                        my_errno, param.db_name, param.table_name);
910
1121
      /* Repairing by sort failed. Now try standard repair method. */
911
1122
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
912
 
      error= (repair(session,param,0) != HA_ADMIN_OK);
 
1123
      error= (repair(thd,param,0) != HA_ADMIN_OK);
913
1124
      /*
914
1125
        If the standard repair succeeded, clear all error messages which
915
1126
        might have been set by the first repair. They can still be seen
916
1127
        with SHOW WARNINGS then.
917
1128
      */
918
1129
      if (! error)
919
 
        session->clear_error();
 
1130
        thd->clear_error();
920
1131
    }
921
1132
    info(HA_STATUS_CONST);
922
 
    session->set_proc_info(save_proc_info);
 
1133
    thd_proc_info(thd, save_proc_info);
923
1134
  }
924
1135
  else
925
1136
  {
947
1158
 
948
1159
int ha_myisam::indexes_are_disabled(void)
949
1160
{
950
 
 
 
1161
  
951
1162
  return mi_indexes_are_disabled(file);
952
1163
}
953
1164
 
968
1179
 
969
1180
void ha_myisam::start_bulk_insert(ha_rows rows)
970
1181
{
971
 
  Session *session= current_session;
972
 
  ulong size= session->variables.read_buff_size;
 
1182
  THD *thd= current_thd;
 
1183
  ulong size= min(thd->variables.read_buff_size,
 
1184
                  (ulong) (table->s->avg_row_length*rows));
973
1185
 
974
1186
  /* don't enable row cache if too few rows */
975
1187
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
978
1190
  can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
979
1191
                                            file->s->base.keys);
980
1192
 
981
 
  /*
982
 
    Only disable old index if the table was empty and we are inserting
983
 
    a lot of rows.
984
 
    We should not do this for only a few rows as this is slower and
985
 
    we don't want to update the key statistics based of only a few rows.
986
 
  */
987
 
  if (file->state->records == 0 && can_enable_indexes &&
988
 
      (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
989
 
    mi_disable_non_unique_index(file,rows);
990
 
  else
 
1193
  if (!(specialflag & SPECIAL_SAFE_MODE))
 
1194
  {
 
1195
    /*
 
1196
      Only disable old index if the table was empty and we are inserting
 
1197
      a lot of rows.
 
1198
      We should not do this for only a few rows as this is slower and
 
1199
      we don't want to update the key statistics based of only a few rows.
 
1200
    */
 
1201
    if (file->state->records == 0 && can_enable_indexes &&
 
1202
        (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
 
1203
      mi_disable_non_unique_index(file,rows);
 
1204
    else
991
1205
    if (!file->bulk_insert &&
992
1206
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
993
1207
    {
994
 
      mi_init_bulk_insert(file,
995
 
                          (size_t)session->variables.bulk_insert_buff_size,
996
 
                          rows);
 
1208
      mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
997
1209
    }
 
1210
  }
 
1211
  return;
998
1212
}
999
1213
 
1000
1214
/*
1019
1233
}
1020
1234
 
1021
1235
 
1022
 
 
1023
 
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
 
1236
bool ha_myisam::check_and_repair(THD *thd)
 
1237
{
 
1238
  int error=0;
 
1239
  int marked_crashed;
 
1240
  char *old_query;
 
1241
  uint old_query_length;
 
1242
  HA_CHECK_OPT check_opt;
 
1243
 
 
1244
  check_opt.init();
 
1245
  check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
 
1246
  // Don't use quick if deleted rows
 
1247
  if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
 
1248
    check_opt.flags|=T_QUICK;
 
1249
  sql_print_warning("Checking table:   '%s'",table->s->path.str);
 
1250
 
 
1251
  old_query= thd->query;
 
1252
  old_query_length= thd->query_length;
 
1253
  pthread_mutex_lock(&LOCK_thread_count);
 
1254
  thd->query=        table->s->table_name.str;
 
1255
  thd->query_length= table->s->table_name.length;
 
1256
  pthread_mutex_unlock(&LOCK_thread_count);
 
1257
 
 
1258
  if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
 
1259
  {
 
1260
    sql_print_warning("Recovering table: '%s'",table->s->path.str);
 
1261
    check_opt.flags=
 
1262
      ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
 
1263
       (marked_crashed                             ? 0 : T_QUICK) |
 
1264
       (myisam_recover_options & HA_RECOVER_FORCE  ? 0 : T_SAFE_REPAIR) |
 
1265
       T_AUTO_REPAIR);
 
1266
    if (repair(thd, &check_opt))
 
1267
      error=1;
 
1268
  }
 
1269
  pthread_mutex_lock(&LOCK_thread_count);
 
1270
  thd->query= old_query;
 
1271
  thd->query_length= old_query_length;
 
1272
  pthread_mutex_unlock(&LOCK_thread_count);
 
1273
  return(error);
 
1274
}
 
1275
 
 
1276
bool ha_myisam::is_crashed() const
 
1277
{
 
1278
  return (file->s->state.changed & STATE_CRASHED ||
 
1279
          (file->s->state.open_count));
 
1280
}
 
1281
 
 
1282
int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
1024
1283
{
1025
1284
  ha_statistic_increment(&SSV::ha_update_count);
1026
1285
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1028
1287
  return mi_update(file,old_data,new_data);
1029
1288
}
1030
1289
 
1031
 
int ha_myisam::delete_row(const unsigned char *buf)
 
1290
int ha_myisam::delete_row(const uchar *buf)
1032
1291
{
1033
1292
  ha_statistic_increment(&SSV::ha_delete_count);
1034
1293
  return mi_delete(file,buf);
1035
1294
}
1036
1295
 
 
1296
C_MODE_START
1037
1297
 
1038
 
int ha_myisam::index_init(uint32_t idx, bool )
 
1298
bool index_cond_func_myisam(void *arg)
1039
1299
{
 
1300
  ha_myisam *h= (ha_myisam*)arg;
 
1301
  /*if (h->in_range_read)*/
 
1302
  if (h->end_range)
 
1303
  {
 
1304
    if (h->compare_key2(h->end_range) > 0)
 
1305
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
 
1306
  }
 
1307
  return (bool)h->pushed_idx_cond->val_int();
 
1308
}
 
1309
 
 
1310
C_MODE_END
 
1311
 
 
1312
 
 
1313
int ha_myisam::index_init(uint idx, bool sorted __attribute__((unused)))
 
1314
1040
1315
  active_index=idx;
1041
1316
  //in_range_read= false;
1042
 
  return 0;
 
1317
  if (pushed_idx_cond_keyno == idx)
 
1318
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
 
1319
  return 0; 
1043
1320
}
1044
1321
 
1045
1322
 
1046
1323
int ha_myisam::index_end()
1047
1324
{
1048
1325
  active_index=MAX_KEY;
1049
 
  return 0;
 
1326
  //pushed_idx_cond_keyno= MAX_KEY;
 
1327
  mi_set_index_cond_func(file, NULL, 0);
 
1328
  in_range_check_pushed_down= false;
 
1329
  ds_mrr.dsmrr_close();
 
1330
  return 0; 
1050
1331
}
1051
1332
 
1052
1333
 
1053
 
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
 
1334
int ha_myisam::index_read_map(uchar *buf, const uchar *key,
1054
1335
                              key_part_map keypart_map,
1055
1336
                              enum ha_rkey_function find_flag)
1056
1337
{
1061
1342
  return error;
1062
1343
}
1063
1344
 
1064
 
int ha_myisam::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
 
1345
int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
1065
1346
                                  key_part_map keypart_map,
1066
1347
                                  enum ha_rkey_function find_flag)
1067
1348
{
1071
1352
  return error;
1072
1353
}
1073
1354
 
1074
 
int ha_myisam::index_read_last_map(unsigned char *buf, const unsigned char *key,
 
1355
int ha_myisam::index_read_last_map(uchar *buf, const uchar *key,
1075
1356
                                   key_part_map keypart_map)
1076
1357
{
1077
1358
  assert(inited==INDEX);
1082
1363
  return(error);
1083
1364
}
1084
1365
 
1085
 
int ha_myisam::index_next(unsigned char *buf)
 
1366
int ha_myisam::index_next(uchar *buf)
1086
1367
{
1087
1368
  assert(inited==INDEX);
1088
1369
  ha_statistic_increment(&SSV::ha_read_next_count);
1091
1372
  return error;
1092
1373
}
1093
1374
 
1094
 
int ha_myisam::index_prev(unsigned char *buf)
 
1375
int ha_myisam::index_prev(uchar *buf)
1095
1376
{
1096
1377
  assert(inited==INDEX);
1097
1378
  ha_statistic_increment(&SSV::ha_read_prev_count);
1100
1381
  return error;
1101
1382
}
1102
1383
 
1103
 
int ha_myisam::index_first(unsigned char *buf)
 
1384
int ha_myisam::index_first(uchar *buf)
1104
1385
{
1105
1386
  assert(inited==INDEX);
1106
1387
  ha_statistic_increment(&SSV::ha_read_first_count);
1109
1390
  return error;
1110
1391
}
1111
1392
 
1112
 
int ha_myisam::index_last(unsigned char *buf)
 
1393
int ha_myisam::index_last(uchar *buf)
1113
1394
{
1114
1395
  assert(inited==INDEX);
1115
1396
  ha_statistic_increment(&SSV::ha_read_last_count);
1118
1399
  return error;
1119
1400
}
1120
1401
 
1121
 
int ha_myisam::index_next_same(unsigned char *buf,
1122
 
                               const unsigned char *,
1123
 
                               uint32_t )
 
1402
int ha_myisam::index_next_same(uchar *buf,
 
1403
                               const uchar *key __attribute__((unused)),
 
1404
                               uint length __attribute__((unused)))
1124
1405
{
1125
1406
  int error;
1126
1407
  assert(inited==INDEX);
1142
1423
  //if (!eq_range_arg)
1143
1424
  //  in_range_read= true;
1144
1425
 
1145
 
  res= Cursor::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
1426
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
1146
1427
 
1147
1428
  //if (res)
1148
1429
  //  in_range_read= false;
1152
1433
 
1153
1434
int ha_myisam::read_range_next()
1154
1435
{
1155
 
  int res= Cursor::read_range_next();
 
1436
  int res= handler::read_range_next();
1156
1437
  //if (res)
1157
1438
  //  in_range_read= false;
1158
1439
  return res;
1166
1447
  return mi_reset(file);                        // Free buffers
1167
1448
}
1168
1449
 
1169
 
int ha_myisam::rnd_next(unsigned char *buf)
 
1450
int ha_myisam::rnd_next(uchar *buf)
1170
1451
{
1171
1452
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1172
1453
  int error=mi_scan(file, buf);
1174
1455
  return error;
1175
1456
}
1176
1457
 
1177
 
int ha_myisam::restart_rnd_next(unsigned char *buf, unsigned char *pos)
 
1458
int ha_myisam::restart_rnd_next(uchar *buf, uchar *pos)
1178
1459
{
1179
1460
  return rnd_pos(buf,pos);
1180
1461
}
1181
1462
 
1182
 
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
 
1463
int ha_myisam::rnd_pos(uchar *buf, uchar *pos)
1183
1464
{
1184
1465
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1185
1466
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
1188
1469
}
1189
1470
 
1190
1471
 
1191
 
void ha_myisam::position(const unsigned char *)
 
1472
void ha_myisam::position(const uchar *record __attribute__((unused)))
1192
1473
{
1193
1474
  my_off_t row_position= mi_position(file);
1194
1475
  my_store_ptr(ref, ref_length, row_position);
1195
1476
}
1196
1477
 
1197
 
int ha_myisam::info(uint32_t flag)
 
1478
int ha_myisam::info(uint flag)
1198
1479
{
1199
1480
  MI_ISAMINFO misam_info;
1200
1481
  char name_buff[FN_REFLEN];
1212
1493
  }
1213
1494
  if (flag & HA_STATUS_CONST)
1214
1495
  {
1215
 
    TableShare *share= table->s;
 
1496
    TABLE_SHARE *share= table->s;
1216
1497
    stats.max_data_file_length=  misam_info.max_data_file_length;
1217
1498
    stats.max_index_file_length= misam_info.max_index_file_length;
1218
1499
    stats.create_time= misam_info.create_time;
1219
1500
    ref_length= misam_info.reflength;
1220
1501
    share->db_options_in_use= misam_info.options;
1221
 
    stats.block_size= block_size;        /* record block size */
 
1502
    stats.block_size= myisam_block_size;        /* record block size */
1222
1503
 
1223
1504
    /* Update share */
1224
1505
    if (share->tmp_table == NO_TMP_TABLE)
1225
1506
      pthread_mutex_lock(&share->mutex);
1226
 
    set_prefix(share->keys_in_use, share->keys);
1227
 
    /*
1228
 
     * Due to bug 394932 (32-bit solaris build failure), we need
1229
 
     * to convert the uint64_t key_map member of the misam_info
1230
 
     * structure in to a std::bitset so that we can logically and
1231
 
     * it with the share->key_in_use key_map.
1232
 
     */
1233
 
    ostringstream ostr;
1234
 
    string binary_key_map;
1235
 
    uint64_t num= misam_info.key_map;
1236
 
    /*
1237
 
     * Convert the uint64_t to a binary
1238
 
     * string representation of it.
1239
 
     */
1240
 
    while (num > 0)
1241
 
    {
1242
 
      uint64_t bin_digit= num % 2;
1243
 
      ostr << bin_digit;
1244
 
      num/= 2;
1245
 
    }
1246
 
    binary_key_map.append(ostr.str());
1247
 
    /*
1248
 
     * Now we have the binary string representation of the
1249
 
     * flags, we need to fill that string representation out
1250
 
     * with the appropriate number of bits. This is needed
1251
 
     * since key_map is declared as a std::bitset of a certain bit
1252
 
     * width that depends on the MAX_INDEXES variable. 
1253
 
     */
1254
 
    if (MAX_INDEXES <= 64)
1255
 
    {
1256
 
      size_t len= 72 - binary_key_map.length();
1257
 
      string all_zeros(len, '0');
1258
 
      binary_key_map.insert(binary_key_map.begin(),
1259
 
                            all_zeros.begin(),
1260
 
                            all_zeros.end());
1261
 
    }
1262
 
    else
1263
 
    {
1264
 
      size_t len= (MAX_INDEXES + 7) / 8 * 8;
1265
 
      string all_zeros(len, '0');
1266
 
      binary_key_map.insert(binary_key_map.begin(),
1267
 
                            all_zeros.begin(),
1268
 
                            all_zeros.end());
1269
 
    }
1270
 
    key_map tmp_map(binary_key_map);
1271
 
    share->keys_in_use&= tmp_map;
1272
 
    share->keys_for_keyread&= share->keys_in_use;
 
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);
1273
1510
    share->db_record_offset= misam_info.record_offset;
1274
1511
    if (share->key_parts)
1275
1512
      memcpy(table->key_info[0].rec_per_key,
1308
1545
 
1309
1546
int ha_myisam::extra(enum ha_extra_function operation)
1310
1547
{
 
1548
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD)
 
1549
    return 0;
1311
1550
  return mi_extra(file, operation, 0);
1312
1551
}
1313
1552
 
1314
1553
int ha_myisam::reset(void)
1315
1554
{
 
1555
  pushed_idx_cond= NULL;
 
1556
  pushed_idx_cond_keyno= MAX_KEY;
 
1557
  mi_set_index_cond_func(file, NULL, 0);
 
1558
  ds_mrr.dsmrr_close();
1316
1559
  return mi_reset(file);
1317
1560
}
1318
1561
 
1320
1563
 
1321
1564
int ha_myisam::extra_opt(enum ha_extra_function operation, uint32_t cache_size)
1322
1565
{
 
1566
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
 
1567
    return 0;
1323
1568
  return mi_extra(file, operation, (void*) &cache_size);
1324
1569
}
1325
1570
 
1328
1573
  return mi_delete_all_rows(file);
1329
1574
}
1330
1575
 
1331
 
int MyisamEngine::doDropTable(Session&, const string table_path)
 
1576
int ha_myisam::delete_table(const char *name)
1332
1577
{
1333
 
  ProtoCache::iterator iter;
1334
 
 
1335
 
  pthread_mutex_lock(&proto_cache_mutex);
1336
 
  iter= proto_cache.find(table_path.c_str());
1337
 
 
1338
 
  if (iter!= proto_cache.end())
1339
 
    proto_cache.erase(iter);
1340
 
 
1341
 
  pthread_mutex_unlock(&proto_cache_mutex);
1342
 
 
1343
 
  return mi_delete_table(table_path.c_str());
 
1578
  return mi_delete_table(name);
1344
1579
}
1345
1580
 
1346
1581
 
1347
 
int ha_myisam::external_lock(Session *session, int lock_type)
 
1582
int ha_myisam::external_lock(THD *thd, int lock_type)
1348
1583
{
1349
 
  file->in_use= session;
 
1584
  file->in_use.data= thd;
1350
1585
  return mi_lock_database(file, !table->s->tmp_table ?
1351
1586
                          lock_type : ((lock_type == F_UNLCK) ?
1352
1587
                                       F_UNLCK : F_EXTRA_LCK));
1353
1588
}
1354
1589
 
1355
 
int MyisamEngine::doCreateTable(Session *, const char *table_name,
1356
 
                                Table& table_arg,
1357
 
                                drizzled::message::Table& create_proto)
 
1590
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
 
1591
                                      THR_LOCK_DATA **to,
 
1592
                                      enum thr_lock_type lock_type)
 
1593
{
 
1594
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
1595
    file->lock.type=lock_type;
 
1596
  *to++= &file->lock;
 
1597
  return to;
 
1598
}
 
1599
 
 
1600
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
 
1601
{
 
1602
  ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
 
1603
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
1604
  {
 
1605
    create_info->auto_increment_value= stats.auto_increment_value;
 
1606
  }
 
1607
  create_info->data_file_name=data_file_name;
 
1608
  create_info->index_file_name=index_file_name;
 
1609
}
 
1610
 
 
1611
 
 
1612
int ha_myisam::create(const char *name, register TABLE *table_arg,
 
1613
                      HA_CREATE_INFO *ha_create_info)
1358
1614
{
1359
1615
  int error;
1360
 
  uint32_t create_flags= 0, create_records;
 
1616
  uint create_flags= 0, records;
1361
1617
  char buff[FN_REFLEN];
1362
1618
  MI_KEYDEF *keydef;
1363
1619
  MI_COLUMNDEF *recinfo;
1364
1620
  MI_CREATE_INFO create_info;
1365
 
  TableShare *share= table_arg.s;
1366
 
  uint32_t options= share->db_options_in_use;
1367
 
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1368
 
    return(error);
 
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 */
1369
1625
  memset(&create_info, 0, sizeof(create_info));
1370
 
  create_info.max_rows= create_proto.options().max_rows();
1371
 
  create_info.reloc_rows= create_proto.options().min_rows();
 
1626
  create_info.max_rows= share->max_rows;
 
1627
  create_info.reloc_rows= share->min_rows;
1372
1628
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1373
 
  create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1374
 
                               create_proto.options().auto_increment_value() -1 :
 
1629
  create_info.auto_increment= (ha_create_info->auto_increment_value ?
 
1630
                               ha_create_info->auto_increment_value -1 :
1375
1631
                               (uint64_t) 0);
1376
 
  create_info.data_file_length= (create_proto.options().max_rows() *
1377
 
                                 create_proto.options().avg_row_length());
1378
 
  create_info.data_file_name= NULL;
1379
 
  create_info.index_file_name=  NULL;
 
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;
1380
1636
  create_info.language= share->table_charset->number;
1381
1637
 
1382
 
  if (create_proto.type() == drizzled::message::Table::TEMPORARY)
 
1638
  if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1383
1639
    create_flags|= HA_CREATE_TMP_TABLE;
 
1640
  if (ha_create_info->options & HA_CREATE_KEEP_FILES)
 
1641
    create_flags|= HA_CREATE_KEEP_FILES;
1384
1642
  if (options & HA_OPTION_PACK_RECORD)
1385
1643
    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;
1386
1648
 
1387
1649
  /* TODO: Check that the following fn_format is really needed */
1388
 
  error= mi_create(fn_format(buff, table_name, "", "",
 
1650
  error= mi_create(fn_format(buff, name, "", "",
1389
1651
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
1390
1652
                   share->keys, keydef,
1391
 
                   create_records, recinfo,
 
1653
                   records, recinfo,
1392
1654
                   0, (MI_UNIQUEDEF*) 0,
1393
1655
                   &create_info, create_flags);
1394
 
  free((unsigned char*) recinfo);
1395
 
 
1396
 
  pthread_mutex_lock(&proto_cache_mutex);
1397
 
  proto_cache.insert(make_pair(table_name, create_proto));
1398
 
  pthread_mutex_unlock(&proto_cache_mutex);
1399
 
 
1400
 
  return error;
 
1656
  my_free((uchar*) recinfo, MYF(0));
 
1657
  return(error);
1401
1658
}
1402
1659
 
1403
1660
 
1404
 
int MyisamEngine::doRenameTable(Session*,
1405
 
                                const char *from, const char *to)
 
1661
int ha_myisam::rename_table(const char * from, const char * to)
1406
1662
{
1407
1663
  return mi_rename(from,to);
1408
1664
}
1409
1665
 
1410
1666
 
1411
 
void ha_myisam::get_auto_increment(uint64_t ,
1412
 
                                   uint64_t ,
1413
 
                                   uint64_t ,
 
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)),
1414
1670
                                   uint64_t *first_value,
1415
1671
                                   uint64_t *nb_reserved_values)
1416
1672
{
1417
1673
  uint64_t nr;
1418
1674
  int error;
1419
 
  unsigned char key[MI_MAX_KEY_LENGTH];
 
1675
  uchar key[MI_MAX_KEY_LENGTH];
1420
1676
 
1421
1677
  if (!table->s->next_number_key_offset)
1422
1678
  {                                             // Autoincrement at key-start
1471
1727
      HA_READ_KEY_EXACT         Include the key in the range
1472
1728
      HA_READ_AFTER_KEY         Don't include key in range
1473
1729
 
1474
 
    max_key.flag can have one of the following values:
 
1730
    max_key.flag can have one of the following values:  
1475
1731
      HA_READ_BEFORE_KEY        Don't include key in range
1476
1732
      HA_READ_AFTER_KEY         Include all 'end_key' values in the range
1477
1733
 
1482
1738
                        the range.
1483
1739
*/
1484
1740
 
1485
 
ha_rows ha_myisam::records_in_range(uint32_t inx, key_range *min_key,
 
1741
ha_rows ha_myisam::records_in_range(uint inx, key_range *min_key,
1486
1742
                                    key_range *max_key)
1487
1743
{
1488
1744
  return (ha_rows) mi_records_in_range(file, (int) inx, min_key, max_key);
1489
1745
}
1490
1746
 
1491
1747
 
1492
 
uint32_t ha_myisam::checksum() const
 
1748
uint ha_myisam::checksum() const
1493
1749
{
1494
1750
  return (uint)file->state->checksum;
1495
1751
}
1496
1752
 
1497
 
static MyisamEngine *engine= NULL;
1498
1753
 
1499
 
static int myisam_init(drizzled::plugin::Registry &registry)
 
1754
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
 
1755
                                           uint table_changes)
1500
1756
{
1501
 
  int error;
1502
 
  engine= new MyisamEngine(engine_name);
1503
 
  registry.add(engine);
1504
 
 
1505
 
  pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
1506
 
 
1507
 
  /* call ha_init_key_cache() on all key caches to init them */
1508
 
  error= init_key_cache(dflt_key_cache,
1509
 
                        (uint32_t) dflt_key_cache->param_block_size,
1510
 
                        (uint32_t) dflt_key_cache->param_buff_size,
1511
 
                        dflt_key_cache->param_division_limit, 
1512
 
                        dflt_key_cache->param_age_threshold);
1513
 
 
1514
 
  if (error == 0)
1515
 
    exit(1); /* Memory Allocation Failure */
1516
 
 
1517
 
  return 0;
 
1757
  uint options= table->s->db_options_in_use;
 
1758
 
 
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;
 
1765
 
 
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;
1518
1772
}
1519
1773
 
1520
 
static int myisam_deinit(drizzled::plugin::Registry &registry)
 
1774
int myisam_deinit(void *hton __attribute__((unused)))
1521
1775
{
1522
 
  registry.remove(engine);
1523
 
  delete engine;
1524
 
 
1525
 
  pthread_mutex_destroy(&THR_LOCK_myisam);
1526
 
  end_key_cache(dflt_key_cache, 1);             // Can never fail
1527
 
 
1528
1776
  return mi_panic(HA_PANIC_CLOSE);
1529
1777
}
1530
1778
 
1531
 
static DRIZZLE_SYSVAR_UINT(block_size, block_size,
1532
 
                           PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1533
 
                           N_("Block size to be used for MyISAM index pages."),
1534
 
                           NULL, NULL, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, 
1535
 
                           MI_MAX_KEY_BLOCK_LENGTH, 0);
1536
 
 
1537
 
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
1538
 
                           PLUGIN_VAR_RQCMDARG,
1539
 
                           N_("Number of threads to use when repairing MyISAM tables. The value of "
1540
 
                              "1 disables parallel repair."),
1541
 
                           NULL, NULL, 1, 1, UINT32_MAX, 0);
1542
 
 
1543
 
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1544
 
                                PLUGIN_VAR_RQCMDARG,
1545
 
                                N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
1546
 
                                NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
1547
 
 
1548
 
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
1549
 
                                PLUGIN_VAR_RQCMDARG,
1550
 
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
1551
 
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
1552
 
 
1553
 
extern uint32_t data_pointer_size;
1554
 
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
1555
 
                           PLUGIN_VAR_RQCMDARG,
1556
 
                           N_("Default pointer size to be used for MyISAM tables."),
1557
 
                           NULL, NULL, 6, 2, 7, 0);
1558
 
 
1559
 
static drizzle_sys_var* system_variables[]= {
1560
 
  DRIZZLE_SYSVAR(block_size),
1561
 
  DRIZZLE_SYSVAR(repair_threads),
1562
 
  DRIZZLE_SYSVAR(max_sort_file_size),
1563
 
  DRIZZLE_SYSVAR(sort_buffer_size),
1564
 
  DRIZZLE_SYSVAR(data_pointer_size),
1565
 
  NULL
1566
 
};
1567
 
 
1568
 
 
1569
 
DRIZZLE_DECLARE_PLUGIN
1570
 
{
1571
 
  DRIZZLE_VERSION_ID,
 
1779
static int myisam_init(void *p)
 
1780
{
 
1781
  handlerton *myisam_hton;
 
1782
 
 
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;
 
1788
  return 0;
 
1789
}
 
1790
 
 
1791
 
 
1792
 
 
1793
/****************************************************************************
 
1794
 * MyISAM MRR implementation: use DS-MRR
 
1795
 ***************************************************************************/
 
1796
 
 
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)
 
1800
{
 
1801
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index], 
 
1802
                           seq, seq_init_param, n_ranges, mode, buf);
 
1803
}
 
1804
 
 
1805
int ha_myisam::multi_range_read_next(char **range_info)
 
1806
{
 
1807
  return ds_mrr.dsmrr_next(this, range_info);
 
1808
}
 
1809
 
 
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)
 
1814
{
 
1815
  /*
 
1816
    This call is here because there is no location where this->table would
 
1817
    already be known.
 
1818
    TODO: consider moving it into some per-query initialization call.
 
1819
  */
 
1820
  ds_mrr.init(this, table);
 
1821
  return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
 
1822
                                 flags, cost);
 
1823
}
 
1824
 
 
1825
int ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
 
1826
                                     uint *bufsz, uint *flags, COST_VECT *cost)
 
1827
{
 
1828
  ds_mrr.init(this, table);
 
1829
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 
1830
}
 
1831
 
 
1832
/* MyISAM MRR implementation ends */
 
1833
 
 
1834
 
 
1835
/* Index condition pushdown implementation*/
 
1836
 
 
1837
 
 
1838
Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
 
1839
{
 
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);
 
1845
  return NULL;
 
1846
}
 
1847
 
 
1848
 
 
1849
mysql_declare_plugin(myisam)
 
1850
{
 
1851
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1572
1852
  "MyISAM",
1573
1853
  "1.0",
1574
1854
  "MySQL AB",
1577
1857
  myisam_init, /* Plugin Init */
1578
1858
  myisam_deinit, /* Plugin Deinit */
1579
1859
  NULL,                       /* status variables                */
1580
 
  system_variables,           /* system variables */
 
1860
  NULL,                       /* system variables                */
1581
1861
  NULL                        /* config options                  */
1582
1862
}
1583
 
DRIZZLE_DECLARE_PLUGIN_END;
 
1863
mysql_declare_plugin_end;