~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Brian Aker
  • Date: 2009-01-17 02:46:52 UTC
  • Revision ID: brian@gir-3.local-20090117024652-4ducefje08ajbs1q
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
(we always quote).

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
 
18
 
#include "config.h"
19
 
#include "drizzled/internal/my_bit.h"
 
18
#include <drizzled/server_includes.h>
 
19
#include <mysys/my_bit.h>
20
20
#include "myisampack.h"
21
21
#include "ha_myisam.h"
22
 
#include "myisam_priv.h"
23
 
#include "drizzled/option.h"
24
 
#include "drizzled/internal/my_bit.h"
25
 
#include "drizzled/internal/m_string.h"
26
 
#include "drizzled/util/test.h"
27
 
#include "drizzled/error.h"
28
 
#include "drizzled/errmsg_print.h"
29
 
#include "drizzled/gettext.h"
30
 
#include "drizzled/session.h"
31
 
#include "drizzled/set_var.h"
32
 
#include <drizzled/plugin.h>
33
 
#include "drizzled/plugin/client.h"
34
 
#include "drizzled/table.h"
35
 
#include "drizzled/field/timestamp.h"
36
 
#include "drizzled/memory/multi_malloc.h"
37
 
#include "drizzled/plugin/daemon.h"
38
 
 
39
 
#include <string>
40
 
#include <sstream>
41
 
#include <map>
42
 
#include <algorithm>
43
 
 
44
 
using namespace std;
45
 
using namespace drizzled;
46
 
 
47
 
extern pthread_mutex_t LOCK_global_system_variables;
48
 
static const string engine_name("MyISAM");
49
 
 
 
22
#include "myisamdef.h"
 
23
#include <drizzled/util/test.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/errmsg_print.h>
 
26
#include <drizzled/gettext.h>
 
27
#include <drizzled/session.h>
 
28
#include <drizzled/protocol.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/field/timestamp.h>
 
31
 
 
32
ulong myisam_recover_options= HA_RECOVER_NONE;
50
33
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
51
34
 
52
35
static uint32_t repair_threads;
53
 
static uint32_t myisam_key_cache_block_size;
54
 
static uint32_t myisam_key_cache_size;
55
 
static uint32_t myisam_key_cache_division_limit;
56
 
static uint32_t myisam_key_cache_age_threshold;
 
36
static uint32_t block_size;
57
37
static uint64_t max_sort_file_size;
58
38
static uint64_t sort_buffer_size;
59
39
 
 
40
/* bits in myisam_recover_options */
 
41
const char *myisam_recover_names[] =
 
42
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
 
43
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
 
44
                                 myisam_recover_names, NULL};
 
45
 
 
46
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
 
47
                                           "nulls_ignored", NULL};
 
48
TYPELIB myisam_stats_method_typelib= {
 
49
  array_elements(myisam_stats_method_names) - 1, "",
 
50
  myisam_stats_method_names, NULL};
 
51
 
 
52
 
60
53
/*****************************************************************************
61
54
** MyISAM tables
62
55
*****************************************************************************/
63
56
 
64
 
static const char *ha_myisam_exts[] = {
65
 
  ".MYI",
66
 
  ".MYD",
67
 
  NULL
68
 
};
69
 
 
70
 
class MyisamEngine : public plugin::StorageEngine
71
 
{
72
 
  MyisamEngine();
73
 
  MyisamEngine(const MyisamEngine&);
74
 
  MyisamEngine& operator=(const MyisamEngine&);
75
 
public:
76
 
  explicit MyisamEngine(string name_arg) :
77
 
    plugin::StorageEngine(name_arg,
78
 
                          HTON_CAN_INDEX_BLOBS |
79
 
                          HTON_STATS_RECORDS_IS_EXACT |
80
 
                          HTON_TEMPORARY_ONLY |
81
 
                          HTON_NULL_IN_KEY |
82
 
                          HTON_HAS_RECORDS |
83
 
                          HTON_DUPLICATE_POS |
84
 
                          HTON_AUTO_PART_KEY |
85
 
                          HTON_SKIP_STORE_LOCK |
86
 
                          HTON_FILE_BASED )
87
 
  {
88
 
    pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
89
 
  }
90
 
 
91
 
  virtual ~MyisamEngine()
92
 
  { 
93
 
    pthread_mutex_destroy(&THR_LOCK_myisam);
94
 
    end_key_cache(dflt_key_cache, 1);           // Can never fail
95
 
 
96
 
    mi_panic(HA_PANIC_CLOSE);
97
 
  }
98
 
 
99
 
  virtual Cursor *create(TableShare &table,
100
 
                         memory::Root *mem_root)
101
 
  {
102
 
    return new (mem_root) ha_myisam(*this, table);
103
 
  }
104
 
 
105
 
  const char **bas_ext() const {
106
 
    return ha_myisam_exts;
107
 
  }
108
 
 
109
 
  int doCreateTable(Session&,
110
 
                    Table& table_arg,
111
 
                    drizzled::TableIdentifier &identifier,
112
 
                    message::Table&);
113
 
 
114
 
  int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
115
 
 
116
 
  int doDropTable(Session&, drizzled::TableIdentifier &identifier);
117
 
 
118
 
  int doGetTableDefinition(Session& session,
119
 
                           drizzled::TableIdentifier &identifier,
120
 
                           message::Table &table_message);
121
 
 
122
 
  /* Temp only engine, so do not return values. */
123
 
  void doGetTableNames(CachedDirectory &, SchemaIdentifier &, set<string>&) { };
124
 
 
125
 
  uint32_t max_supported_keys()          const { return MI_MAX_KEY; }
126
 
  uint32_t max_supported_key_length()    const { return MI_MAX_KEY_LENGTH; }
127
 
  uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
128
 
 
129
 
  uint32_t index_flags(enum  ha_key_alg) const
130
 
  {
131
 
    return (HA_READ_NEXT |
132
 
            HA_READ_PREV |
133
 
            HA_READ_RANGE |
134
 
            HA_READ_ORDER |
135
 
            HA_KEYREAD_ONLY);
136
 
  }
137
 
  bool doDoesTableExist(Session& session, TableIdentifier &identifier);
138
 
 
139
 
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
140
 
                             drizzled::SchemaIdentifier &schema_identifier,
141
 
                             drizzled::TableIdentifiers &set_of_identifiers);
142
 
};
143
 
 
144
 
void MyisamEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
145
 
                                         drizzled::SchemaIdentifier&,
146
 
                                         drizzled::TableIdentifiers&)
147
 
{
148
 
}
149
 
 
150
 
bool MyisamEngine::doDoesTableExist(Session &session, TableIdentifier &identifier)
151
 
{
152
 
  return session.doesTableMessageExist(identifier);
153
 
}
154
 
 
155
 
int MyisamEngine::doGetTableDefinition(Session &session,
156
 
                                       drizzled::TableIdentifier &identifier,
157
 
                                       message::Table &table_message)
158
 
{
159
 
  if (session.getTableMessage(identifier, table_message))
160
 
    return EEXIST;
161
 
  return ENOENT;
162
 
}
163
 
 
164
 
/* 
165
 
  Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
166
 
*/
167
 
 
168
 
static void mi_check_print_msg(MI_CHECK *,      const char* ,
169
 
                               const char *, va_list )
170
 
{
 
57
static handler *myisam_create_handler(handlerton *hton,
 
58
                                      TABLE_SHARE *table,
 
59
                                      MEM_ROOT *mem_root)
 
60
{
 
61
  return new (mem_root) ha_myisam(hton, table);
 
62
}
 
63
 
 
64
// collect errors printed by mi_check routines
 
65
 
 
66
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
 
67
                               const char *fmt, va_list args)
 
68
{
 
69
  Session* session = (Session*)param->session;
 
70
  Protocol *protocol= session->protocol;
 
71
  uint32_t length, msg_length;
 
72
  char msgbuf[MI_MAX_MSG_BUF];
 
73
  char name[NAME_LEN*2+2];
 
74
 
 
75
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
 
76
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
 
77
 
 
78
  if (!session->vio_ok())
 
79
  {
 
80
    errmsg_printf(ERRMSG_LVL_ERROR, "%s",msgbuf);
 
81
    return;
 
82
  }
 
83
 
 
84
  if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
 
85
                         T_AUTO_REPAIR))
 
86
  {
 
87
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
 
88
    return;
 
89
  }
 
90
  length= sprintf(name,"%s.%s",param->db_name,param->table_name);
 
