~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/ha_myisam.cc

  • Committer: Brian Aker
  • Date: 2010-02-11 22:43:58 UTC
  • Revision ID: brian@gaz-20100211224358-y0gdvnat2ahg4c1e
Disabling support for memcached plugins until we can test for version of
memcached.

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
 
#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>
 
17
 
 
18
#include "config.h"
 
19
#include "drizzled/internal/my_bit.h"
 
20
#include "myisampack.h"
26
21
#include "ha_myisam.h"
27
 
#include "myisamdef.h"
28
 
#include <drizzled/drizzled_error_messages.h>
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
 
 
 
22
#include "myisam_priv.h"
 
23
#include "drizzled/my_getopt.h"
 
24
#include "drizzled/internal/my_bit.h"
 
25
#include "drizzled/internal/m_string.h"
 
26
#include "drizzled/util/test.h"
 
27
#include "drizzled/error.h"
 
28
#include "drizzled/errmsg_print.h"
 
29
#include "drizzled/gettext.h"
 
30
#include "drizzled/session.h"
 
31
#include "drizzled/set_var.h"
 
32
#include <drizzled/plugin.h>
 
33
#include "drizzled/plugin/client.h"
 
34
#include "drizzled/table.h"
 
35
#include "drizzled/field/timestamp.h"
 
36
#include "drizzled/memory/multi_malloc.h"
 
37
 
 
38
#include <string>
 
39
#include <sstream>
 
40
#include <map>
 
41
#include <algorithm>
 
42
 
 
43
using namespace std;
 
44
using namespace drizzled;
 
45
 
 
46
extern pthread_mutex_t LOCK_global_system_variables;
 
47
static const string engine_name("MyISAM");
 
48
 
 
49
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
 
50
 
 
51
static uint32_t repair_threads;
 
52
static uint32_t myisam_key_cache_block_size;
 
53
static uint32_t myisam_key_cache_size;
 
54
static uint32_t myisam_key_cache_division_limit;
 
55
static uint32_t myisam_key_cache_age_threshold;
 
56
static uint64_t max_sort_file_size;
 
57
static uint64_t sort_buffer_size;
44
58
 
45
59
/*****************************************************************************
46
60
** MyISAM tables
47
61
*****************************************************************************/
48
62
 
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);
 
63
static const char *ha_myisam_exts[] = {
 
64
  ".MYI",
 
65
  ".MYD",
 
66
  NULL
 
67
};
 
68
 
 
69
class MyisamEngine : public plugin::StorageEngine
 
70
{
 
71
public:
 
72
  MyisamEngine(string name_arg)
 
73
   : plugin::StorageEngine(name_arg,
 
74
                                     HTON_HAS_DATA_DICTIONARY |
 
75
                                     HTON_CAN_INDEX_BLOBS |
 
76
                                     HTON_STATS_RECORDS_IS_EXACT |
 
77
                                     HTON_TEMPORARY_ONLY |
 
78
                                     HTON_NULL_IN_KEY |
 
79
                                     HTON_HAS_RECORDS |
 
80
                                     HTON_DUPLICATE_POS |
 
81
                                     HTON_AUTO_PART_KEY |
 
82
                                     HTON_SKIP_STORE_LOCK |
 
83
                                     HTON_FILE_BASED ) {}
 
84
 
 
85
  ~MyisamEngine()
 
86
  { }
 
87
 
 
88
  virtual Cursor *create(TableShare &table,
 
89
                         memory::Root *mem_root)
 
90
  {
 
91
    return new (mem_root) ha_myisam(*this, table);
 
92
  }
 
93
 
 
94
  const char **bas_ext() const {
 
95
    return ha_myisam_exts;
 
96
  }
 
97
 
 
98
  int doCreateTable(Session *, const char *table_name,
 
99
                    Table& table_arg,
 
100
                    message::Table&);
 
101
 
 
102
  int doRenameTable(Session*, const char *from, const char *to);
 
103
 
 
104
  int doDropTable(Session&, const string table_name);
 
105
 
 
106
  int doGetTableDefinition(Session& session,
 
107
                           const char* path,
 
108
                           const char *db,
 
109
                           const char *table_name,
 
110
                           const bool is_tmp,
 
111
                           message::Table *table_proto);
 
112
 
 
113
  /* Temp only engine, so do not return values. */
 
114
  void doGetTableNames(CachedDirectory &, string& , set<string>&) { };
 
115
 
 
116
  uint32_t max_supported_keys()          const { return MI_MAX_KEY; }
 
117
  uint32_t max_supported_key_length()    const { return MI_MAX_KEY_LENGTH; }
 
118
  uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
 
119
 
 
120
  uint32_t index_flags(enum  ha_key_alg) const
 
121
  {
 
122
    return (HA_READ_NEXT |
 
123
            HA_READ_PREV |
 
124
            HA_READ_RANGE |
 
125
            HA_READ_ORDER |
 
126
            HA_KEYREAD_ONLY);
 
127
  }
 
128
};
 
129
 
 
130
int MyisamEngine::doGetTableDefinition(Session&,
 
131
                                       const char* path,
 
132
                                       const char *,
 
133
                                       const char *,
 
134
                                       const bool,
 
135
                                       message::Table *table_proto)
 
136
{
 
137
  int error= ENOENT;
 
138
  ProtoCache::iterator iter;
 
139
 
 
140
  pthread_mutex_lock(&proto_cache_mutex);
 
141
  iter= proto_cache.find(path);
 
142
 
 
143
  if (iter!= proto_cache.end())
 
144
  {
 
145
    if (table_proto)
 
146
      table_proto->CopyFrom(((*iter).second));
 
147
    error= EEXIST;
 
148
  }
 
149
  pthread_mutex_unlock(&proto_cache_mutex);
 
150
 
 
151
  return error;
54
152
}
55
153
 
56
 
// collect errors printed by mi_check routines
 
154
/* 
 
155
  Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
 
156
*/
57
157
 
58
 
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
59
 
                               const char *fmt, va_list args)
 
158
static void mi_check_print_msg(MI_CHECK *,      const char* ,
 
159
                               const char *, va_list )
60
160
{
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;
101
161
}
102
162
 
103
163
 
104
164
/*
105
 
  Convert TABLE object to MyISAM key and column definition
 
165
  Convert Table object to MyISAM key and column definition
106
166
 
107
167
  SYNOPSIS
108
168
    table2myisam()
109
 
      table_arg   in     TABLE object.
 
169
      table_arg   in     Table object.
110
170
      keydef_out  out    MyISAM key definition.
111
171
      recinfo_out out    MyISAM column definition.
112
172
      records_out out    Number of fields.
117
177
    table conformance in merge engine.
118
178
 
119
179
    The caller needs to free *recinfo_out after use. Since *recinfo_out
120
 
    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
 
180
    and *keydef_out are allocated with a multi_malloc, *keydef_out
121
181
    is freed automatically when *recinfo_out is freed.
122
182
 
123
183
  RETURN VALUE
125
185
    !0 error code
126
186
*/
127
187
 