91
 
 
92
  /*
 
93
    TODO: switch from protocol to push_warning here. The main reason we didn't
 
94
    it yet is parallel repair. Due to following trace:
 
95
    mi_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
 
96
 
 
97
    Also we likely need to lock mutex here (in both cases with protocol and
 
98
    push_warning).
 
99
  */
 
100
  protocol->prepare_for_resend();
 
101
  protocol->store(name, length, system_charset_info);
 
102
  protocol->store(param->op_name, system_charset_info);
 
103
  protocol->store(msg_type, system_charset_info);
 
104
  protocol->store(msgbuf, msg_length, system_charset_info);
 
105
  if (protocol->write())
 
106
    errmsg_printf(ERRMSG_LVL_ERROR, "Failed on my_net_write, writing to stderr instead: %s\n",
 
107
                    msgbuf);
 
108
  return;
171
109
}
172
110
 
173
111
 
187
125
    table conformance in merge engine.
188
126
 
189
127
    The caller needs to free *recinfo_out after use. Since *recinfo_out
190
 
    and *keydef_out are allocated with a multi_malloc, *keydef_out
 
128
    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
191
129
    is freed automatically when *recinfo_out is freed.
192
130
 
193
131
  RETURN VALUE
195
133
    !0 error code
196
134
*/
197
135
 
198
 
static int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
199
 
                        MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
 
136
int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
 
137
                 MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