128
 
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
129
 
                 MI_COLUMNDEF **recinfo_out, uint *records_out)
 
188
static int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
 
189
                        MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
130
190
{
131
 
  uint i, j, recpos, minpos, fieldpos, temp_length, length;
 
191
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
132
192
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
133
 
  uchar *record;
 
193
  unsigned char *record;
134
194
  KEY *pos;
135
195
  MI_KEYDEF *keydef;
136
196
  MI_COLUMNDEF *recinfo, *recinfo_pos;
137
197
  HA_KEYSEG *keyseg;
138
 
  TABLE_SHARE *share= table_arg->s;
139
 
  uint options= share->db_options_in_use;
140
 
  if (!(my_multi_malloc(MYF(MY_WME),
 
198
  TableShare *share= table_arg->s;
 
199
  uint32_t options= share->db_options_in_use;
 
200
  if (!(memory::multi_malloc(false,
141
201
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
142
202
          keydef_out, share->keys * sizeof(MI_KEYDEF),
143
 
          &keyseg,
144
 
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
145
 
          NullS)))
146
 
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
 
203
          &keyseg, (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
204
          NULL)))
 
205
    return(HA_ERR_OUT_OF_MEM);
147
206
  keydef= *keydef_out;
148
207
  recinfo= *recinfo_out;
149
208
  pos= table_arg->key_info;
166
225
      {
167
226
        if (pos->key_part[j].length > 8 &&
168
227
            (type == HA_KEYTYPE_TEXT ||
169
 
             type == HA_KEYTYPE_NUM ||
170
228
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
171
229
        {
172
230
          /* No blobs here */
190
248
      {
191
249
        keydef[i].seg[j].null_bit= field->null_bit;
192
250
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
193
 
                                           (uchar*) table_arg->record[0]);
 
251
                                           (unsigned char*) table_arg->record[0]);
194
252
      }
195
253
      else
196
254
      {
212
270
  record= table_arg->record[0];
213
271
  recpos= 0;
214
272
  recinfo_pos= recinfo;
215
 
  while (recpos < (uint) share->reclength)
 
273
  while (recpos < (uint) share->stored_rec_length)
216
274
  {
217
275
    Field **field, *found= 0;
218
276
    minpos= share->reclength;
258
316
    {
259
317
      recinfo_pos->null_bit= found->null_bit;
260
318
      recinfo_pos->null_pos= (uint) (found->null_ptr -
261
 
                                     (uchar*) table_arg->record[0]);
 
319
                                     (unsigned char*) table_arg->record[0]);
262
320
    }
263
321
    else
264
322
    {
272
330
  return(0);
273
331
}
274
332
 
 
333
int ha_myisam::reset_auto_increment(uint64_t value)
 
334
{
 
335
  file->s->state.auto_increment= value;
 
336
  return 0;
 
337
}
275
338
 
276
339
/*
277
340
  Check for underlying table conformance
313
376
      (should be corretly detected in table2myisam).
314
377
*/
315
378
 
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)
 
379
static int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
 
380
                            uint32_t t1_keys, uint32_t t1_recs,
 
381
                            MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
 
382
                            uint32_t t2_keys, uint32_t t2_recs, bool strict)
320
383
{
321
 
  uint i, j;
 
384
  uint32_t i, j;
322
385
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
323
386
  {
324
387
    return(1);
351
414
      {
352
415
        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
353
416
            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
354
 
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
 
417
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1;
355
418
        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
356
419
                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
357
 
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
 
420
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1;
358
421
      }
359
422
 
360
423
      if (t1_keysegs_j__type != t2_keysegs[j].type ||
388
451
}
389
452
 
390
453
 
391
 
extern "C" {
392
 
 
393
454
volatile int *killed_ptr(MI_CHECK *param)
394
455
{
395
456
  /* In theory Unsafe conversion, but should be ok for now */
396
 
  return (int*) &(((THD *)(param->thd))->killed);
 
457
  return (int*) &(((Session *)(param->session))->killed);
397
458
}
398
459
 
399
460
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
440
501
*/
441
502
 
442
503
void _mi_report_crashed(MI_INFO *file, const char *message,
443
 
                        const char *sfile, uint sline)
 
504
                        const char *sfile, uint32_t sline)
444
505
{
445
 
  THD *cur_thd;
446
 
  LIST *element;
 
506
  Session *cur_session;
447
507
  pthread_mutex_lock(&file->s->intern_lock);
448
 
  if ((cur_thd= (THD*) file->in_use.data))
449
 
    sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
 
508
  if ((cur_session= file->in_use))
 
509
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
 
510
                    cur_session->thread_id,
450
511
                    sfile, sline);
451
512
  else
452
 
    sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline);
 
513
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
453
514
  if (message)
454
 
    sql_print_error("%s", message);
455
 
  for (element= file->s->in_use; element; element= list_rest(element))
 
515
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
 
516
  list<Session *>::iterator it= file->s->in_use->begin();
 
517
  while (it != file->s->in_use->end())
456
518
  {
457
 
    sql_print_error("%s", "Unknown thread accessing table");
 
519
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
 
520
    ++it;
458
521
  }
459
522
  pthread_mutex_unlock(&file->s->intern_lock);
460
523
}
461
524
 
462
 
}
463
 
 
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
 
{}
475
 
 
476
 
handler *ha_myisam::clone(MEM_ROOT *mem_root)
 
525
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
 
526
                     TableShare &table_arg)
 
527
  : Cursor(engine_arg, table_arg),
 
528
  file(0),
 
529
  can_enable_indexes(true),
 
530
  is_ordered(true)
 
531
{ }
 
532
 
 
533
Cursor *ha_myisam::clone(memory::Root *mem_root)
477
534
{
478
 
  ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
 
535
  ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
479
536
  if (new_handler)
480
537
    new_handler->file->state= file->state;
481
538
  return new_handler;
482
539
}
483
540
 
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)))
 
541
const char *ha_myisam::index_type(uint32_t )
498
542
{
499
543
  return "BTREE";
500
544
}
501
545
 
502
546
/* Name is here without an extension */
503
 
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
 