200
138
{
201
139
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
202
140
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
205
143
  MI_KEYDEF *keydef;
206
144
  MI_COLUMNDEF *recinfo, *recinfo_pos;
207
145
  HA_KEYSEG *keyseg;
208
 
  TableShare *share= table_arg->s;
 
146
  TABLE_SHARE *share= table_arg->s;
209
147
  uint32_t options= share->db_options_in_use;
210
 
  if (!(memory::multi_malloc(false,
 
148
  if (!(my_multi_malloc(MYF(MY_WME),
211
149
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
212
150
          keydef_out, share->keys * sizeof(MI_KEYDEF),
213
 
          &keyseg, (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
151
          &keyseg,
 
152
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
214
153
          NULL)))
215
 
    return(HA_ERR_OUT_OF_MEM);
 
154
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
216
155
  keydef= *keydef_out;
217
156
  recinfo= *recinfo_out;
218
157
  pos= table_arg->key_info;
235
174
      {
236
175
        if (pos->key_part[j].length > 8 &&
237
176
            (type == HA_KEYTYPE_TEXT ||
 
177
             type == HA_KEYTYPE_NUM ||
238
178
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
239
179
        {
240
180
          /* No blobs here */
340
280
  return(0);
341
281
}
342
282
 
343
 
int ha_myisam::reset_auto_increment(uint64_t value)
344
 
{
345
 
  file->s->state.auto_increment= value;
346
 
  return 0;
347
 
}
348
283
 
349
284
/*
350
285
  Check for underlying table conformance
386
321
      (should be corretly detected in table2myisam).
387
322
*/
388
323
 
389
 
static int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
390
 
                            uint32_t t1_keys, uint32_t t1_recs,
391
 
                            MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
392
 
                            uint32_t t2_keys, uint32_t t2_recs, bool strict)
 
324
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
 
325
                     uint32_t t1_keys, uint32_t t1_recs,
 
326
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
 
327
                     uint32_t t2_keys, uint32_t t2_recs, bool strict)
393
328
{
394
329
  uint32_t i, j;
395
330
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
424
359
      {
425
360
        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
426
361
            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
427
 
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1;
 
362
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
428
363
        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
429
364
                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
430
 
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1;
 
365
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
431
366
      }
432
367
 
433
368
      if (t1_keysegs_j__type != t2_keysegs[j].type ||
461
396
}
462
397
 
463
398
 
 
399
extern "C" {
 
400
 
464
401
volatile int *killed_ptr(MI_CHECK *param)
465
402
{
466
403
  /* In theory Unsafe conversion, but should be ok for now */
514
451
                        const char *sfile, uint32_t sline)
515
452
{
516
453
  Session *cur_session;
 
454
  LIST *element;
517
455
  pthread_mutex_lock(&file->s->intern_lock);
518
 
  if ((cur_session= file->in_use))
 
456
  if ((cur_session= (Session*) file->in_use.data))
519
457
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
520
458
                    cur_session->thread_id,
521
459
                    sfile, sline);
523
461
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
524
462
  if (message)
525
463
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
526
 
  list<Session *>::iterator it= file->s->in_use->begin();
527
 
  while (it != file->s->in_use->end())
 
464
  for (element= file->s->in_use; element; element= list_rest(element))
528
465
  {
529
466
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
530
 
    ++it;
531
467
  }
532
468
  pthread_mutex_unlock(&file->s->intern_lock);
533
469
}
534
470
 
535
 
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
536
 
                     TableShare &table_arg)
537
 
  : Cursor(engine_arg, table_arg),
538
 
  file(0),
539
 
  can_enable_indexes(true),
540
 
  is_ordered(true)
541
 
{ }
542
 
 
543
 
Cursor *ha_myisam::clone(memory::Root *mem_root)
 
471
}
 
472
 
 
473
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
 
474
  :handler(hton, table_arg), file(0),
 
475
  int_table_flags(HA_NULL_IN_KEY |
 
476
                  HA_BINLOG_ROW_CAPABLE |
 
477
                  HA_BINLOG_STMT_CAPABLE |
 
478
                  HA_DUPLICATE_POS |
 
479
                  HA_CAN_INDEX_BLOBS |
 
480
                  HA_AUTO_PART_KEY |
 
481
                  HA_FILE_BASED |
 
482
                  HA_NO_TRANSACTIONS |
 
483
                  HA_HAS_RECORDS |
 
484
                  HA_STATS_RECORDS_IS_EXACT |
 
485
                  HA_NEED_READ_RANGE_BUFFER |
 
486
                  HA_MRR_CANT_SORT),
 
487
   can_enable_indexes(1)
 
488
{}
 
489
 
 
490
handler *ha_myisam::clone(MEM_ROOT *mem_root)
544
491
{
545
 
  ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
 
492
  ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
546
493
  if (new_handler)
547
494
    new_handler->file->state= file->state;
548
495
  return new_handler;
549
496
}
550
497
 
551
 
const char *ha_myisam::index_type(uint32_t )
 
498
 
 
499
static const char *ha_myisam_exts[] = {
 
500
  ".MYI",
 
501
  ".MYD",
 
502
  NULL
 
503
};
 
504
 
 
505
const char **ha_myisam::bas_ext() const
 
506
{
 
507
  return ha_myisam_exts;
 
508
}
 
509
 
 
510
 
 
511
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
552
512
{
553
513
  return "BTREE";
554
514
}
576
536
    open of a table that is in use by other threads already (if the
577
537
    MyISAM share exists already).
578
538
  */
579
 
  if (!(file=mi_open(name, mode, test_if_locked)))
580
 
    return (errno ? errno : -1);
581
 
 
 
539
  if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
 
540
    return (my_errno ? my_errno : -1);
582
541
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
583
542
  {
584
 
    if ((errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
543
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
585
544
    {
 
545
      /* purecov: begin inspected */
586
546
      goto err;
 
547
      /* purecov: end */
587
548
    }
588
549
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
589
550
                         file->s->keyinfo, file->s->rec,
590
551
                         file->s->base.keys, file->s->base.fields, true))
591
552
    {
592
 
      errno= HA_ERR_CRASHED;
 
553
      /* purecov: begin inspected */
 
554
      my_errno= HA_ERR_CRASHED;
593
555
      goto err;
 
556
      /* purecov: end */
594
557
    }
595
558
  }
596
559
 
601
564
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
602
565
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
603
566
  if (!table->s->db_record_offset)
604
 
    is_ordered= false;
605
 
 
606
 
 
607
 
  keys_with_parts.reset();
 
567
    int_table_flags|=HA_REC_NOT_IN_SEQ;
 
568
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
569
    int_table_flags|=HA_HAS_CHECKSUM;
 
570
 
 
571
  keys_with_parts.clear_all();
608
572
  for (i= 0; i < table->s->keys; i++)
609
573
  {
610
574
    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
613
577
    KEY_PART_INFO *kp_end= kp + table->key_info[i].key_parts;
614
578
    for (; kp != kp_end; kp++)
615
579
    {
616
 
      if (!kp->field->part_of_key.test(i))
 
580
      if (!kp->field->part_of_key.is_set(i))
617
581
      {
618
 
        keys_with_parts.set(i);
 
582
        keys_with_parts.set_bit(i);
619
583
        break;
620
584
      }
621
585
    }
622
586
  }
623
 
  errno= 0;
 
587
  my_errno= 0;
624
588
  goto end;
625
589
 err:
626
590
  this->close();
627
591
 end:
628
592
  /*
629
 
    Both recinfo and keydef are allocated by multi_malloc(), thus only
 
593
    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
630
594
    recinfo must be freed.
631
595
  */
632
596
  if (recinfo)
633
597
    free((unsigned char*) recinfo);
634
 
  return errno;
 
598
  return my_errno;
635
599
}
636
600
 
637
601
int ha_myisam::close(void)
643
607
 
644
608
int ha_myisam::write_row(unsigned char *buf)
645
609
{
646
 
  ha_statistic_increment(&system_status_var::ha_write_count);
 
610
  ha_statistic_increment(&SSV::ha_write_count);
 
611
 
 
612
  /* If we have a timestamp column, update it to the current time */
 
613
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
614
    table->timestamp_field->set_time();
647
615
 
648
616
  /*
649
617
    If we have an auto_increment column and we are writing a changed row
658
626
  return mi_write(file,buf);
659
627
}
660
628
 
 
629
int ha_myisam::check(Session* session, HA_CHECK_OPT* check_opt)
 
630
{
 
631
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
632
  int error;
 
633
  MI_CHECK param;
 
634
  MYISAM_SHARE* share = file->s;
 
635
  const char *old_proc_info= session->get_proc_info();
 
636
 
 
637
  session->set_proc_info("Checking table");
 
638
  myisamchk_init(&param);
 
639
  param.session = session;
 
640
  param.op_name =   "check";
 
641
  param.db_name=    table->s->db.str;
 
642
  param.table_name= table->alias;
 
643
  param.testflag = check_opt->flags | T_CHECK | T_SILENT;
 
644
  param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
 
645
 
 
646
  if (!(table->db_stat & HA_READ_ONLY))
 
647
    param.testflag|= T_STATISTICS;
 
648
  param.using_global_keycache = 1;
 
649
 
 
650
  if (!mi_is_crashed(file) &&
 
651
      (((param.testflag & T_CHECK_ONLY_CHANGED) &&
 
652
        !(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
 
653
                                  STATE_CRASHED_ON_REPAIR)) &&
 
654
        share->state.open_count == 0) ||
 
655
       ((param.testflag & T_FAST) && (share->state.open_count ==
 
656
                                      (uint) (share->global_changed ? 1 : 0)))))
 
657
    return HA_ADMIN_ALREADY_DONE;
 
658
 
 
659
  error = chk_status(&param, file);             // Not fatal
 
660
  error = chk_size(&param, file);
 
661
  if (!error)
 
662
    error |= chk_del(&param, file, param.testflag);
 
663
  if (!error)
 
664
    error = chk_key(&param, file);
 
665
  if (!error)
 
666
  {
 
667
    if ((!(param.testflag & T_QUICK) &&
 
668
         ((share->options &
 
669
           (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
 
670
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
 
671
        mi_is_crashed(file))
 
672
    {
 
673
      uint32_t old_testflag=param.testflag;
 
674
      param.testflag|=T_MEDIUM;
 
675
      if (!(error= init_io_cache(&param.read_cache, file->dfile,
 
676
                                 my_default_record_cache_size, READ_CACHE,
 
677
                                 share->pack.header_length, 1, MYF(MY_WME))))
 
678
      {
 
679
        error= chk_data_link(&param, file, param.testflag & T_EXTEND);
 
680
        end_io_cache(&(param.read_cache));
 
681
      }
 
682
      param.testflag= old_testflag;
 
683
    }
 
684
  }
 
685
  if (!error)
 
686
  {
 
687
    if ((share->state.changed & (STATE_CHANGED |
 
688
                                 STATE_CRASHED_ON_REPAIR |
 
689
                                 STATE_CRASHED | STATE_NOT_ANALYZED)) ||
 
690
        (param.testflag & T_STATISTICS) ||
 
691
        mi_is_crashed(file))
 
692
    {
 
693
      file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
694
      pthread_mutex_lock(&share->intern_lock);
 
695
      share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
 
696
                               STATE_CRASHED_ON_REPAIR);
 
697
      if (!(table->db_stat & HA_READ_ONLY))
 
698
        error=update_state_info(&param,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
 
699
                                UPDATE_STAT);
 
700
      pthread_mutex_unlock(&share->intern_lock);
 
701
      info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 
702
           HA_STATUS_CONST);
 
703
    }
 
704
  }
 
705
  else if (!mi_is_crashed(file) && !session->killed)
 
706
  {
 
707
    mi_mark_crashed(file);
 
708
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
709
  }
 
710
 
 
711
  session->set_proc_info(old_proc_info);
 
712
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
713
}
 
714
 
 
715
 
 
716
/*
 
717
  analyze the key distribution in the table
 
718
  As the table may be only locked for read, we have to take into account that
 
719
  two threads may do an analyze at the same time!
 
720
*/
 
721
 
 
722
int ha_myisam::analyze(Session *session,
 
723
                       HA_CHECK_OPT* check_opt __attribute__((unused)))
 
724
{
 
725
  int error=0;
 
726
  MI_CHECK param;
 
727
  MYISAM_SHARE* share = file->s;
 
728
 
 
729
  myisamchk_init(&param);
 
730
  param.session = session;
 
731
  param.op_name=    "analyze";
 
732
  param.db_name=    table->s->db.str;
 
733
  param.table_name= table->alias;
 
734
  param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
 
735
                   T_DONT_CHECK_CHECKSUM);
 
736
  param.using_global_keycache = 1;
 
737
  param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
 
738
 
 
739
  if (!(share->state.changed & STATE_NOT_ANALYZED))
 
740
    return HA_ADMIN_ALREADY_DONE;
 
741
 
 
742
  error = chk_key(&param, file);
 
743
  if (!error)
 
744
  {
 
745
    pthread_mutex_lock(&share->intern_lock);
 
746
    error=update_state_info(&param,file,UPDATE_STAT);
 
747
    pthread_mutex_unlock(&share->intern_lock);
 
748
  }
 
749
  else if (!mi_is_crashed(file) && !session->killed)
 
750
    mi_mark_crashed(file);
 
751
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
752
}
 
753
 
 
754
 
 
755
int ha_myisam::repair(Session* session, HA_CHECK_OPT *check_opt)
 
756
{
 
757
  int error;
 
758
  MI_CHECK param;
 
759
  ha_rows start_records;
 
760
 
 
761
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
762
 
 
763
  myisamchk_init(&param);
 
764
  param.session = session;
 
765
  param.op_name=  "repair";
 
766
  param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
 
767
                   T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
 
768
                   (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
 
769
  param.sort_buffer_length=  sort_buffer_size;
 
770
  start_records=file->state->records;
 
771
  while ((error=repair(session,param,0)) && param.retry_repair)
 
772
  {
 
773
    param.retry_repair=0;
 
774
    if (test_all_bits(param.testflag,
 
775
                      (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
 
776
    {
 
777
      param.testflag&= ~T_RETRY_WITHOUT_QUICK;
 
778
      errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' without quick",
 
779
                            table->s->path.str);
 
780
      continue;
 
781
    }
 
782
    param.testflag&= ~T_QUICK;
 
783
    if ((param.testflag & T_REP_BY_SORT))
 
784
    {
 
785
      param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
 
786
      errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' with keycache",
 
787
                            table->s->path.str);
 
788
      continue;
 
789
    }
 
790
    break;
 
791
  }
 
792
  if (!error && start_records != file->state->records &&
 
793
      !(check_opt->flags & T_VERY_SILENT))
 
794
  {
 
795
    char llbuff[22],llbuff2[22];
 
796
    errmsg_printf(ERRMSG_LVL_INFO, "Found %s of %s rows when repairing '%s'",
 
797
                          llstr(file->state->records, llbuff),
 
798
                          llstr(start_records, llbuff2),
 
799
                          table->s->path.str);
 
800
  }
 
801
  return error;
 
802
}
 
803
 
 
804
int ha_myisam::optimize(Session* session, HA_CHECK_OPT *check_opt)
 
805
{
 
806
  int error;
 
807
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
808
  MI_CHECK param;
 
809
 
 
810
  myisamchk_init(&param);
 
811
  param.session = session;
 
812
  param.op_name= "optimize";
 
813
  param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
 
814
                   T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
 
815
  param.sort_buffer_length= sort_buffer_size;
 
816
  if ((error= repair(session,param,1)) && param.retry_repair)
 
817
  {
 
818
    errmsg_printf(ERRMSG_LVL_WARN, "Warning: Optimize table got errno %d on %s.%s, retrying",
 
819
                      my_errno, param.db_name, param.table_name);
 
820
    param.testflag&= ~T_REP_BY_SORT;
 
821
    error= repair(session,param,1);
 
822
  }
 
823
  return error;
 
824
}
 
825
 
661
826
 
662
827
int ha_myisam::repair(Session *session, MI_CHECK &param, bool do_optimize)
663
828
{
685
850
    return(HA_ADMIN_FAILED);
686
851
  }
687
852
 
688
 
  param.db_name=    table->s->getSchemaName();
 
853
  param.db_name=    table->s->db.str;
689
854
  param.table_name= table->alias;
690
855
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
691
856
  param.using_global_keycache = 1;
692
857
  param.session= session;
693
858
  param.out_flag= 0;
694
 
  param.sort_buffer_length= (size_t)sort_buffer_size;
 
859
  param.sort_buffer_length= sort_buffer_size;
695
860
  strcpy(fixed_name,file->filename);
696
861
 
697
862
  // Don't lock tables if we have used LOCK Table
698
 
  if (mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
 
863
  if (!session->locked_tables &&
 
864
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
699
865
  {
700
 
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
 
866
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
701
867
    return(HA_ADMIN_FAILED);
702
868
  }
703
869
 
720
886
      {
721
887
        char buf[40];
722
888
        /* TODO: respect myisam_repair_threads variable */
723
 
        snprintf(buf, 40, "Repair with %d threads", internal::my_count_bits(key_map));
 
889
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
724
890
        session->set_proc_info(buf);
725
891
        error = mi_repair_parallel(&param, file, fixed_name,
726
892
            param.testflag & T_QUICK);
793
959
    {
794
960
      char llbuff[22],llbuff2[22];
795
961
      mi_check_print_warning(&param,"Number of rows changed from %s to %s",
796
 
                             internal::llstr(rows,llbuff),
797
 
                             internal::llstr(file->state->records,llbuff2));
 
962
                             llstr(rows,llbuff),
 
963
                             llstr(file->state->records,llbuff2));
798
964
    }
799
965
  }
800
966
  else
804
970
    update_state_info(&param, file, 0);
805
971
  }
806
972
  session->set_proc_info(old_proc_info);
807
 
  mi_lock_database(file,F_UNLCK);
808
 
 
 
973
  if (!session->locked_tables)
 
974
    mi_lock_database(file,F_UNLCK);
809
975
  return(error ? HA_ADMIN_FAILED :
810
976
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
811
977
}
812
978
 
813
979
 
814
980
/*
 
981
  Assign table indexes to a specific key cache.
 
982
*/
 
983
 
 
984
int ha_myisam::assign_to_keycache(Session* session, HA_CHECK_OPT *check_opt)
 
985
{
 
986
  KEY_CACHE *new_key_cache= check_opt->key_cache;
 
987
  const char *errmsg= 0;
 
988
  int error= HA_ADMIN_OK;
 
989
  uint64_t map;
 
990
  TableList *table_list= table->pos_in_table_list;
 
991
 
 
992
  table->keys_in_use_for_query.clear_all();
 
993
 
 
994
  if (table_list->process_index_hints(table))
 
995
    return(HA_ADMIN_FAILED);
 
996
  map= ~(uint64_t) 0;
 
997
  if (!table->keys_in_use_for_query.is_clear_all())
 
998
    /* use all keys if there's no list specified by the user through hints */
 
999
    map= table->keys_in_use_for_query.to_uint64_t();
 
1000
 
 
1001
  if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
 
1002
  {
 
1003
    char buf[STRING_BUFFER_USUAL_SIZE];
 
1004
    snprintf(buf, sizeof(buf),
 
1005
                "Failed to flush to index file (errno: %d)", error);
 
1006
    errmsg= buf;
 
1007
    error= HA_ADMIN_CORRUPT;
 
1008
  }
 
1009
 
 
1010
  if (error != HA_ADMIN_OK)
 
1011
  {
 
1012
    /* Send error to user */
 
1013
    MI_CHECK param;
 
1014
    myisamchk_init(&param);
 
1015
    param.session= session;
 
1016
    param.op_name=    "assign_to_keycache";
 
1017
    param.db_name=    table->s->db.str;
 
1018
    param.table_name= table->s->table_name.str;
 
1019
    param.testflag= 0;
 
1020
    mi_check_print_error(&param, errmsg);
 
1021
  }
 
1022
  return(error);
 
1023
}
 
1024
 
 
1025
 
 
1026
/*
815
1027
  Disable indexes, making it persistent if requested.
816
1028
 
817
1029
  SYNOPSIS
870
1082
    Enable indexes, which might have been disabled by disable_index() before.
871
1083
    The modes without _SAVE work only if both data and indexes are empty,
872
1084
    since the MyISAM repair would enable them persistently.
873
 
    To be sure in these cases, call Cursor::delete_all_rows() before.
 
1085
    To be sure in these cases, call handler::delete_all_rows() before.
874
1086
 
875
1087
  IMPLEMENTATION
876
1088
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
913
1125
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
914
1126
                     T_CREATE_MISSING_KEYS);
915
1127
    param.myf_rw&= ~MY_WAIT_IF_FULL;
916
 
    param.sort_buffer_length=  (size_t)sort_buffer_size;
917
 
    param.stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
 
1128
    param.sort_buffer_length=  sort_buffer_size;
 
1129
    param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
918
1130
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
919
1131
    {
920
1132
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
921
 
                        errno, param.db_name, param.table_name);
 
1133
                        my_errno, param.db_name, param.table_name);
922
1134
      /* Repairing by sort failed. Now try standard repair method. */
923
1135
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
924
1136
      error= (repair(session,param,0) != HA_ADMIN_OK);
981
1193
void ha_myisam::start_bulk_insert(ha_rows rows)
982
1194
{
983
1195
  Session *session= current_session;
984
 
  ulong size= session->variables.read_buff_size;
 
1196
  ulong size= cmin(session->variables.read_buff_size,
 
1197
                  (ulong) (table->s->avg_row_length*rows));
985
1198
 
986
1199
  /* don't enable row cache if too few rows */
987
1200
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
1003
1216
    if (!file->bulk_insert &&
1004
1217
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1005
1218
    {
1006
 
      mi_init_bulk_insert(file,
1007
 
                          (size_t)session->variables.bulk_insert_buff_size,
1008
 
                          rows);
 
1219
      mi_init_bulk_insert(file, session->variables.bulk_insert_buff_size, rows);
1009
1220
    }
 
1221
 
 
1222
  return;
1010
1223
}
1011
1224
 
1012
1225
/*
1031
1244
}
1032
1245
 
1033
1246
 
 
1247
bool ha_myisam::check_and_repair(Session *session)
 
1248
{
 
1249
  int error=0;
 
1250
  int marked_crashed;
 
1251
  char *old_query;
 
1252
  uint32_t old_query_length;
 
1253
  HA_CHECK_OPT check_opt;
 
1254
 
 
1255
  check_opt.init();
 
1256
  check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
 
1257
  // Don't use quick if deleted rows
 
1258
  if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
 
1259
    check_opt.flags|=T_QUICK;
 
1260
  errmsg_printf(ERRMSG_LVL_WARN, "Checking table:   '%s'",table->s->path.str);
 
1261
 
 
1262
  old_query= session->query;
 
1263
  old_query_length= session->query_length;
 
1264
  pthread_mutex_lock(&LOCK_thread_count);
 
1265
  session->query=        table->s->table_name.str;
 
1266
  session->query_length= table->s->table_name.length;
 
1267
  pthread_mutex_unlock(&LOCK_thread_count);
 
1268
 
 
1269
  if ((marked_crashed= mi_is_crashed(file)) || check(session, &check_opt))
 
1270
  {
 
1271
    errmsg_printf(ERRMSG_LVL_WARN, "Recovering table: '%s'",table->s->path.str);
 
1272
    check_opt.flags=
 
1273
      ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
 
1274
       (marked_crashed                             ? 0 : T_QUICK) |
 
1275
       (myisam_recover_options & HA_RECOVER_FORCE  ? 0 : T_SAFE_REPAIR) |
 
1276
       T_AUTO_REPAIR);
 
1277
    if (repair(session, &check_opt))
 
1278
      error=1;
 
1279
  }
 
1280
  pthread_mutex_lock(&LOCK_thread_count);
 
1281
  session->query= old_query;
 
1282
  session->query_length= old_query_length;
 
1283
  pthread_mutex_unlock(&LOCK_thread_count);
 
1284
  return(error);
 
1285
}
 
1286
 
 
1287
bool ha_myisam::is_crashed() const
 
1288
{
 
1289
  return (file->s->state.changed & STATE_CRASHED ||
 
1290
          (file->s->state.open_count));
 
1291
}
1034
1292
 
1035
1293
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
1036
1294
{
1037
 
  ha_statistic_increment(&system_status_var::ha_update_count);
 
1295
  ha_statistic_increment(&SSV::ha_update_count);
1038
1296
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1039
1297
    table->timestamp_field->set_time();
1040
1298
  return mi_update(file,old_data,new_data);
1042
1300
 
1043
1301
int ha_myisam::delete_row(const unsigned char *buf)
1044
1302
{
1045
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
1303
  ha_statistic_increment(&SSV::ha_delete_count);
1046
1304
  return mi_delete(file,buf);
1047
1305
}
1048
1306
 
1049
 
 
1050
 
int ha_myisam::index_init(uint32_t idx, bool )
 
1307
#ifdef __cplusplus
 
1308
extern "C" {
 
1309
#endif
 
1310
 
 
1311
bool index_cond_func_myisam(void *arg)
 
1312
{
 
1313
  ha_myisam *h= (ha_myisam*)arg;
 
1314
  /*if (h->in_range_read)*/
 
1315
  if (h->end_range)
 
1316
  {
 
1317
    if (h->compare_key2(h->end_range) > 0)
 
1318
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
 
1319
  }
 
1320
  return (bool)h->pushed_idx_cond->val_int();
 
1321
}
 
1322
 
 
1323
#ifdef __cplusplus
 
1324
}
 
1325
#endif
 
1326
 
 
1327
 
 
1328
int ha_myisam::index_init(uint32_t idx, bool sorted __attribute__((unused)))
1051
1329
{
1052
1330
  active_index=idx;
1053
1331
  //in_range_read= false;
 
1332
  if (pushed_idx_cond_keyno == idx)
 
1333
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
1054
1334
  return 0;
1055
1335
}
1056
1336
 
1058
1338
int ha_myisam::index_end()
1059
1339
{
1060
1340
  active_index=MAX_KEY;
 
1341
  //pushed_idx_cond_keyno= MAX_KEY;
 
1342
  mi_set_index_cond_func(file, NULL, 0);
 
1343
  in_range_check_pushed_down= false;
 
1344
  ds_mrr.dsmrr_close();
1061
1345
  return 0;
1062
1346
}
1063
1347
 
1064
1348
 
 
1349
uint32_t ha_myisam::index_flags(uint32_t inx, uint32_t, bool) const
 
1350
{
 
1351
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
 
1352
          0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
 
1353
          HA_READ_ORDER | HA_KEYREAD_ONLY |
 
1354
          (keys_with_parts.is_set(inx)?0:HA_DO_INDEX_COND_PUSHDOWN));
 
1355
}
 
1356
 
 
1357
 
1065
1358
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
1066
1359
                              key_part_map keypart_map,
1067
1360
                              enum ha_rkey_function find_flag)
1068
1361
{
1069
1362
  assert(inited==INDEX);
1070
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1363
  ha_statistic_increment(&SSV::ha_read_key_count);
1071
1364
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1072
1365
  table->status=error ? STATUS_NOT_FOUND: 0;
1073
1366
  return error;
1077
1370
                                  key_part_map keypart_map,
1078
1371
                                  enum ha_rkey_function find_flag)
1079
1372
{
1080
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1373
  ha_statistic_increment(&SSV::ha_read_key_count);
1081
1374
  int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
1082
1375
  table->status=error ? STATUS_NOT_FOUND: 0;
1083
1376
  return error;
1087
1380
                                   key_part_map keypart_map)
1088
1381
{
1089
1382
  assert(inited==INDEX);
1090
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1383
  ha_statistic_increment(&SSV::ha_read_key_count);
1091
1384
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1092
1385
                    HA_READ_PREFIX_LAST);
1093
1386
  table->status=error ? STATUS_NOT_FOUND: 0;
1097
1390
int ha_myisam::index_next(unsigned char *buf)
1098
1391
{
1099
1392
  assert(inited==INDEX);
1100
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1393
  ha_statistic_increment(&SSV::ha_read_next_count);
1101
1394
  int error=mi_rnext(file,buf,active_index);
1102
1395
  table->status=error ? STATUS_NOT_FOUND: 0;
1103
1396
  return error;
1106
1399
int ha_myisam::index_prev(unsigned char *buf)
1107
1400
{
1108
1401
  assert(inited==INDEX);
1109
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
1402
  ha_statistic_increment(&SSV::ha_read_prev_count);
1110
1403
  int error=mi_rprev(file,buf, active_index);
1111
1404
  table->status=error ? STATUS_NOT_FOUND: 0;
1112
1405
  return error;
1115
1408
int ha_myisam::index_first(unsigned char *buf)
1116
1409
{
1117
1410
  assert(inited==INDEX);
1118
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1411
  ha_statistic_increment(&SSV::ha_read_first_count);
1119
1412
  int error=mi_rfirst(file, buf, active_index);
1120
1413
  table->status=error ? STATUS_NOT_FOUND: 0;
1121
1414
  return error;
1124
1417
int ha_myisam::index_last(unsigned char *buf)
1125
1418
{
1126
1419
  assert(inited==INDEX);
1127
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
1420
  ha_statistic_increment(&SSV::ha_read_last_count);
1128
1421
  int error=mi_rlast(file, buf, active_index);
1129
1422
  table->status=error ? STATUS_NOT_FOUND: 0;
1130
1423
  return error;
1131
1424
}
1132
1425
 
1133
1426
int ha_myisam::index_next_same(unsigned char *buf,
1134
 
                               const unsigned char *,
1135
 
                               uint32_t )
 
1427
                               const unsigned char *key __attribute__((unused)),
 
1428
                               uint32_t length __attribute__((unused)))
1136
1429
{
1137
1430
  int error;
1138
1431
  assert(inited==INDEX);
1139
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1432
  ha_statistic_increment(&SSV::ha_read_next_count);
1140
1433
  do
1141
1434
  {
1142
1435
    error= mi_rnext_same(file,buf);
1154
1447
  //if (!eq_range_arg)
1155
1448
  //  in_range_read= true;
1156
1449
 
1157
 
  res= Cursor::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
1450
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
1158
1451
 
1159
1452
  //if (res)
1160
1453
  //  in_range_read= false;
1164
1457
 
1165
1458
int ha_myisam::read_range_next()
1166
1459
{
1167
 
  int res= Cursor::read_range_next();
 
1460
  int res= handler::read_range_next();
1168
1461
  //if (res)
1169
1462
  //  in_range_read= false;
1170
1463
  return res;
1180
1473
 
1181
1474
int ha_myisam::rnd_next(unsigned char *buf)
1182
1475
{
1183
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1476
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1184
1477
  int error=mi_scan(file, buf);
1185
1478
  table->status=error ? STATUS_NOT_FOUND: 0;
1186
1479
  return error;
1193
1486
 
1194
1487
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
1195
1488
{
1196
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
1197
 
  int error=mi_rrnd(file, buf, internal::my_get_ptr(pos,ref_length));
 
1489
  ha_statistic_increment(&SSV::ha_read_rnd_count);
 
1490
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
1198
1491
  table->status=error ? STATUS_NOT_FOUND: 0;
1199
1492
  return error;
1200
1493
}
1201
1494
 
1202
1495
 
1203
 
void ha_myisam::position(const unsigned char *)
 
1496
void ha_myisam::position(const unsigned char *record __attribute__((unused)))
1204
1497
{
1205
 
  internal::my_off_t row_position= mi_position(file);
1206
 
  internal::my_store_ptr(ref, ref_length, row_position);
 
1498
  my_off_t row_position= mi_position(file);
 
1499
  my_store_ptr(ref, ref_length, row_position);
1207
1500
}
1208
1501
 
1209
1502
int ha_myisam::info(uint32_t flag)
1224
1517
  }
1225
1518
  if (flag & HA_STATUS_CONST)
1226
1519
  {
1227
 
    TableShare *share= table->s;
 
1520
    TABLE_SHARE *share= table->s;
1228
1521
    stats.max_data_file_length=  misam_info.max_data_file_length;
1229
1522
    stats.max_index_file_length= misam_info.max_index_file_length;
1230
1523
    stats.create_time= misam_info.create_time;
1231
1524
    ref_length= misam_info.reflength;
1232
1525
    share->db_options_in_use= misam_info.options;
1233
 
    stats.block_size= myisam_key_cache_block_size;        /* record block size */
 
1526
    stats.block_size= block_size;        /* record block size */
1234
1527
 
1235
1528
    /* Update share */
1236
 
    if (share->tmp_table == message::Table::STANDARD)
 
1529
    if (share->tmp_table == NO_TMP_TABLE)
1237
1530
      pthread_mutex_lock(&share->mutex);
1238
 
    set_prefix(share->keys_in_use, share->keys);
1239
 
    /*
1240
 
     * Due to bug 394932 (32-bit solaris build failure), we need
1241
 
     * to convert the uint64_t key_map member of the misam_info
1242
 
     * structure in to a std::bitset so that we can logically and
1243
 
     * it with the share->key_in_use key_map.
1244
 
     */
1245
 
    ostringstream ostr;
1246
 
    string binary_key_map;
1247
 
    uint64_t num= misam_info.key_map;
1248
 
    /*
1249
 
     * Convert the uint64_t to a binary
1250
 
     * string representation of it.
1251
 
     */
1252
 
    while (num > 0)
1253
 
    {
1254
 
      uint64_t bin_digit= num % 2;
1255
 
      ostr << bin_digit;
1256
 
      num/= 2;
1257
 
    }
1258
 
    binary_key_map.append(ostr.str());
1259
 
    /*
1260
 
     * Now we have the binary string representation of the
1261
 
     * flags, we need to fill that string representation out
1262
 
     * with the appropriate number of bits. This is needed
1263
 
     * since key_map is declared as a std::bitset of a certain bit
1264
 
     * width that depends on the MAX_INDEXES variable. 
1265
 
     */
1266
 
    if (MAX_INDEXES <= 64)
1267
 
    {
1268
 
      size_t len= 72 - binary_key_map.length();
1269
 
      string all_zeros(len, '0');
1270
 
      binary_key_map.insert(binary_key_map.begin(),
1271
 
                            all_zeros.begin(),
1272
 
                            all_zeros.end());
1273
 
    }
1274
 
    else
1275
 
    {
1276
 
      size_t len= (MAX_INDEXES + 7) / 8 * 8;
1277
 
      string all_zeros(len, '0');
1278
 
      binary_key_map.insert(binary_key_map.begin(),
1279
 
                            all_zeros.begin(),
1280
 
                            all_zeros.end());
1281
 
    }
1282
 
    key_map tmp_map(binary_key_map);
1283
 
    share->keys_in_use&= tmp_map;
1284
 
    share->keys_for_keyread&= share->keys_in_use;
 
1531
    share->keys_in_use.set_prefix(share->keys);
 
1532
    share->keys_in_use.intersect_extended(misam_info.key_map);
 
1533
    share->keys_for_keyread.intersect(share->keys_in_use);
1285
1534
    share->db_record_offset= misam_info.record_offset;
1286
1535
    if (share->key_parts)
1287
1536
      memcpy(table->key_info[0].rec_per_key,
1288
1537
             misam_info.rec_per_key,
1289
1538
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1290
 
    if (share->tmp_table == message::Table::STANDARD)
 
1539
    if (share->tmp_table == NO_TMP_TABLE)
1291
1540
      pthread_mutex_unlock(&share->mutex);
1292
1541
 
1293
1542
   /*
1295
1544
     if table is symlinked (Ie;  Real name is not same as generated name)
1296
1545
   */
1297
1546
    data_file_name= index_file_name= 0;
1298
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
 
1547
    fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
1299
1548
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1300
1549
    if (strcmp(name_buff, misam_info.data_file_name))
1301
1550
      data_file_name=misam_info.data_file_name;
1302
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
 
1551
    fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
1303
1552
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1304
1553
    if (strcmp(name_buff, misam_info.index_file_name))
1305
1554
      index_file_name=misam_info.index_file_name;
1307
1556
  if (flag & HA_STATUS_ERRKEY)
1308
1557
  {
1309
1558
    errkey  = misam_info.errkey;
1310
 
    internal::my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
 
1559
    my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
1311
1560
  }
1312
1561
  if (flag & HA_STATUS_TIME)
1313
1562
    stats.update_time = misam_info.update_time;
1325
1574
 
1326
1575
int ha_myisam::reset(void)
1327
1576
{
 
1577
  pushed_idx_cond= NULL;
 
1578
  pushed_idx_cond_keyno= MAX_KEY;
 
1579
  mi_set_index_cond_func(file, NULL, 0);
 
1580
  ds_mrr.dsmrr_close();
1328
1581
  return mi_reset(file);
1329
1582
}
1330
1583
 
1340
1593
  return mi_delete_all_rows(file);
1341
1594
}
1342
1595
 
1343
 
int MyisamEngine::doDropTable(Session &session,
1344
 
                              drizzled::TableIdentifier &identifier)
 
1596
int ha_myisam::delete_table(const char *name)
1345
1597
{
1346
 
  session.removeTableMessage(identifier);
1347
 
 
1348
 
  return mi_delete_table(identifier.getPath().c_str());
 
1598
  return mi_delete_table(name);
1349
1599
}
1350
1600
 
1351
1601
 
1352
1602
int ha_myisam::external_lock(Session *session, int lock_type)
1353
1603
{
1354
 
  file->in_use= session;
 
1604
  file->in_use.data= session;
1355
1605
  return mi_lock_database(file, !table->s->tmp_table ?
1356
1606
                          lock_type : ((lock_type == F_UNLCK) ?
1357
1607
                                       F_UNLCK : F_EXTRA_LCK));
1358
1608
}
1359
1609
 
1360
 
int MyisamEngine::doCreateTable(Session &session,
1361
 
                                Table& table_arg,
1362
 
                                drizzled::TableIdentifier &identifier,
1363
 
                                message::Table& create_proto)
 
1610
THR_LOCK_DATA **ha_myisam::store_lock(Session *session __attribute__((unused)),
 
1611
                                      THR_LOCK_DATA **to,
 
1612
                                      enum thr_lock_type lock_type)
 
1613
{
 
1614
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
1615
    file->lock.type=lock_type;
 
1616
  *to++= &file->lock;
 
1617
  return to;
 
1618
}
 
1619
 
 
1620
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
 
1621
{
 
1622
  ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
 
1623
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
1624
  {
 
1625
    create_info->auto_increment_value= stats.auto_increment_value;
 
1626
  }
 
1627
  create_info->data_file_name=data_file_name;
 
1628
  create_info->index_file_name=index_file_name;
 
1629
}
 
1630
 
 
1631
 
 
1632
int ha_myisam::create(const char *name, register Table *table_arg,
 
1633
                      HA_CREATE_INFO *ha_create_info)
1364
1634
{
1365
1635
  int error;
1366
 
  uint32_t create_flags= 0, create_records;
 
1636
  uint32_t create_flags= 0, records;
1367
1637
  char buff[FN_REFLEN];
1368
1638
  MI_KEYDEF *keydef;
1369
1639
  MI_COLUMNDEF *recinfo;
1370
1640
  MI_CREATE_INFO create_info;
1371
 
  TableShare *share= table_arg.s;
 
1641
  TABLE_SHARE *share= table_arg->s;
1372
1642
  uint32_t options= share->db_options_in_use;
1373
 
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1374
 
    return(error);
 
1643
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
 
1644
    return(error); /* purecov: inspected */
1375
1645
  memset(&create_info, 0, sizeof(create_info));
1376
 
  create_info.max_rows= create_proto.options().max_rows();
1377
 
  create_info.reloc_rows= create_proto.options().min_rows();
 
1646
  create_info.max_rows= share->max_rows;
 
1647
  create_info.reloc_rows= share->min_rows;
1378
1648
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1379
 
  create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1380
 
                               create_proto.options().auto_increment_value() -1 :
 
1649
  create_info.auto_increment= (ha_create_info->auto_increment_value ?
 
1650
                               ha_create_info->auto_increment_value -1 :
1381
1651
                               (uint64_t) 0);
1382
 
  create_info.data_file_length= (create_proto.options().max_rows() *
1383
 
                                 create_proto.options().avg_row_length());
1384
 
  create_info.data_file_name= NULL;
1385
 
  create_info.index_file_name=  NULL;
 
1652
  create_info.data_file_length= ((uint64_t) share->max_rows *
 
1653
                                 share->avg_row_length);
 
1654
  create_info.data_file_name= ha_create_info->data_file_name;
 
1655
  create_info.index_file_name= ha_create_info->index_file_name;
1386
1656
  create_info.language= share->table_charset->number;
1387
1657
 
1388
 
  if (create_proto.type() == message::Table::TEMPORARY)
 
1658
  if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1389
1659
    create_flags|= HA_CREATE_TMP_TABLE;
 
1660
  if (ha_create_info->options & HA_CREATE_KEEP_FILES)
 
1661
    create_flags|= HA_CREATE_KEEP_FILES;
1390
1662
  if (options & HA_OPTION_PACK_RECORD)
1391
1663
    create_flags|= HA_PACK_RECORD;
 
1664
  if (options & HA_OPTION_CHECKSUM)
 
1665
    create_flags|= HA_CREATE_CHECKSUM;
 
1666
  if (options & HA_OPTION_DELAY_KEY_WRITE)
 
1667
    create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1392
1668
 
1393
 
  /* TODO: Check that the following internal::fn_format is really needed */
1394
 
  error= mi_create(internal::fn_format(buff, identifier.getPath().c_str(), "", "",
1395
 
                                       MY_UNPACK_FILENAME|MY_APPEND_EXT),
 
1669
  /* TODO: Check that the following fn_format is really needed */
 
1670
  error= mi_create(fn_format(buff, name, "", "",
 
1671
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
1396
1672
                   share->keys, keydef,
1397
 
                   create_records, recinfo,
 
1673
                   records, recinfo,
1398
1674
                   0, (MI_UNIQUEDEF*) 0,
1399
1675
                   &create_info, create_flags);
1400
1676
  free((unsigned char*) recinfo);
1401
 
 
1402
 
  session.storeTableMessage(identifier, create_proto);
1403
 
 
1404
 
  return error;
 
1677
  return(error);
1405
1678
}
1406
1679
 
1407
1680
 
1408
 
int MyisamEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
1681
int ha_myisam::rename_table(const char * from, const char * to)
1409
1682
{
1410
 
  session.renameTableMessage(from, to);
1411
 
 
1412
 
  return mi_rename(from.getPath().c_str(), to.getPath().c_str());
 
1683
  return mi_rename(from,to);
1413
1684
}
1414
1685
 
1415
1686
 
1416
 
void ha_myisam::get_auto_increment(uint64_t ,
1417
 
                                   uint64_t ,
1418
 
                                   uint64_t ,
 
1687
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
 
1688
                                   uint64_t increment __attribute__((unused)),
 
1689
                                   uint64_t nb_desired_values __attribute__((unused)),
1419
1690
                                   uint64_t *first_value,
1420
1691
                                   uint64_t *nb_reserved_values)
1421
1692
{
1499
1770
  return (uint)file->state->checksum;
1500
1771
}
1501
1772
 
1502
 
static MyisamEngine *engine= NULL;
1503
 
 
1504
 
static int myisam_init(plugin::Context &context)
1505
 
{
1506
 
  engine= new MyisamEngine(engine_name);
1507
 
  context.add(engine);
1508
 
 
1509
 
  /* call ha_init_key_cache() on all key caches to init them */
1510
 
  int error= init_key_cache(dflt_key_cache,
1511
 
                            myisam_key_cache_block_size,
1512
 
                            myisam_key_cache_size,
1513
 
                            myisam_key_cache_division_limit, 
1514
 
                            myisam_key_cache_age_threshold);
1515
 
 
1516
 
  if (error == 0)
1517
 
    exit(1); /* Memory Allocation Failure */
1518
 
 
 
1773
 
 
1774
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
 
1775
                                           uint32_t table_changes)
 
1776
{
 
1777
  uint32_t options= table->s->db_options_in_use;
 
1778
 
 
1779
  if (info->auto_increment_value != stats.auto_increment_value ||
 
1780
      info->data_file_name != data_file_name ||
 
1781
      info->index_file_name != index_file_name ||
 
1782
      table_changes == IS_EQUAL_NO ||
 
1783
      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
 
1784
    return COMPATIBLE_DATA_NO;
 
1785
 
 
1786
  if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
1787
                  HA_OPTION_DELAY_KEY_WRITE)) !=
 
1788
      (info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
1789
                              HA_OPTION_DELAY_KEY_WRITE)))
 
1790
    return COMPATIBLE_DATA_NO;
 
1791
  return COMPATIBLE_DATA_YES;
 
1792
}
 
1793
 
 
1794
int myisam_deinit(void *hton __attribute__((unused)))
 
1795
{
 
1796
  pthread_mutex_destroy(&THR_LOCK_myisam);
 
1797
 
 
1798
  return mi_panic(HA_PANIC_CLOSE);
 
1799
}
 
1800
 
 
1801
static int myisam_init(void *p)
 
1802
{
 
1803
  handlerton *myisam_hton;
 
1804
 
 
1805
  myisam_hton= (handlerton *)p;
 
1806
  myisam_hton->state= SHOW_OPTION_YES;
 
1807
  myisam_hton->create= myisam_create_handler;
 
1808
  myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1519
1809
  return 0;
1520
1810
}
1521
1811
 
1522
1812
 
1523
 
static void sys_var_key_cache_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1524
 
{
1525
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1526
 
  bool error= 0;
1527
 
 
1528
 
        struct option option_limits;
1529
 
  plugin_opt_set_limits(&option_limits, var);
1530
 
        option_limits.name= "myisam_key_cache_size";
1531
 
 
1532
 
  if (dflt_key_cache->in_init)
1533
 
    return;
1534
 
 
1535
 
  myisam_key_cache_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1536
 
 
1537
 
  /* If key cache didn't existed initialize it, else resize it */
1538
 
  dflt_key_cache->in_init= 1;
1539
 
 
1540
 
  error= ! resize_key_cache(dflt_key_cache,
1541
 
                                                                                                                myisam_key_cache_block_size,
1542
 
                            myisam_key_cache_size,
1543
 
                            myisam_key_cache_division_limit,
1544
 
                                                                                                          myisam_key_cache_age_threshold);
1545
 
  dflt_key_cache->in_init= 0;
1546
 
}
1547
 
 
1548
 
static void sys_var_key_cache_block_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1549
 
{
1550
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1551
 
  bool error= 0;
1552
 
 
1553
 
        struct option option_limits;
1554
 
  plugin_opt_set_limits(&option_limits, var);
1555
 
        option_limits.name= "myisam_key_cache_block_size";
1556
 
 
1557
 
  if (dflt_key_cache->in_init)
1558
 
    return;
1559
 
 
1560
 
  myisam_key_cache_block_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1561
 
 
1562
 
  dflt_key_cache->in_init= 1;
1563
 
 
1564
 
  error= ! resize_key_cache(dflt_key_cache,
1565
 
                                                                                                                myisam_key_cache_block_size,
1566
 
                            myisam_key_cache_size,
1567
 
                            myisam_key_cache_division_limit,
1568
 
                                                                                                          myisam_key_cache_age_threshold);
1569
 
 
1570
 
  dflt_key_cache->in_init= 0;
1571
 
}
1572
 
 
1573
 
static void sys_var_key_cache_division_limit_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1574
 
{
1575
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1576
 
  bool error= 0;
1577
 
 
1578
 
        struct option option_limits;
1579
 
  plugin_opt_set_limits(&option_limits, var);
1580
 
        option_limits.name= "myisam_key_cache_division_limit";
1581
 
 
1582
 
  if (dflt_key_cache->in_init)
1583
 
    return;
1584
 
 
1585
 
  myisam_key_cache_division_limit= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1586
 
 
1587
 
  dflt_key_cache->in_init= 1;
1588
 
 
1589
 
  error= ! resize_key_cache(dflt_key_cache,
1590
 
                                                                                                                myisam_key_cache_block_size,
1591
 
                            myisam_key_cache_size,
1592
 
                            myisam_key_cache_division_limit,
1593
 
                                                                                                          myisam_key_cache_age_threshold);
1594
 
 
1595
 
  dflt_key_cache->in_init= 0;
1596
 
}
1597
 
 
1598
 
static void sys_var_key_cache_age_threshold_update(Session *session, drizzle_sys_var *var, void *, const void *save)
1599
 
{
1600
 
  uint32_t tmp= *static_cast<const uint32_t *>(save);
1601
 
  bool error= 0;
1602
 
 
1603
 
        struct option option_limits;
1604
 
  plugin_opt_set_limits(&option_limits, var);
1605
 
        option_limits.name= "myisam_key_cache_age_threshold";
1606
 
 
1607
 
  if (dflt_key_cache->in_init)
1608
 
    return;
1609
 
 
1610
 
  myisam_key_cache_age_threshold= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
1611
 
 
1612
 
  dflt_key_cache->in_init= 1;
1613
 
 
1614
 
  error= ! resize_key_cache(dflt_key_cache,
1615
 
                                                                                                                myisam_key_cache_block_size,
1616
 
                            myisam_key_cache_size,
1617
 
                            myisam_key_cache_division_limit,
1618
 
                                                                                                          myisam_key_cache_age_threshold);
1619
 
 
1620
 
  dflt_key_cache->in_init= 0;
1621
 
}
1622
 
 
1623
 
static DRIZZLE_SYSVAR_UINT(key_cache_block_size,
1624
 
                            myisam_key_cache_block_size,
1625
 
                            PLUGIN_VAR_RQCMDARG,
1626
 
                            N_("Block size to be used for MyISAM index pages."),
1627
 
                            NULL,
1628
 
                            sys_var_key_cache_block_size_update,
1629
 
                            KEY_CACHE_BLOCK_SIZE,
1630
 
                            512, 
1631
 
                            16 * 1024,
1632
 
                            0);
1633
 
 
1634
 
static DRIZZLE_SYSVAR_UINT(key_cache_age_threshold, myisam_key_cache_age_threshold,
1635
 
                            PLUGIN_VAR_RQCMDARG,
1636
 
                            N_("This characterizes the number of hits a hot block has to be untouched "
1637
 
                            "until it is considered aged enough to be downgraded to a warm block. "
1638
 
                            "This specifies the percentage ratio of that number of hits to the "
1639
 
                            "total number of blocks in key cache"),
1640
 
                            NULL,
1641
 
                            sys_var_key_cache_age_threshold_update,
1642
 
                            300,
1643
 
                            100, 
1644
 
                            UINT32_MAX,
1645
 
                            0);
1646
 
 
1647
 
static DRIZZLE_SYSVAR_UINT(key_cache_division_limit, myisam_key_cache_division_limit,
1648
 
                            PLUGIN_VAR_RQCMDARG,
1649
 
                            N_("The minimum percentage of warm blocks in key cache"),
1650
 
                            NULL,
1651
 
                            sys_var_key_cache_division_limit_update,
1652
 
                            100,
1653
 
                            1, 
1654
 
                            100,
1655
 
                            0);
1656
 
 
1657
 
static DRIZZLE_SYSVAR_UINT(key_cache_size,
1658
 
                            myisam_key_cache_size,
1659
 
                            PLUGIN_VAR_RQCMDARG,
1660
 
                            N_("The size of the buffer used for index blocks for MyISAM tables. "
1661
 
                            "Increase this to get better index handling (for all reads and multiple "
1662
 
                            "writes) to as much as you can afford;"),
1663
 
                            NULL,
1664
 
                            sys_var_key_cache_size_update,
1665
 
                            KEY_CACHE_SIZE,
1666
 
                            1 * 1024 * 1024, 
1667
 
                            UINT32_MAX,
1668
 
                            IO_SIZE);
 
1813
 
 
1814
/****************************************************************************
 
1815
 * MyISAM MRR implementation: use DS-MRR
 
1816
 ***************************************************************************/
 
1817
 
 
1818
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
 
1819
                                     uint32_t n_ranges, uint32_t mode,
 
1820
                                     HANDLER_BUFFER *buf)
 
1821
{
 
1822
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
 
1823
                           seq, seq_init_param, n_ranges, mode, buf);
 
1824
}
 
1825
 
 
1826
int ha_myisam::multi_range_read_next(char **range_info)
 
1827
{
 
1828
  return ds_mrr.dsmrr_next(this, range_info);
 
1829
}
 
1830
 
 
1831
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
1832
                                               void *seq_init_param,
 
1833
                                               uint32_t n_ranges, uint32_t *bufsz,
 
1834
                                               uint32_t *flags, COST_VECT *cost)
 
1835
{
 
1836
  /*
 
1837
    This call is here because there is no location where this->table would
 
1838
    already be known.
 
1839
    TODO: consider moving it into some per-query initialization call.
 
1840
  */
 
1841
  ds_mrr.init(this, table);
 
1842
  return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
 
1843
                                 flags, cost);
 
1844
}
 
1845
 
 
1846
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
 
1847
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
1848
{
 
1849
  ds_mrr.init(this, table);
 
1850
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 
1851
}
 
1852
 
 
1853
/* MyISAM MRR implementation ends */
 
1854
 
 
1855
 
 
1856
/* Index condition pushdown implementation*/
 
1857
 
 
1858
 
 
1859
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
 
1860
{
 
1861
  pushed_idx_cond_keyno= keyno_arg;
 
1862
  pushed_idx_cond= idx_cond_arg;
 
1863
  in_range_check_pushed_down= true;
 
1864
  if (active_index == pushed_idx_cond_keyno)
 
1865
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
 
1866
  return NULL;
 
1867
}
 
1868
 
 
1869
static DRIZZLE_SYSVAR_UINT(block_size, block_size,
 
1870
                           PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
1871
                           N_("Block size to be used for MyISAM index pages."),
 
1872
                           NULL, NULL, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, 
 
1873
                           MI_MAX_KEY_BLOCK_LENGTH, 0);
1669
1874
 
1670
1875
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
1671
 
                            PLUGIN_VAR_RQCMDARG,
1672
 
                            N_("Number of threads to use when repairing MyISAM tables. The value of "
1673
 
                            "1 disables parallel repair."),
1674
 
                            NULL, NULL, 1, 1, UINT32_MAX, 0);
 
1876
                           PLUGIN_VAR_RQCMDARG,
 
1877
                           N_("Number of threads to use when repairing MyISAM tables. The value of "
 
1878
                              "1 disables parallel repair."),
 
1879
                           NULL, NULL, 1, 1, UINT32_MAX, 0);
1675
1880
 
1676
1881
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1677
1882
                                PLUGIN_VAR_RQCMDARG,
1681
1886
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
1682
1887
                                PLUGIN_VAR_RQCMDARG,
1683
1888
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
1684
 
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
 
1889
                                NULL, NULL, 8192*1024, 1024, UINT64_MAX, 0);
1685
1890
 
1686
1891
extern uint32_t data_pointer_size;
1687
1892
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
1688
 
                            PLUGIN_VAR_RQCMDARG,
1689
 
                            N_("Default pointer size to be used for MyISAM tables."),
1690
 
                            NULL, NULL, 6, 2, 7, 0);
 