547
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
504
548
{
505
549
  MI_KEYDEF *keyinfo;
506
550
  MI_COLUMNDEF *recinfo= 0;
507
 
  uint recs;
508
 
  uint i;
 
551
  uint32_t recs;
 
552
  uint32_t i;
509
553
 
510
554
  /*
511
555
    If the user wants to have memory mapped data files, add an
522
566
    open of a table that is in use by other threads already (if the
523
567
    MyISAM share exists already).
524
568
  */
525
 
  if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
526
 
    return (my_errno ? my_errno : -1);
 
569
  if (!(file=mi_open(name, mode, test_if_locked)))
 
570
    return (errno ? errno : -1);
 
571
 
527
572
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
528
573
  {
529
 
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
574
    if ((errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
530
575
    {
531
 
      /* purecov: begin inspected */
532
576
      goto err;
533
 
      /* purecov: end */
534
577
    }
535
578
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
536
579
                         file->s->keyinfo, file->s->rec,
537
580
                         file->s->base.keys, file->s->base.fields, true))
538
581
    {
539
 
      /* purecov: begin inspected */
540
 
      my_errno= HA_ERR_CRASHED;
 
582
      errno= HA_ERR_CRASHED;
541
583
      goto err;
542
 
      /* purecov: end */
543
584
    }
544
585
  }
545
 
  
 
586
 
546
587
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
547
 
    VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
 
588
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
548
589
 
549
590
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
550
591
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
551
 
    VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
 
592
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
552
593
  if (!table->s->db_record_offset)
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();
 
594
    is_ordered= false;
 
595
 
 
596
 
 
597
  keys_with_parts.reset();
558
598
  for (i= 0; i < table->s->keys; i++)
559
599
  {
560
600
    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
563
603
    KEY_PART_INFO *kp_end= kp + table->key_info[i].key_parts;
564
604
    for (; kp != kp_end; kp++)
565
605
    {
566
 
      if (!kp->field->part_of_key.is_set(i))
 
606
      if (!kp->field->part_of_key.test(i))
567
607
      {
568
 
        keys_with_parts.set_bit(i);
 
608
        keys_with_parts.set(i);
569
609
        break;
570
610
      }
571
611
    }
572
612
  }
573
 
  my_errno= 0;
 
613
  errno= 0;
574
614
  goto end;
575
615
 err:
576
616
  this->close();
577
617
 end:
578
618
  /*
579
 
    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
 
619
    Both recinfo and keydef are allocated by multi_malloc(), thus only
580
620
    recinfo must be freed.
581
621
  */
582
622
  if (recinfo)
583
 
    my_free((uchar*) recinfo, MYF(0));
584
 
  return my_errno;
 
623
    free((unsigned char*) recinfo);
 
624
  return errno;
585
625
}
586
626
 
587
627
int ha_myisam::close(void)
591
631
  return mi_close(tmp);
592
632
}
593
633
 
594
 
int ha_myisam::write_row(uchar *buf)
 
634
int ha_myisam::write_row(unsigned char *buf)
595
635
{
596
636
  ha_statistic_increment(&SSV::ha_write_count);
597
637
 
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
 
 
602
638
  /*
603
639
    If we have an auto_increment column and we are writing a changed row
604
640
    or a new row, then update the auto_increment value in the record.
612
648
  return mi_write(file,buf);
613
649
}
614
650
 
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;
 
651
 
 
652
int ha_myisam::repair(Session *session, MI_CHECK &param, bool do_optimize)
 
653
{
 
654
  int error=0;
 
655
  uint32_t local_testflag= param.testflag;
817
656
  bool optimize_done= !do_optimize, statistics_done=0;
818
 
  const char *old_proc_info=thd->proc_info;
 
657
  const char *old_proc_info= session->get_proc_info();
819
658
  char fixed_name[FN_REFLEN];
820
659
  MYISAM_SHARE* share = file->s;
821
660
  ha_rows rows= file->state->records;
830
669
  */
831
670
  if (file->dfile == -1)
832
671
  {
833
 
    sql_print_information("Retrying repair of: '%s' failed. "
 
672
    errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' failed. "
834
673
                          "Please try REPAIR EXTENDED or myisamchk",
835
674
                          table->s->path.str);
836
675
    return(HA_ADMIN_FAILED);
840
679
  param.table_name= table->alias;
841
680
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
842
681
  param.using_global_keycache = 1;
843
 
  param.thd= thd;
844
 
  param.tmpdir= &mysql_tmpdir_list;
 
682
  param.session= session;
845
683
  param.out_flag= 0;
846
 
  stpcpy(fixed_name,file->filename);
 
684
  param.sort_buffer_length= (size_t)sort_buffer_size;
 
685
  strcpy(fixed_name,file->filename);
847
686
 
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
  // Don't lock tables if we have used LOCK Table
 
688
  if (mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
851
689
  {
852
 
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
 
690
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
853
691
    return(HA_ADMIN_FAILED);
854
692
  }
855
693
 
861
699
    uint64_t key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
862
700
                        mi_get_mask_all_keys_active(share->base.keys) :
863
701
                        share->state.key_map);
864
 
    uint testflag=param.testflag;
 
702
    uint32_t testflag=param.testflag;
865
703
    if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
866
704
        (local_testflag & T_REP_BY_SORT))
867
705
    {
868
706
      local_testflag|= T_STATISTICS;
869
707
      param.testflag|= T_STATISTICS;            // We get this for free
870
708
      statistics_done=1;
871
 
      if (thd->variables.myisam_repair_threads>1)
 
709
      if (repair_threads > 1)
872
710
      {
873
711
        char buf[40];
874
712
        /* TODO: respect myisam_repair_threads variable */
875
 
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
876
 
        thd_proc_info(thd, buf);
 
713
        snprintf(buf, 40, "Repair with %d threads", internal::my_count_bits(key_map));
 
714
        session->set_proc_info(buf);
877
715
        error = mi_repair_parallel(&param, file, fixed_name,
878
716
            param.testflag & T_QUICK);
879
 
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
 
717
        session->set_proc_info("Repair done"); // to reset proc_info, as
880
718
                                      // it was pointing to local buffer
881
719
      }
882
720
      else
883
721
      {
884
 
        thd_proc_info(thd, "Repair by sorting");
 
722
        session->set_proc_info("Repair by sorting");
885
723
        error = mi_repair_by_sort(&param, file, fixed_name,
886
724
            param.testflag & T_QUICK);
887
725
      }
888
726
    }
889
727
    else
890
728
    {
891
 
      thd_proc_info(thd, "Repair with keycache");
 
729
      session->set_proc_info("Repair with keycache");
892
730
      param.testflag &= ~T_REP_BY_SORT;
893
731
      error=  mi_repair(&param, file, fixed_name,
894
732
                        param.testflag & T_QUICK);
902
740
        (share->state.changed & STATE_NOT_SORTED_PAGES))
903
741
    {
904
742
      optimize_done=1;
905
 
      thd_proc_info(thd, "Sorting index");
 
743
      session->set_proc_info("Sorting index");
906
744
      error=mi_sort_index(&param,file,fixed_name);
907
745
    }
908
746
    if (!statistics_done && (local_testflag & T_STATISTICS))
910
748
      if (share->state.changed & STATE_NOT_ANALYZED)
911
749
      {
912
750
        optimize_done=1;
913
 
        thd_proc_info(thd, "Analyzing");
 
751
        session->set_proc_info("Analyzing");
914
752
        error = chk_key(&param, file);
915
753
      }
916
754
      else
917
755
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
918
756
    }
919
757
  }
920
 
  thd_proc_info(thd, "Saving state");
 
758
  session->set_proc_info("Saving state");
921
759
  if (!error)
922
760
  {
923
761
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
945
783
    {
946
784
      char llbuff[22],llbuff2[22];
947
785
      mi_check_print_warning(&param,"Number of rows changed from %s to %s",
948
 
                             llstr(rows,llbuff),
949
 
                             llstr(file->state->records,llbuff2));
 
786
                             internal::llstr(rows,llbuff),
 
787
                             internal::llstr(file->state->records,llbuff2));
950
788
    }