1893
                           PLUGIN_VAR_RQCMDARG,
 
1894
                           N_("Default pointer size to be used for MyISAM tables."),
 
1895
                           NULL, NULL, 6, 2, 7, 0);
1691
1896
 
1692
 
static drizzle_sys_var* sys_variables[]= {
1693
 
  DRIZZLE_SYSVAR(key_cache_block_size),
1694
 
  DRIZZLE_SYSVAR(key_cache_size),
1695
 
  DRIZZLE_SYSVAR(key_cache_division_limit),
1696
 
  DRIZZLE_SYSVAR(key_cache_age_threshold),
 
1897
static struct st_mysql_sys_var* system_variables[]= {
 
1898
  DRIZZLE_SYSVAR(block_size),
1697
1899
  DRIZZLE_SYSVAR(repair_threads),
1698
1900
  DRIZZLE_SYSVAR(max_sort_file_size),
1699
1901
  DRIZZLE_SYSVAR(sort_buffer_size),
1702
1904
};
1703
1905
 
1704
1906
 
1705
 
DRIZZLE_DECLARE_PLUGIN
 
1907
mysql_declare_plugin(myisam)
1706
1908
{
1707
 
  DRIZZLE_VERSION_ID,
 
1909
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1708
1910
  "MyISAM",
1709
1911
  "1.0",
1710
1912
  "MySQL AB",
1711
1913
  "Default engine as of MySQL 3.23 with great performance",
1712
1914
  PLUGIN_LICENSE_GPL,
1713
1915
  myisam_init, /* Plugin Init */
1714
 
  sys_variables,           /* system variables */
 
1916
  myisam_deinit, /* Plugin Deinit */
 
1917
  NULL,                       /* status variables                */
 
1918
  system_variables,           /* system variables */
1715
1919
  NULL                        /* config options                  */
1716
1920
}
1717
 
DRIZZLE_DECLARE_PLUGIN_END;
 
1921
mysql_declare_plugin_end;