951
789
  }
952
790
  else
955
793
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
956
794
    update_state_info(&param, file, 0);
957
795
  }
958
 
  thd_proc_info(thd, old_proc_info);
959
 
  if (!thd->locked_tables)
960
 
    mi_lock_database(file,F_UNLCK);
 
796
  session->set_proc_info(old_proc_info);
 
797
  mi_lock_database(file,F_UNLCK);
 
798
 
961
799
  return(error ? HA_ADMIN_FAILED :
962
800
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
963
801
}
964
802
 
965
803
 
966
804
/*
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
 
/*
1013
805
  Disable indexes, making it persistent if requested.
1014
806
 
1015
807
  SYNOPSIS
1029
821
    HA_ERR_WRONG_COMMAND  mode not implemented.
1030
822
*/
1031
823
 
1032
 
int ha_myisam::disable_indexes(uint mode)
 
824
int ha_myisam::disable_indexes(uint32_t mode)
1033
825
{
1034
826
  int error;
1035
827
 
1068
860
    Enable indexes, which might have been disabled by disable_index() before.
1069
861
    The modes without _SAVE work only if both data and indexes are empty,
1070
862
    since the MyISAM repair would enable them persistently.
1071
 
    To be sure in these cases, call handler::delete_all_rows() before.
 
863
    To be sure in these cases, call Cursor::delete_all_rows() before.
1072
864
 
1073
865
  IMPLEMENTATION
1074
866
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
1081
873
    HA_ERR_WRONG_COMMAND  mode not implemented.
1082
874
*/
1083
875
 
1084
 
int ha_myisam::enable_indexes(uint mode)
 
876
int ha_myisam::enable_indexes(uint32_t mode)
1085
877
{
1086
878
  int error;
1087
879
 
1102
894
  }
1103
895
  else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
1104
896
  {
1105
 
    THD *thd=current_thd;
 
897
    Session *session=current_session;
1106
898
    MI_CHECK param;
1107
 
    const char *save_proc_info=thd->proc_info;
1108
 
    thd_proc_info(thd, "Creating index");
 
899
    const char *save_proc_info= session->get_proc_info();
 
900
    session->set_proc_info("Creating index");
1109
901
    myisamchk_init(&param);
1110
902
    param.op_name= "recreating_index";
1111
903
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
1112
904
                     T_CREATE_MISSING_KEYS);
1113
905
    param.myf_rw&= ~MY_WAIT_IF_FULL;
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)
 
906
    param.sort_buffer_length=  (size_t)sort_buffer_size;
 
907
    param.stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
 
908
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
1118
909
    {
1119
 
      sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
1120
 
                        my_errno, param.db_name, param.table_name);
 
910
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
 
911
                        errno, param.db_name, param.table_name);
1121
912
      /* Repairing by sort failed. Now try standard repair method. */
1122
913
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
1123
 
      error= (repair(thd,param,0) != HA_ADMIN_OK);
 
914
      error= (repair(session,param,0) != HA_ADMIN_OK);
1124
915
      /*
1125
916
        If the standard repair succeeded, clear all error messages which
1126
917
        might have been set by the first repair. They can still be seen
1127
918
        with SHOW WARNINGS then.
1128
919
      */
1129
920
      if (! error)
1130
 
        thd->clear_error();
 
921
        session->clear_error();
1131
922
    }
1132
923
    info(HA_STATUS_CONST);
1133
 
    thd_proc_info(thd, save_proc_info);
 
924
    session->set_proc_info(save_proc_info);
1134
925
  }
1135
926
  else
1136
927
  {
1158
949
 
1159
950
int ha_myisam::indexes_are_disabled(void)
1160
951
{
1161
 
  
 
952
 
1162
953
  return mi_indexes_are_disabled(file);
1163
954
}
1164
955
 
1179
970
 
1180
971
void ha_myisam::start_bulk_insert(ha_rows rows)
1181
972
{
1182
 
  THD *thd= current_thd;
1183
 
  ulong size= min(thd->variables.read_buff_size,
1184
 
                  (ulong) (table->s->avg_row_length*rows));
 
973
  Session *session= current_session;
 
974
  ulong size= session->variables.read_buff_size;
1185
975
 
1186
976
  /* don't enable row cache if too few rows */
1187
977
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
1190
980
  can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
1191
981
                                            file->s->base.keys);
1192
982
 
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
 
983
  /*
 
984
    Only disable old index if the table was empty and we are inserting
 
985
    a lot of rows.
 
986
    We should not do this for only a few rows as this is slower and
 
987
    we don't want to update the key statistics based of only a few rows.
 
988
  */
 
989
  if (file->state->records == 0 && can_enable_indexes &&
 
990
      (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
 
991
    mi_disable_non_unique_index(file,rows);
 
992
  else
1205
993
    if (!file->bulk_insert &&
1206
994
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1207
995
    {
1208
 
      mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
 
996
      mi_init_bulk_insert(file,
 
997
                          (size_t)session->variables.bulk_insert_buff_size,
 
998
                          rows);
1209
999
    }
1210
 
  }
1211
 
  return;
1212
1000
}
1213
1001
 
1214
1002
/*
1233
1021
}
1234
1022
 
1235
1023
 
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
 
 
1025
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
1283
1026
{
1284
1027
  ha_statistic_increment(&SSV::ha_update_count);
1285
1028
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1287
1030
  return mi_update(file,old_data,new_data);
1288
1031
}
1289
1032
 
1290
 
int ha_myisam::delete_row(const uchar *buf)
 
1033
int ha_myisam::delete_row(const unsigned char *buf)
1291
1034
{
1292
1035
  ha_statistic_increment(&SSV::ha_delete_count);
1293
1036
  return mi_delete(file,buf);
1294
1037
}
1295
1038
 
1296
 
C_MODE_START
1297
1039
 
1298
 
bool index_cond_func_myisam(void *arg)
 
1040
int ha_myisam::index_init(uint32_t idx, bool )
1299
1041
{
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
 
1315
1042
  active_index=idx;
1316
1043
  //in_range_read= false;
1317
 
  if (pushed_idx_cond_keyno == idx)
1318
 
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
1319
 
  return 0; 
 
1044
  return 0;
1320
1045
}
1321
1046
 
1322
1047
 
1323
1048
int ha_myisam::index_end()
1324
1049
{
1325
1050
  active_index=MAX_KEY;
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; 
 
1051
  return 0;
1331
1052
}
1332
1053
 
1333
1054
 
1334
 
int ha_myisam::index_read_map(uchar *buf, const uchar *key,
 
1055
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
1335
1056
                              key_part_map keypart_map,
1336
1057
                              enum ha_rkey_function find_flag)
1337
1058
{
1342
1063
  return error;
1343
1064
}
1344
1065
 
1345
 
int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
 
1066
int ha_myisam::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
1346
1067
                                  key_part_map keypart_map,
1347
1068
                                  enum ha_rkey_function find_flag)
1348
1069
{
1352
1073
  return error;
1353
1074
}
1354
1075
 
1355
 
int ha_myisam::index_read_last_map(uchar *buf, const uchar *key,
 
1076
int ha_myisam::index_read_last_map(unsigned char *buf, const unsigned char *key,
1356
1077
                                   key_part_map keypart_map)
1357
1078
{
1358
1079
  assert(inited==INDEX);
1363
1084
  return(error);
1364
1085
}
1365
1086
 
1366
 
int ha_myisam::index_next(uchar *buf)
 
1087
int ha_myisam::index_next(unsigned char *buf)
1367
1088
{
1368
1089
  assert(inited==INDEX);
1369
1090
  ha_statistic_increment(&SSV::ha_read_next_count);
1372
1093
  return error;
1373
1094
}
1374
1095
 
1375
 
int ha_myisam::index_prev(uchar *buf)
 
1096
int ha_myisam::index_prev(unsigned char *buf)
1376
1097
{
1377
1098
  assert(inited==INDEX);
1378
1099
  ha_statistic_increment(&SSV::ha_read_prev_count);
1381
1102
  return error;
1382
1103
}
1383
1104
 
1384
 
int ha_myisam::index_first(uchar *buf)
 
1105
int ha_myisam::index_first(unsigned char *buf)
1385
1106
{
1386
1107
  assert(inited==INDEX);
1387
1108
  ha_statistic_increment(&SSV::ha_read_first_count);
1390
1111
  return error;
1391
1112
}
1392
1113
 
1393
 
int ha_myisam::index_last(uchar *buf)
 
1114
int ha_myisam::index_last(unsigned char *buf)
1394
1115
{
1395
1116
  assert(inited==INDEX);
1396
1117
  ha_statistic_increment(&SSV::ha_read_last_count);
1399
1120
  return error;
1400
1121
}
1401
1122
 
1402
 
int ha_myisam::index_next_same(uchar *buf,
1403
 
                               const uchar *key __attribute__((unused)),
1404
 
                               uint length __attribute__((unused)))
 
1123
int ha_myisam::index_next_same(unsigned char *buf,
 
1124
                               const unsigned char *,
 
1125
                               uint32_t )
1405
1126
{
1406
1127
  int error;
1407
1128
  assert(inited==INDEX);
1423
1144
  //if (!eq_range_arg)
1424
1145
  //  in_range_read= true;
1425
1146
 
1426
 
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
1147
  res= Cursor::read_range_first(start_key, end_key, eq_range_arg, sorted);
1427
1148
 
1428
1149
  //if (res)
1429
1150
  //  in_range_read= false;
1433
1154
 
1434
1155
int ha_myisam::read_range_next()
1435
1156
{
1436
 
  int res= handler::read_range_next();
 
1157
  int res= Cursor::read_range_next();
1437
1158
  //if (res)
1438
1159
  //  in_range_read= false;
1439
1160
  return res;
1447
1168
  return mi_reset(file);                        // Free buffers
1448
1169
}
1449
1170
 
1450
 
int ha_myisam::rnd_next(uchar *buf)
 
1171
int ha_myisam::rnd_next(unsigned char *buf)
1451
1172
{
1452
1173
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1453
1174
  int error=mi_scan(file, buf);
1455
1176
  return error;
1456
1177
}
1457
1178
 
1458
 
int ha_myisam::restart_rnd_next(uchar *buf, uchar *pos)
 
1179
int ha_myisam::restart_rnd_next(unsigned char *buf, unsigned char *pos)
1459
1180
{
1460
1181
  return rnd_pos(buf,pos);
1461
1182
}
1462
1183
 
1463
 
int ha_myisam::rnd_pos(uchar *buf, uchar *pos)
 
1184
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
1464
1185
{
1465
1186
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1466
 
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
 
1187
  int error=mi_rrnd(file, buf, internal::my_get_ptr(pos,ref_length));
1467
1188
  table->status=error ? STATUS_NOT_FOUND: 0;
1468
1189
  return error;
1469
1190
}
1470
1191
 
1471
1192
 
1472
 
void ha_myisam::position(const uchar *record __attribute__((unused)))
 
1193
void ha_myisam::position(const unsigned char *)
1473
1194
{
1474
 
  my_off_t row_position= mi_position(file);
1475
 
  my_store_ptr(ref, ref_length, row_position);
 
1195
  internal::my_off_t row_position= mi_position(file);
 
1196
  internal::my_store_ptr(ref, ref_length, row_position);
1476
1197
}
1477
1198
 
1478
 
int ha_myisam::info(uint flag)
 
1199
int ha_myisam::info(uint32_t flag)
1479
1200
{
1480
1201
  MI_ISAMINFO misam_info;
1481
1202
  char name_buff[FN_REFLEN];
1493
1214
  }
1494
1215
  if (flag & HA_STATUS_CONST)
1495
1216
  {
1496
 
    TABLE_SHARE *share= table->s;
 
1217
    TableShare *share= table->s;
1497
1218
    stats.max_data_file_length=  misam_info.max_data_file_length;
1498
1219
    stats.max_index_file_length= misam_info.max_index_file_length;
1499
1220
    stats.create_time= misam_info.create_time;
1500
1221
    ref_length= misam_info.reflength;
1501
1222
    share->db_options_in_use= misam_info.options;
1502
 
    stats.block_size= myisam_block_size;        /* record block size */
 
1223
    stats.block_size= myisam_key_cache_block_size;        /* record block size */
1503
1224
 
1504
1225
    /* Update share */
1505
1226
    if (share->tmp_table == NO_TMP_TABLE)
1506
1227
      pthread_mutex_lock(&share->mutex);
1507
 
    share->keys_in_use.set_prefix(share->keys);
1508
 
    share->keys_in_use.intersect_extended(misam_info.key_map);
1509
 
    share->keys_for_keyread.intersect(share->keys_in_use);
 
1228
    set_prefix(share->keys_in_use, share->keys);
 
1229
    /*
 
1230
     * Due to bug 394932 (32-bit solaris build failure), we need
 
1231
     * to convert the uint64_t key_map member of the misam_info
 
1232
     * structure in to a std::bitset so that we can logically and
 
1233
     * it with the share->key_in_use key_map.
 
1234
     */
 
1235
    ostringstream ostr;
 
1236
    string binary_key_map;
 
1237
    uint64_t num= misam_info.key_map;
 
1238
    /*
 
1239
     * Convert the uint64_t to a binary
 
1240
     * string representation of it.
 
1241
     */
 
1242
    while (num > 0)
 
1243
    {
 
1244
      uint64_t bin_digit= num % 2;
 
1245
      ostr << bin_digit;
 
1246
      num/= 2;
 
1247
    }
 
1248
    binary_key_map.append(ostr.str());
 
1249
    /*
 
1250
     * Now we have the binary string representation of the
 
1251
     * flags, we need to fill that string representation out
 
1252
     * with the appropriate number of bits. This is needed
 
1253
     * since key_map is declared as a std::bitset of a certain bit
 
1254
     * width that depends on the MAX_INDEXES variable. 
 
1255
     */
 
1256
    if (MAX_INDEXES <= 64)
 
1257
    {
 
1258
      size_t len= 72 - binary_key_map.length();
 
1259
      string all_zeros(len, '0');
 
1260
      binary_key_map.insert(binary_key_map.begin(),
 
1261
                            all_zeros.begin(),
 
1262
                            all_zeros.end());
 
1263
    }
 
1264
    else
 
1265
    {
 
1266
      size_t len= (MAX_INDEXES + 7) / 8 * 8;
 
1267
      string all_zeros(len, '0');
 
1268
      binary_key_map.insert(binary_key_map.begin(),
 
1269
                            all_zeros.begin(),
 
1270
                            all_zeros.end());
 
1271
    }
 
1272
    key_map tmp_map(binary_key_map);
 
1273
    share->keys_in_use&= tmp_map;
 
1274
    share->keys_for_keyread&= share->keys_in_use;
1510
1275
    share->db_record_offset= misam_info.record_offset;
1511
1276
    if (share->key_parts)
1512
1277
      memcpy(table->key_info[0].rec_per_key,
1520
1285
     if table is symlinked (Ie;  Real name is not same as generated name)
1521
1286
   */
1522
1287
    data_file_name= index_file_name= 0;
1523
 
    fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
 
1288
    internal::fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
1524
1289
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1525
1290
    if (strcmp(name_buff, misam_info.data_file_name))
1526
1291
      data_file_name=misam_info.data_file_name;
1527
 
    fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
 
1292
    internal::fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
1528
1293
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1529
1294
    if (strcmp(name_buff, misam_info.index_file_name))
1530
1295
      index_file_name=misam_info.index_file_name;
1532
1297
  if (flag & HA_STATUS_ERRKEY)
1533
1298
  {
1534
1299
    errkey  = misam_info.errkey;
1535
 
    my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
 
1300
    internal::my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
1536
1301
  }
1537
1302
  if (flag & HA_STATUS_TIME)
1538
1303
    stats.update_time = misam_info.update_time;
1545
1310
 
1546
1311
int ha_myisam::extra(enum ha_extra_function operation)
1547
1312
{
1548
 
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD)
1549
 
    return 0;
1550
1313
  return mi_extra(file, operation, 0);
1551
1314
}
1552
1315
 
1553
1316
int ha_myisam::reset(void)
1554
1317
{
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();
1559
1318
  return mi_reset(file);
1560
1319
}
1561
1320
 
1563
1322
 
1564
1323
int ha_myisam::extra_opt(enum ha_extra_function operation, uint32_t cache_size)
1565
1324
{
1566
 
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
1567
 
    return 0;
1568
1325
  return mi_extra(file, operation, (void*) &cache_size);
1569
1326
}
1570
1327
 
1573
1330
  return mi_delete_all_rows(file);
1574
1331
}
1575
1332
 
1576
 
int ha_myisam::delete_table(const char *name)
 
1333
int MyisamEngine::doDropTable(Session&, const string table_path)
1577
1334
{
1578
 
  return mi_delete_table(name);
 
1335
  ProtoCache::iterator iter;
 
1336
 
 
1337
  pthread_mutex_lock(&proto_cache_mutex);
 
1338
  iter= proto_cache.find(table_path.c_str());
 
1339
 
 
1340
  if (iter!= proto_cache.end())
 
1341
    proto_cache.erase(iter);
 
1342
 
 
1343
  pthread_mutex_unlock(&proto_cache_mutex);
 
1344
 
 
1345
  return mi_delete_table(table_path.c_str());
1579
1346
}
1580
1347
 
1581
1348
 
1582
 
int ha_myisam::external_lock(THD *thd, int lock_type)
 
1349
int ha_myisam::external_lock(Session *session, int lock_type)
1583
1350
{
1584
 
  file->in_use.data= thd;
 
1351
  file->in_use= session;
1585
1352
  return mi_lock_database(file, !table->s->tmp_table ?
1586
1353
                          lock_type : ((lock_type == F_UNLCK) ?
1587
1354
                                       F_UNLCK : F_EXTRA_LCK));
1588
1355
}
1589
1356
 
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)
 
1357
int MyisamEngine::doCreateTable(Session *, const char *table_name,
 
1358
                                Table& table_arg,
 
1359
                                message::Table& create_proto)
1614
1360
{
1615
1361
  int error;
1616
 
  uint create_flags= 0, records;
 
1362
  uint32_t create_flags= 0, create_records;
1617
1363
  char buff[FN_REFLEN];
1618
1364
  MI_KEYDEF *keydef;
1619
1365
  MI_COLUMNDEF *recinfo;
1620
1366
  MI_CREATE_INFO create_info;
1621
 
  TABLE_SHARE *share= table_arg->s;
1622
 
  uint options= share->db_options_in_use;
1623
 
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1624
 
    return(error); /* purecov: inspected */
 
1367
  TableShare *share= table_arg.s;
 
1368
  uint32_t options= share->db_options_in_use;
 
1369
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
 
1370
    return(error);
1625
1371
  memset(&create_info, 0, sizeof(create_info));
1626
 
  create_info.max_rows= share->max_rows;
1627
 
  create_info.reloc_rows= share->min_rows;
 
1372
  create_info.max_rows= create_proto.options().max_rows();
 
1373
  create_info.reloc_rows= create_proto.options().min_rows();
1628
1374
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1629
 
  create_info.auto_increment= (ha_create_info->auto_increment_value ?
1630
 
                               ha_create_info->auto_increment_value -1 :
 
1375
  create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
 
1376
                               create_proto.options().auto_increment_value() -1 :
1631
1377
                               (uint64_t) 0);
1632
 
  create_info.data_file_length= ((uint64_t) share->max_rows *
1633
 
                                 share->avg_row_length);
1634
 
  create_info.data_file_name= ha_create_info->data_file_name;
1635
 
  create_info.index_file_name= ha_create_info->index_file_name;
 
1378
  create_info.data_file_length= (create_proto.options().max_rows() *
 
1379
                                 create_proto.options().avg_row_length());
 
1380
  create_info.data_file_name= NULL;
 
1381
  create_info.index_file_name=  NULL;
1636
1382
  create_info.language= share->table_charset->number;
1637
1383
 
1638
 
  if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1384
  if (create_proto.type() == message::Table::TEMPORARY)
1639
1385
    create_flags|= HA_CREATE_TMP_TABLE;
1640
 
  if (ha_create_info->options & HA_CREATE_KEEP_FILES)
1641
 
    create_flags|= HA_CREATE_KEEP_FILES;
1642
1386
  if (options & HA_OPTION_PACK_RECORD)
1643
1387
    create_flags|= HA_PACK_RECORD;
1644
 
  if (options & HA_OPTION_CHECKSUM)
1645
 
    create_flags|= HA_CREATE_CHECKSUM;
1646
 
  if (options & HA_OPTION_DELAY_KEY_WRITE)
1647
 
    create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1648
1388
 
1649
 
  /* TODO: Check that the following fn_format is really needed */
1650
 
  error= mi_create(fn_format(buff, name, "", "",
 
1389
  /* TODO: Check that the following internal::fn_format is really needed */
 
1390
  error= mi_create(internal::fn_format(buff, table_name, "", "",
1651
1391
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
1652
1392
                   share->keys, keydef,
1653
 
                   records, recinfo,
 
1393
                   create_records, recinfo,
1654
1394
                   0, (MI_UNIQUEDEF*) 0,
1655
1395
                   &create_info, create_flags);
1656
 
  my_free((uchar*) recinfo, MYF(0));
1657
 
  return(error);
 
1396
  free((unsigned char*) recinfo);
 
1397
 
 
1398
  pthread_mutex_lock(&proto_cache_mutex);
 
1399
  proto_cache.insert(make_pair(table_name, create_proto));
 
1400
  pthread_mutex_unlock(&proto_cache_mutex);
 
1401
 
 
1402
  return error;
1658
1403
}
1659
1404
 
1660
1405
 
1661
 
int ha_myisam::rename_table(const char * from, const char * to)
 
1406
int MyisamEngine::doRenameTable(Session*,
 
1407
                                const char *from, const char *to)
1662
1408
{
1663
1409
  return mi_rename(from,to);
1664
1410
}
1665
1411
 
1666
1412
 
1667
 
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1668
 
                                   uint64_t increment __attribute__((unused)),
1669
 
                                   uint64_t nb_desired_values __attribute__((unused)),
 
1413
void ha_myisam::get_auto_increment(uint64_t ,
 
1414
                                   uint64_t ,
 
1415
                                   uint64_t ,
1670
1416
                                   uint64_t *first_value,
1671
1417
                                   uint64_t *nb_reserved_values)
1672
1418
{
1673
1419
  uint64_t nr;
1674
1420
  int error;
1675
 
  uchar key[MI_MAX_KEY_LENGTH];
 
1421
  unsigned char key[MI_MAX_KEY_LENGTH];
1676
1422
 
1677
1423
  if (!table->s->next_number_key_offset)
1678
1424
  {                                             // Autoincrement at key-start
1727
1473
      HA_READ_KEY_EXACT         Include the key in the range
1728
1474
      HA_READ_AFTER_KEY         Don't include key in range
1729
1475
 
1730
 
    max_key.flag can have one of the following values:  
 
1476
    max_key.flag can have one of the following values:
1731
1477
      HA_READ_BEFORE_KEY        Don't include key in range
1732
1478
      HA_READ_AFTER_KEY         Include all 'end_key' values in the range
1733
1479
 
1738
1484
                        the range.
1739
1485
*/
1740
1486
 
1741
 
ha_rows ha_myisam::records_in_range(uint inx, key_range *min_key,
 
1487
ha_rows ha_myisam::records_in_range(uint32_t inx, key_range *min_key,
1742
1488
                                    key_range *max_key)
1743
1489
{
1744
1490
  return (ha_rows) mi_records_in_range(file, (int) inx, min_key, max_key);
1745
1491
}
1746
1492
 
1747
1493
 
1748
 
uint ha_myisam::checksum() const
 
1494
uint32_t ha_myisam::checksum() const
1749
1495
{
1750
1496
  return (uint)file->state->checksum;
1751
1497
}
1752
1498
 
 
1499
static MyisamEngine *engine= NULL;
1753
1500
 
1754
 
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1755
 
                                           uint table_changes)
 
1501
static int myisam_init(plugin::Registry &registry)
1756
1502
{
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;
 
1503
  int error;
 
1504
  engine= new MyisamEngine(engine_name);
 
1505
  registry.add(engine);
 
1506
 
 
1507
  pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
 
1508
 
 
1509
  /* call ha_init_key_cache() on all key caches to init them */
 
1510
  error= init_key_cache(dflt_key_cache,
 
1511
                        myisam_key_cache_block_size,
 
1512
                        myisam_key_cache_size,
 
1513
                        myisam_key_cache_division_limit, 
 
1514
                        myisam_key_cache_age_threshold);
 
1515
 
 
1516
  if (error == 0)
 
1517
    exit(1); /* Memory Allocation Failure */
 
1518
 
 
1519
  return 0;
1772
1520
}
1773
1521
 
1774
 
int myisam_deinit(void *hton __attribute__((unused)))
 
1522
static int myisam_deinit(plugin::Registry &registry)
1775
1523
{
 
1524
  registry.remove(engine);
 
1525
  delete engine;
 
1526
 
 
1527
  pthread_mutex_destroy(&THR_LOCK_myisam);
 
1528
  end_key_cache(dflt_key_cache, 1);             // Can never fail
 
1529
 
1776
1530
  return mi_panic(HA_PANIC_CLOSE);
1777
1531
}
1778
1532
 
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,
 
1533
static void sys_var_key_cache_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
 
1534
{
 
1535
  uint32_t tmp= *static_cast<const uint32_t *>(save);
 
1536
  bool error= 0;
 
1537
 
 
1538
        struct my_option option_limits;
 
1539
  plugin_opt_set_limits(&option_limits, var);
 
1540
        option_limits.name= "myisam_key_cache_size";
 
1541
 
 
1542
  if (dflt_key_cache->in_init)
 
1543
    return;
 
1544
 
 
1545
  myisam_key_cache_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
 
1546
 
 
1547
  /* If key cache didn't existed initialize it, else resize it */
 
1548
  dflt_key_cache->in_init= 1;
 
1549
 
 
1550
  error= ! resize_key_cache(dflt_key_cache,
 
1551
                                                                                                                myisam_key_cache_block_size,
 
1552
                            myisam_key_cache_size,
 
1553
                            myisam_key_cache_division_limit,
 
1554
                                                                                                          myisam_key_cache_age_threshold);
 
1555
  dflt_key_cache->in_init= 0;
 
1556
}
 
1557
 
 
1558
static void sys_var_key_cache_block_size_update(Session *session, drizzle_sys_var *var, void *, const void *save)
 
1559
{
 
1560
  uint32_t tmp= *static_cast<const uint32_t *>(save);
 
1561
  bool error= 0;
 
1562
 
 
1563
        struct my_option option_limits;
 
1564
  plugin_opt_set_limits(&option_limits, var);
 
1565
        option_limits.name= "myisam_key_cache_block_size";
 
1566
 
 
1567
  if (dflt_key_cache->in_init)
 
1568
    return;
 
1569
 
 
1570
  myisam_key_cache_block_size= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
 
1571
 
 
1572
  dflt_key_cache->in_init= 1;
 
1573
 
 
1574
  error= ! resize_key_cache(dflt_key_cache,
 
1575
                                                                                                                myisam_key_cache_block_size,
 
1576
                            myisam_key_cache_size,
 
1577
                            myisam_key_cache_division_limit,
 
1578
                                                                                                          myisam_key_cache_age_threshold);
 
1579
 
 
1580
  dflt_key_cache->in_init= 0;
 
1581
}
 
1582
 
 
1583
static void sys_var_key_cache_division_limit_update(Session *session, drizzle_sys_var *var, void *, const void *save)
 
1584
{
 
1585
  uint32_t tmp= *static_cast<const uint32_t *>(save);
 
1586
  bool error= 0;
 
1587
 
 
1588
        struct my_option option_limits;
 
1589
  plugin_opt_set_limits(&option_limits, var);
 
1590
        option_limits.name= "myisam_key_cache_division_limit";
 
1591
 
 
1592
  if (dflt_key_cache->in_init)
 
1593
    return;
 
1594
 
 
1595
  myisam_key_cache_division_limit= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
 
1596
 
 
1597
  dflt_key_cache->in_init= 1;
 
1598
 
 
1599
  error= ! resize_key_cache(dflt_key_cache,
 
1600
                                                                                                                myisam_key_cache_block_size,
 
1601
                            myisam_key_cache_size,
 
1602
                            myisam_key_cache_division_limit,
 
1603
                                                                                                          myisam_key_cache_age_threshold);
 
1604
 
 
1605
  dflt_key_cache->in_init= 0;
 
1606
}
 
1607
 
 
1608
static void sys_var_key_cache_age_threshold_update(Session *session, drizzle_sys_var *var, void *, const void *save)
 
1609
{
 
1610
  uint32_t tmp= *static_cast<const uint32_t *>(save);
 
1611
  bool error= 0;
 
1612
 
 
1613
        struct my_option option_limits;
 
1614
  plugin_opt_set_limits(&option_limits, var);
 
1615
        option_limits.name= "myisam_key_cache_age_threshold";
 
1616
 
 
1617
  if (dflt_key_cache->in_init)
 
1618
    return;
 
1619
 
 
1620
  myisam_key_cache_age_threshold= static_cast<uint32_t>(fix_unsigned(session, static_cast<uint64_t>(tmp), &option_limits));
 
1621
 
 
1622
  dflt_key_cache->in_init= 1;
 
1623
 
 
1624
  error= ! resize_key_cache(dflt_key_cache,
 
1625
                                                                                                                myisam_key_cache_block_size,
 
1626
                            myisam_key_cache_size,
 
1627
                            myisam_key_cache_division_limit,
 
1628
                                                                                                          myisam_key_cache_age_threshold);
 
1629
 
 
1630
  dflt_key_cache->in_init= 0;
 
1631
}
 
1632
 
 
1633
static DRIZZLE_SYSVAR_UINT(key_cache_block_size,
 
1634
                            myisam_key_cache_block_size,
 
1635
                            PLUGIN_VAR_RQCMDARG,
 
1636
                            N_("Block size to be used for MyISAM index pages."),
 
1637
                            NULL,
 
1638
                            sys_var_key_cache_block_size_update,
 
1639
                            KEY_CACHE_BLOCK_SIZE,
 
1640
                            512, 
 
1641
                            16 * 1024,
 
1642
                            0);
 
1643
 
 
1644
static DRIZZLE_SYSVAR_UINT(key_cache_age_threshold, myisam_key_cache_age_threshold,
 
1645
                            PLUGIN_VAR_RQCMDARG,
 
1646
                            N_("This characterizes the number of hits a hot block has to be untouched "
 
1647
                            "until it is considered aged enough to be downgraded to a warm block. "
 
1648
                            "This specifies the percentage ratio of that number of hits to the "
 
1649
                            "total number of blocks in key cache"),
 
1650
                            NULL,
 
1651
                            sys_var_key_cache_age_threshold_update,
 
1652
                            300,
 
1653
                            100, 
 
1654
                            UINT32_MAX,
 
1655
                            0);
 
1656
 
 
1657
static DRIZZLE_SYSVAR_UINT(key_cache_division_limit, myisam_key_cache_division_limit,
 
1658
                            PLUGIN_VAR_RQCMDARG,
 
1659
                            N_("The minimum percentage of warm blocks in key cache"),
 
1660
                            NULL,
 
1661
                            sys_var_key_cache_division_limit_update,
 
1662
                            100,
 
1663
                            1, 
 
1664
                            100,
 
1665
                            0);
 
1666
 
 
1667
static DRIZZLE_SYSVAR_UINT(key_cache_size,
 
1668
                            myisam_key_cache_size,
 
1669
                            PLUGIN_VAR_RQCMDARG,
 
1670
                            N_("The size of the buffer used for index blocks for MyISAM tables. "
 
1671
                            "Increase this to get better index handling (for all reads and multiple "
 
1672
                            "writes) to as much as you can afford;"),
 
1673
                            NULL,
 
1674
                            sys_var_key_cache_size_update,
 
1675
                            KEY_CACHE_SIZE,
 
1676
                            1 * 1024 * 1024, 
 
1677
                            UINT32_MAX,
 
1678
                            IO_SIZE);
 
1679
 
 
1680
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
 
1681
                            PLUGIN_VAR_RQCMDARG,
 
1682
                            N_("Number of threads to use when repairing MyISAM tables. The value of "
 
1683
                            "1 disables parallel repair."),
 
1684
                            NULL, NULL, 1, 1, UINT32_MAX, 0);
 
1685
 
 
1686
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
 
1687
                                PLUGIN_VAR_RQCMDARG,
 
1688
                                N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
 
1689
                                NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
 
1690
 
 
1691
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
 
1692
                                PLUGIN_VAR_RQCMDARG,
 
1693
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
 
1694
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
 
1695
 
 
1696
extern uint32_t data_pointer_size;
 
1697
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
 
1698
                            PLUGIN_VAR_RQCMDARG,
 
1699
                            N_("Default pointer size to be used for MyISAM tables."),
 
1700
                            NULL, NULL, 6, 2, 7, 0);
 
1701
 
 
1702
static drizzle_sys_var* sys_variables[]= {
 
1703
  DRIZZLE_SYSVAR(key_cache_block_size),
 
1704
  DRIZZLE_SYSVAR(key_cache_size),
 
1705
  DRIZZLE_SYSVAR(key_cache_division_limit),
 
1706
  DRIZZLE_SYSVAR(key_cache_age_threshold),
 
1707
  DRIZZLE_SYSVAR(repair_threads),
 
1708
  DRIZZLE_SYSVAR(max_sort_file_size),
 
1709
  DRIZZLE_SYSVAR(sort_buffer_size),
 
1710
  DRIZZLE_SYSVAR(data_pointer_size),
 
1711
  NULL
 
1712
};
 
1713
 
 
1714
 
 
1715
DRIZZLE_DECLARE_PLUGIN
 
1716
{
 
1717
  DRIZZLE_VERSION_ID,
1852
1718
  "MyISAM",
1853
1719
  "1.0",
1854
1720
  "MySQL AB",
1857
1723
  myisam_init, /* Plugin Init */
1858
1724
  myisam_deinit, /* Plugin Deinit */
1859
1725
  NULL,                       /* status variables                */
1860
 
  NULL,                       /* system variables                */
 
1726
  sys_variables,           /* system variables */
1861
1727
  NULL                        /* config options                  */
1862
1728
}
1863
 
mysql_declare_plugin_end;
 
1729
DRIZZLE_DECLARE_PLUGIN_END;