~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
 
17
 
 
18
 
#include "config.h"
19
 
#include "drizzled/internal/my_bit.h"
20
 
#include "myisampack.h"
 
17
#ifdef USE_PRAGMA_IMPLEMENTATION
 
18
#pragma implementation                          // gcc: Class implementation
 
19
#endif
 
20
 
 
21
#define DRIZZLE_SERVER 1
 
22
 
 
23
#include <drizzled/server_includes.h>
 
24
#include <mysys/my_bit.h>
 
25
#include <myisampack.h>
21
26
#include "ha_myisam.h"
22
 
#include "myisam_priv.h"
23
 
#include "drizzled/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
 
 
50
 
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
51
 
 
52
 
static uint32_t repair_threads;
53
 
static uint32_t myisam_key_cache_block_size;
54
 
static uint32_t myisam_key_cache_size;
55
 
static uint32_t myisam_key_cache_division_limit;
56
 
static uint32_t myisam_key_cache_age_threshold;
57
 
static uint64_t max_sort_file_size;
58
 
static uint64_t sort_buffer_size;
 
27
#include "myisamdef.h"
 
28
#include <drizzled/drizzled_error_messages.h>
 
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", NULL};
 
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", NULL};
 
40
TYPELIB myisam_stats_method_typelib= {
 
41
  array_elements(myisam_stats_method_names) - 1, "",
 
42
  myisam_stats_method_names, NULL};
 
43
 
59
44
 
60
45
/*****************************************************************************
61
46
** MyISAM tables
62
47
*****************************************************************************/
63
48
 
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
 
{
 
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);
 
54
}
 
55
 
 
56
// collect errors printed by mi_check routines
 
57
 
 
58
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
 
59
                               const char *fmt, va_list args)
 
60
{
 
61
  THD* thd = (THD*)param->thd;
 
62
  Protocol *protocol= thd->protocol;
 
63
  uint32_t length, msg_length;
 
64
  char msgbuf[MI_MAX_MSG_BUF];
 
65
  char name[NAME_LEN*2+2];
 
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,NULL) -
 
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;
171
101
}
172
102
 
173
103
 
187
117
    table conformance in merge engine.
188
118
 
189
119
    The caller needs to free *recinfo_out after use. Since *recinfo_out
190
 
    and *keydef_out are allocated with a multi_malloc, *keydef_out
 
120
    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
191
121
    is freed automatically when *recinfo_out is freed.
192
122
 
193
123
  RETURN VALUE
195
125
    !0 error code
196
126
*/
197
127
 
198
 
static int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
199
 
                        MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
 
128
int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
 
129
                 MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
200
130
{
201
131
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
202
132
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
205
135
  MI_KEYDEF *keydef;
206
136
  MI_COLUMNDEF *recinfo, *recinfo_pos;
207
137
  HA_KEYSEG *keyseg;
208
 
  TableShare *share= table_arg->s;
 
138
  TABLE_SHARE *share= table_arg->s;
209
139
  uint32_t options= share->db_options_in_use;
210
 
  if (!(memory::multi_malloc(false,
 
140
  if (!(my_multi_malloc(MYF(MY_WME),
211
141
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
212
142
          keydef_out, share->keys * sizeof(MI_KEYDEF),
213
 
          &keyseg, (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
143
          &keyseg,
 
144
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
214
145
          NULL)))
215
 
    return(HA_ERR_OUT_OF_MEM);
 
146
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
216
147
  keydef= *keydef_out;
217
148
  recinfo= *recinfo_out;
218
149
  pos= table_arg->key_info;
235
166
      {
236
167
        if (pos->key_part[j].length > 8 &&
237
168
            (type == HA_KEYTYPE_TEXT ||
 
169
             type == HA_KEYTYPE_NUM ||
238
170
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
239
171
        {
240
172
          /* No blobs here */
280
212
  record= table_arg->record[0];
281
213
  recpos= 0;
282
214
  recinfo_pos= recinfo;
283
 
  while (recpos < (uint) share->stored_rec_length)
 
215
  while (recpos < (uint) share->reclength)
284
216
  {
285
217
    Field **field, *found= 0;
286
218
    minpos= share->reclength;
340
272
  return(0);
341
273
}
342
274
 
343
 
int ha_myisam::reset_auto_increment(uint64_t value)
344
 
{
345
 
  file->s->state.auto_increment= value;
346
 
  return 0;
347
 
}
348
275
 
349
276
/*
350
277
  Check for underlying table conformance
386
313
      (should be corretly detected in table2myisam).
387
314
*/
388
315
 
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)
 
316
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
 
317
                     uint32_t t1_keys, uint32_t t1_recs,
 
318
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
 
319
                     uint32_t t2_keys, uint32_t t2_recs, bool strict)
393
320
{
394
321
  uint32_t i, j;
395
322
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
424
351
      {
425
352
        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
426
353
            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
427
 
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1;
 
354
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
428
355
        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
429
356
                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
430
 
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1;
 
357
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
431
358
      }
432
359
 
433
360
      if (t1_keysegs_j__type != t2_keysegs[j].type ||
461
388
}
462
389
 
463
390
 
 
391
extern "C" {
 
392
 
464
393
volatile int *killed_ptr(MI_CHECK *param)
465
394
{
466
395
  /* In theory Unsafe conversion, but should be ok for now */
467
 
  return (int*) &(((Session *)(param->session))->killed);
 
396
  return (int*) &(((THD *)(param->thd))->killed);
468
397
}
469
398
 
470
399
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
513
442
void _mi_report_crashed(MI_INFO *file, const char *message,
514
443
                        const char *sfile, uint32_t sline)
515
444
{
516
 
  Session *cur_session;
 
445
  THD *cur_thd;
 
446
  LIST *element;
517
447
  pthread_mutex_lock(&file->s->intern_lock);
518
 
  if ((cur_session= file->in_use))
519
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
520
 
                    cur_session->thread_id,
 
448
  if ((cur_thd= (THD*) file->in_use.data))
 
449
    sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
521
450
                    sfile, sline);
522
451
  else
523
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
 
452
    sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline);
524
453
  if (message)
525
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
526
 
  list<Session *>::iterator it= file->s->in_use->begin();
527
 
  while (it != file->s->in_use->end())
 
454
    sql_print_error("%s", message);
 
455
  for (element= file->s->in_use; element; element= list_rest(element))
528
456
  {
529
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
530
 
    ++it;
 
457
    sql_print_error("%s", "Unknown thread accessing table");
531
458
  }
532
459
  pthread_mutex_unlock(&file->s->intern_lock);
533
460
}
534
461
 
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)
 
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 |
 
467
                  HA_BINLOG_ROW_CAPABLE |
 
468
                  HA_BINLOG_STMT_CAPABLE |
 
469
                  HA_DUPLICATE_POS |
 
470
                  HA_CAN_INDEX_BLOBS |
 
471
                  HA_AUTO_PART_KEY |
 
472
                  HA_FILE_BASED |
 
473
                  HA_NO_TRANSACTIONS |
 
474
                  HA_HAS_RECORDS |
 
475
                  HA_STATS_RECORDS_IS_EXACT |
 
476
                  HA_NEED_READ_RANGE_BUFFER |
 
477
                  HA_MRR_CANT_SORT),
 
478
   can_enable_indexes(1)
 
479
{}
 
480
 
 
481
handler *ha_myisam::clone(MEM_ROOT *mem_root)
544
482
{
545
 
  ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
 
483
  ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
546
484
  if (new_handler)
547
485
    new_handler->file->state= file->state;
548
486
  return new_handler;
549
487
}
550
488
 
551
 
const char *ha_myisam::index_type(uint32_t )
 
489
 
 
490
static const char *ha_myisam_exts[] = {
 
491
  ".MYI",
 
492
  ".MYD",
 
493
  NULL
 
494
};
 
495
 
 
496
const char **ha_myisam::bas_ext() const
 
497
{
 
498
  return ha_myisam_exts;
 
499
}
 
500
 
 
501
 
 
502
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
552
503
{
553
504
  return "BTREE";
554
505
}
576
527
    open of a table that is in use by other threads already (if the
577
528
    MyISAM share exists already).
578
529
  */
579
 
  if (!(file=mi_open(name, mode, test_if_locked)))
580
 
    return (errno ? errno : -1);
581
 
 
 
530
  if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
 
531
    return (my_errno ? my_errno : -1);
582
532
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
583
533
  {
584
 
    if ((errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
 
534
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
585
535
    {
 
536
      /* purecov: begin inspected */
586
537
      goto err;
 
538
      /* purecov: end */
587
539
    }
588
540
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
589
541
                         file->s->keyinfo, file->s->rec,
590
542
                         file->s->base.keys, file->s->base.fields, true))
591
543
    {
592
 
      errno= HA_ERR_CRASHED;
 
544
      /* purecov: begin inspected */
 
545
      my_errno= HA_ERR_CRASHED;
593
546
      goto err;
 
547
      /* purecov: end */
594
548
    }
595
549
  }
596
 
 
 
550
  
597
551
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
598
552
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
599
553
 
601
555
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
602
556
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
603
557
  if (!table->s->db_record_offset)
604
 
    is_ordered= false;
605
 
 
606
 
 
607
 
  keys_with_parts.reset();
 
558
    int_table_flags|=HA_REC_NOT_IN_SEQ;
 
559
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
560
    int_table_flags|=HA_HAS_CHECKSUM;
 
561
  
 
562
  keys_with_parts.clear_all();
608
563
  for (i= 0; i < table->s->keys; i++)
609
564
  {
610
565
    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
613
568
    KEY_PART_INFO *kp_end= kp + table->key_info[i].key_parts;
614
569
    for (; kp != kp_end; kp++)
615
570
    {
616
 
      if (!kp->field->part_of_key.test(i))
 
571
      if (!kp->field->part_of_key.is_set(i))
617
572
      {
618
 
        keys_with_parts.set(i);
 
573
        keys_with_parts.set_bit(i);
619
574
        break;
620
575
      }
621
576
    }
622
577
  }
623
 
  errno= 0;
 
578
  my_errno= 0;
624
579
  goto end;
625
580
 err:
626
581
  this->close();
627
582
 end:
628
583
  /*
629
 
    Both recinfo and keydef are allocated by multi_malloc(), thus only
 
584
    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
630
585
    recinfo must be freed.
631
586
  */
632
587
  if (recinfo)
633
588
    free((unsigned char*) recinfo);
634
 
  return errno;
 
589
  return my_errno;
635
590
}
636
591
 
637
592
int ha_myisam::close(void)
643
598
 
644
599
int ha_myisam::write_row(unsigned char *buf)
645
600
{
646
 
  ha_statistic_increment(&system_status_var::ha_write_count);
 
601
  ha_statistic_increment(&SSV::ha_write_count);
 
602
 
 
603
  /* If we have a timestamp column, update it to the current time */
 
604
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
605
    table->timestamp_field->set_time();
647
606
 
648
607
  /*
649
608
    If we have an auto_increment column and we are writing a changed row
658
617
  return mi_write(file,buf);
659
618
}
660
619
 
661
 
 
662
 
int ha_myisam::repair(Session *session, MI_CHECK &param, bool do_optimize)
663
 
{
664
 
  int error=0;
665
 
  uint32_t local_testflag= param.testflag;
 
620
int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
 
621
{
 
622
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
623
  int error;
 
624
  MI_CHECK param;
 
625
  MYISAM_SHARE* share = file->s;
 
626
  const char *old_proc_info= thd->get_proc_info();
 
627
 
 
628
  thd_proc_info(thd, "Checking table");
 
629
  myisamchk_init(&param);
 
630
  param.thd = thd;
 
631
  param.op_name =   "check";
 
632
  param.db_name=    table->s->db.str;
 
633
  param.table_name= table->alias;
 
634
  param.testflag = check_opt->flags | T_CHECK | T_SILENT;
 
635
  param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
 
636
 
 
637
  if (!(table->db_stat & HA_READ_ONLY))
 
638
    param.testflag|= T_STATISTICS;
 
639
  param.using_global_keycache = 1;
 
640
 
 
641
  if (!mi_is_crashed(file) &&
 
642
      (((param.testflag & T_CHECK_ONLY_CHANGED) &&
 
643
        !(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
 
644
                                  STATE_CRASHED_ON_REPAIR)) &&
 
645
        share->state.open_count == 0) ||
 
646
       ((param.testflag & T_FAST) && (share->state.open_count ==
 
647
                                      (uint) (share->global_changed ? 1 : 0)))))
 
648
    return HA_ADMIN_ALREADY_DONE;
 
649
 
 
650
  error = chk_status(&param, file);             // Not fatal
 
651
  error = chk_size(&param, file);
 
652
  if (!error)
 
653
    error |= chk_del(&param, file, param.testflag);
 
654
  if (!error)
 
655
    error = chk_key(&param, file);
 
656
  if (!error)
 
657
  {
 
658
    if ((!(param.testflag & T_QUICK) &&
 
659
         ((share->options &
 
660
           (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
 
661
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
 
662
        mi_is_crashed(file))
 
663
    {
 
664
      uint32_t old_testflag=param.testflag;
 
665
      param.testflag|=T_MEDIUM;
 
666
      if (!(error= init_io_cache(&param.read_cache, file->dfile,
 
667
                                 my_default_record_cache_size, READ_CACHE,
 
668
                                 share->pack.header_length, 1, MYF(MY_WME))))
 
669
      {
 
670
        error= chk_data_link(&param, file, param.testflag & T_EXTEND);
 
671
        end_io_cache(&(param.read_cache));
 
672
      }
 
673
      param.testflag= old_testflag;
 
674
    }
 
675
  }
 
676
  if (!error)
 
677
  {
 
678
    if ((share->state.changed & (STATE_CHANGED |
 
679
                                 STATE_CRASHED_ON_REPAIR |
 
680
                                 STATE_CRASHED | STATE_NOT_ANALYZED)) ||
 
681
        (param.testflag & T_STATISTICS) ||
 
682
        mi_is_crashed(file))
 
683
    {
 
684
      file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
685
      pthread_mutex_lock(&share->intern_lock);
 
686
      share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
 
687
                               STATE_CRASHED_ON_REPAIR);
 
688
      if (!(table->db_stat & HA_READ_ONLY))
 
689
        error=update_state_info(&param,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
 
690
                                UPDATE_STAT);
 
691
      pthread_mutex_unlock(&share->intern_lock);
 
692
      info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 
693
           HA_STATUS_CONST);
 
694
    }
 
695
  }
 
696
  else if (!mi_is_crashed(file) && !thd->killed)
 
697
  {
 
698
    mi_mark_crashed(file);
 
699
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
700
  }
 
701
 
 
702
  thd_proc_info(thd, old_proc_info);
 
703
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
704
}
 
705
 
 
706
 
 
707
/*
 
708
  analyze the key distribution in the table
 
709
  As the table may be only locked for read, we have to take into account that
 
710
  two threads may do an analyze at the same time!
 
711
*/
 
712
 
 
713
int ha_myisam::analyze(THD *thd,
 
714
                       HA_CHECK_OPT* check_opt __attribute__((unused)))
 
715
{
 
716
  int error=0;
 
717
  MI_CHECK param;
 
718
  MYISAM_SHARE* share = file->s;
 
719
 
 
720
  myisamchk_init(&param);
 
721
  param.thd = thd;
 
722
  param.op_name=    "analyze";
 
723
  param.db_name=    table->s->db.str;
 
724
  param.table_name= table->alias;
 
725
  param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
 
726
                   T_DONT_CHECK_CHECKSUM);
 
727
  param.using_global_keycache = 1;
 
728
  param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
 
729
 
 
730
  if (!(share->state.changed & STATE_NOT_ANALYZED))
 
731
    return HA_ADMIN_ALREADY_DONE;
 
732
 
 
733
  error = chk_key(&param, file);
 
734
  if (!error)
 
735
  {
 
736
    pthread_mutex_lock(&share->intern_lock);
 
737
    error=update_state_info(&param,file,UPDATE_STAT);
 
738
    pthread_mutex_unlock(&share->intern_lock);
 
739
  }
 
740
  else if (!mi_is_crashed(file) && !thd->killed)
 
741
    mi_mark_crashed(file);
 
742
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
743
}
 
744
 
 
745
 
 
746
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
 
747
{
 
748
  int error;
 
749
  MI_CHECK param;
 
750
  ha_rows start_records;
 
751
 
 
752
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
753
 
 
754
  myisamchk_init(&param);
 
755
  param.thd = thd;
 
756
  param.op_name=  "repair";
 
757
  param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
 
758
                   T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
 
759
                   (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
 
760
  param.sort_buffer_length=  check_opt->sort_buffer_size;
 
761
  start_records=file->state->records;
 
762
  while ((error=repair(thd,param,0)) && param.retry_repair)
 
763
  {
 
764
    param.retry_repair=0;
 
765
    if (test_all_bits(param.testflag,
 
766
                      (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
 
767
    {
 
768
      param.testflag&= ~T_RETRY_WITHOUT_QUICK;
 
769
      sql_print_information("Retrying repair of: '%s' without quick",
 
770
                            table->s->path.str);
 
771
      continue;
 
772
    }
 
773
    param.testflag&= ~T_QUICK;
 
774
    if ((param.testflag & T_REP_BY_SORT))
 
775
    {
 
776
      param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
 
777
      sql_print_information("Retrying repair of: '%s' with keycache",
 
778
                            table->s->path.str);
 
779
      continue;
 
780
    }
 
781
    break;
 
782
  }
 
783
  if (!error && start_records != file->state->records &&
 
784
      !(check_opt->flags & T_VERY_SILENT))
 
785
  {
 
786
    char llbuff[22],llbuff2[22];
 
787
    sql_print_information("Found %s of %s rows when repairing '%s'",
 
788
                          llstr(file->state->records, llbuff),
 
789
                          llstr(start_records, llbuff2),
 
790
                          table->s->path.str);
 
791
  }
 
792
  return error;
 
793
}
 
794
 
 
795
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
 
796
{
 
797
  int error;
 
798
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
799
  MI_CHECK param;
 
800
 
 
801
  myisamchk_init(&param);
 
802
  param.thd = thd;
 
803
  param.op_name= "optimize";
 
804
  param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
 
805
                   T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
 
806
  param.sort_buffer_length=  check_opt->sort_buffer_size;
 
807
  if ((error= repair(thd,param,1)) && param.retry_repair)
 
808
  {
 
809
    sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
 
810
                      my_errno, param.db_name, param.table_name);
 
811
    param.testflag&= ~T_REP_BY_SORT;
 
812
    error= repair(thd,param,1);
 
813
  }
 
814
  return error;
 
815
}
 
816
 
 
817
 
 
818
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
 
819
{
 
820
  int error=0;
 
821
  uint32_t local_testflag=param.testflag;
666
822
  bool optimize_done= !do_optimize, statistics_done=0;
667
 
  const char *old_proc_info= session->get_proc_info();
 
823
  const char *old_proc_info= thd->get_proc_info();
668
824
  char fixed_name[FN_REFLEN];
669
825
  MYISAM_SHARE* share = file->s;
670
826
  ha_rows rows= file->state->records;
679
835
  */
680
836
  if (file->dfile == -1)
681
837
  {
682
 
    errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' failed. "
 
838
    sql_print_information("Retrying repair of: '%s' failed. "
683
839
                          "Please try REPAIR EXTENDED or myisamchk",
684
840
                          table->s->path.str);
685
841
    return(HA_ADMIN_FAILED);
686
842
  }
687
843
 
688
 
  param.db_name=    table->s->getSchemaName();
 
844
  param.db_name=    table->s->db.str;
689
845
  param.table_name= table->alias;
690
846
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
691
847
  param.using_global_keycache = 1;
692
 
  param.session= session;
 
848
  param.thd= thd;
 
849
  param.tmpdir= &mysql_tmpdir_list;
693
850
  param.out_flag= 0;
694
 
  param.sort_buffer_length= (size_t)sort_buffer_size;
695
 
  strcpy(fixed_name,file->filename);
 
851
  my_stpcpy(fixed_name,file->filename);
696
852
 
697
853
  // 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))
 
854
  if (!thd->locked_tables && 
 
855
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
699
856
  {
700
 
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
 
857
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
701
858
    return(HA_ADMIN_FAILED);
702
859
  }
703
860
 
716
873
      local_testflag|= T_STATISTICS;
717
874
      param.testflag|= T_STATISTICS;            // We get this for free
718
875
      statistics_done=1;
719
 
      if (repair_threads > 1)
 
876
      if (thd->variables.myisam_repair_threads>1)
720
877
      {
721
878
        char buf[40];
722
879
        /* TODO: respect myisam_repair_threads variable */
723
 
        snprintf(buf, 40, "Repair with %d threads", internal::my_count_bits(key_map));
724
 
        session->set_proc_info(buf);
 
880
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
 
881
        thd_proc_info(thd, buf);
725
882
        error = mi_repair_parallel(&param, file, fixed_name,
726
883
            param.testflag & T_QUICK);
727
 
        session->set_proc_info("Repair done"); // to reset proc_info, as
 
884
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
728
885
                                      // it was pointing to local buffer
729
886
      }
730
887
      else
731
888
      {
732
 
        session->set_proc_info("Repair by sorting");
 
889
        thd_proc_info(thd, "Repair by sorting");
733
890
        error = mi_repair_by_sort(&param, file, fixed_name,
734
891
            param.testflag & T_QUICK);
735
892
      }
736
893
    }
737
894
    else
738
895
    {
739
 
      session->set_proc_info("Repair with keycache");
 
896
      thd_proc_info(thd, "Repair with keycache");
740
897
      param.testflag &= ~T_REP_BY_SORT;
741
898
      error=  mi_repair(&param, file, fixed_name,
742
899
                        param.testflag & T_QUICK);
750
907
        (share->state.changed & STATE_NOT_SORTED_PAGES))
751
908
    {
752
909
      optimize_done=1;
753
 
      session->set_proc_info("Sorting index");
 
910
      thd_proc_info(thd, "Sorting index");
754
911
      error=mi_sort_index(&param,file,fixed_name);
755
912
    }
756
913
    if (!statistics_done && (local_testflag & T_STATISTICS))
758
915
      if (share->state.changed & STATE_NOT_ANALYZED)
759
916
      {
760
917
        optimize_done=1;
761
 
        session->set_proc_info("Analyzing");
 
918
        thd_proc_info(thd, "Analyzing");
762
919
        error = chk_key(&param, file);
763
920
      }
764
921
      else
765
922
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
766
923
    }
767
924
  }
768
 
  session->set_proc_info("Saving state");
 
925
  thd_proc_info(thd, "Saving state");
769
926
  if (!error)
770
927
  {
771
928
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
793
950
    {
794
951
      char llbuff[22],llbuff2[22];
795
952
      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));
 
953
                             llstr(rows,llbuff),
 
954
                             llstr(file->state->records,llbuff2));
798
955
    }
799
956
  }
800
957
  else
803
960
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
804
961
    update_state_info(&param, file, 0);
805
962
  }
806
 
  session->set_proc_info(old_proc_info);
807
 
  mi_lock_database(file,F_UNLCK);
808
 
 
 
963
  thd_proc_info(thd, old_proc_info);
 
964
  if (!thd->locked_tables)
 
965
    mi_lock_database(file,F_UNLCK);
809
966
  return(error ? HA_ADMIN_FAILED :
810
967
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
811
968
}
812
969
 
813
970
 
814
971
/*
 
972
  Assign table indexes to a specific key cache.
 
973
*/
 
974
 
 
975
int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
 
976
{
 
977
  KEY_CACHE *new_key_cache= check_opt->key_cache;
 
978
  const char *errmsg= 0;
 
979
  int error= HA_ADMIN_OK;
 
980
  uint64_t map;
 
981
  TableList *table_list= table->pos_in_table_list;
 
982
 
 
983
  table->keys_in_use_for_query.clear_all();
 
984
 
 
985
  if (table_list->process_index_hints(table))
 
986
    return(HA_ADMIN_FAILED);
 
987
  map= ~(uint64_t) 0;
 
988
  if (!table->keys_in_use_for_query.is_clear_all())
 
989
    /* use all keys if there's no list specified by the user through hints */
 
990
    map= table->keys_in_use_for_query.to_uint64_t();
 
991
 
 
992
  if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
 
993
  { 
 
994
    char buf[STRING_BUFFER_USUAL_SIZE];
 
995
    snprintf(buf, sizeof(buf),
 
996
                "Failed to flush to index file (errno: %d)", error);
 
997
    errmsg= buf;
 
998
    error= HA_ADMIN_CORRUPT;
 
999
  }
 
1000
 
 
1001
  if (error != HA_ADMIN_OK)
 
1002
  {
 
1003
    /* Send error to user */
 
1004
    MI_CHECK param;
 
1005
    myisamchk_init(&param);
 
1006
    param.thd= thd;
 
1007
    param.op_name=    "assign_to_keycache";
 
1008
    param.db_name=    table->s->db.str;
 
1009
    param.table_name= table->s->table_name.str;
 
1010
    param.testflag= 0;
 
1011
    mi_check_print_error(&param, errmsg);
 
1012
  }
 
1013
  return(error);
 
1014
}
 
1015
 
 
1016
 
 
1017
/*
815
1018
  Disable indexes, making it persistent if requested.
816
1019
 
817
1020
  SYNOPSIS
870
1073
    Enable indexes, which might have been disabled by disable_index() before.
871
1074
    The modes without _SAVE work only if both data and indexes are empty,
872
1075
    since the MyISAM repair would enable them persistently.
873
 
    To be sure in these cases, call Cursor::delete_all_rows() before.
 
1076
    To be sure in these cases, call handler::delete_all_rows() before.
874
1077
 
875
1078
  IMPLEMENTATION
876
1079
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
904
1107
  }
905
1108
  else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
906
1109
  {
907
 
    Session *session=current_session;
 
1110
    THD *thd=current_thd;
908
1111
    MI_CHECK param;
909
 
    const char *save_proc_info= session->get_proc_info();
910
 
    session->set_proc_info("Creating index");
 
1112
    const char *save_proc_info= thd->get_proc_info();
 
1113
    thd_proc_info(thd, "Creating index");
911
1114
    myisamchk_init(&param);
912
1115
    param.op_name= "recreating_index";
913
1116
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
914
1117
                     T_CREATE_MISSING_KEYS);
915
1118
    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;
918
 
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
 
1119
    param.sort_buffer_length=  thd->variables.myisam_sort_buff_size;
 
1120
    param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
 
1121
    param.tmpdir=&mysql_tmpdir_list;
 
1122
    if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
919
1123
    {
920
 
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
921
 
                        errno, param.db_name, param.table_name);
 
1124
      sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
 
1125
                        my_errno, param.db_name, param.table_name);
922
1126
      /* Repairing by sort failed. Now try standard repair method. */
923
1127
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
924
 
      error= (repair(session,param,0) != HA_ADMIN_OK);
 
1128
      error= (repair(thd,param,0) != HA_ADMIN_OK);
925
1129
      /*
926
1130
        If the standard repair succeeded, clear all error messages which
927
1131
        might have been set by the first repair. They can still be seen
928
1132
        with SHOW WARNINGS then.
929
1133
      */
930
1134
      if (! error)
931
 
        session->clear_error();
 
1135
        thd->clear_error();
932
1136
    }
933
1137
    info(HA_STATUS_CONST);
934
 
    session->set_proc_info(save_proc_info);
 
1138
    thd_proc_info(thd, save_proc_info);
935
1139
  }
936
1140
  else
937
1141
  {
959
1163
 
960
1164
int ha_myisam::indexes_are_disabled(void)
961
1165
{
962
 
 
 
1166
  
963
1167
  return mi_indexes_are_disabled(file);
964
1168
}
965
1169
 
980
1184
 
981
1185
void ha_myisam::start_bulk_insert(ha_rows rows)
982
1186
{
983
 
  Session *session= current_session;
984
 
  ulong size= session->variables.read_buff_size;
 
1187
  THD *thd= current_thd;
 
1188
  ulong size= cmin(thd->variables.read_buff_size,
 
1189
                  (ulong) (table->s->avg_row_length*rows));
985
1190
 
986
1191
  /* don't enable row cache if too few rows */
987
1192
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
1003
1208
    if (!file->bulk_insert &&
1004
1209
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1005
1210
    {
1006
 
      mi_init_bulk_insert(file,
1007
 
                          (size_t)session->variables.bulk_insert_buff_size,
1008
 
                          rows);
 
1211
      mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
1009
1212
    }
 
1213
 
 
1214
  return;
1010
1215
}
1011
1216
 
1012
1217
/*
1031
1236
}
1032
1237
 
1033
1238
 
 
1239
bool ha_myisam::check_and_repair(THD *thd)
 
1240
{
 
1241
  int error=0;
 
1242
  int marked_crashed;
 
1243
  char *old_query;
 
1244
  uint32_t old_query_length;
 
1245
  HA_CHECK_OPT check_opt;
 
1246
 
 
1247
  check_opt.init();
 
1248
  check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
 
1249
  // Don't use quick if deleted rows
 
1250
  if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
 
1251
    check_opt.flags|=T_QUICK;
 
1252
  sql_print_warning("Checking table:   '%s'",table->s->path.str);
 
1253
 
 
1254
  old_query= thd->query;
 
1255
  old_query_length= thd->query_length;
 
1256
  pthread_mutex_lock(&LOCK_thread_count);
 
1257
  thd->query=        table->s->table_name.str;
 
1258
  thd->query_length= table->s->table_name.length;
 
1259
  pthread_mutex_unlock(&LOCK_thread_count);
 
1260
 
 
1261
  if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
 
1262
  {
 
1263
    sql_print_warning("Recovering table: '%s'",table->s->path.str);
 
1264
    check_opt.flags=
 
1265
      ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
 
1266
       (marked_crashed                             ? 0 : T_QUICK) |
 
1267
       (myisam_recover_options & HA_RECOVER_FORCE  ? 0 : T_SAFE_REPAIR) |
 
1268
       T_AUTO_REPAIR);
 
1269
    if (repair(thd, &check_opt))
 
1270
      error=1;
 
1271
  }
 
1272
  pthread_mutex_lock(&LOCK_thread_count);
 
1273
  thd->query= old_query;
 
1274
  thd->query_length= old_query_length;
 
1275
  pthread_mutex_unlock(&LOCK_thread_count);
 
1276
  return(error);
 
1277
}
 
1278
 
 
1279
bool ha_myisam::is_crashed() const
 
1280
{
 
1281
  return (file->s->state.changed & STATE_CRASHED ||
 
1282
          (file->s->state.open_count));
 
1283
}
1034
1284
 
1035
1285
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
1036
1286
{
1037
 
  ha_statistic_increment(&system_status_var::ha_update_count);
 
1287
  ha_statistic_increment(&SSV::ha_update_count);
1038
1288
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1039
1289
    table->timestamp_field->set_time();
1040
1290
  return mi_update(file,old_data,new_data);
1042
1292
 
1043
1293
int ha_myisam::delete_row(const unsigned char *buf)
1044
1294
{
1045
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
1295
  ha_statistic_increment(&SSV::ha_delete_count);
1046
1296
  return mi_delete(file,buf);
1047
1297
}
1048
1298
 
 
1299
#ifdef __cplusplus
 
1300
extern "C" {
 
1301
#endif
1049
1302
 
1050
 
int ha_myisam::index_init(uint32_t idx, bool )
 
1303
bool index_cond_func_myisam(void *arg)
1051
1304
{
 
1305
  ha_myisam *h= (ha_myisam*)arg;
 
1306
  /*if (h->in_range_read)*/
 
1307
  if (h->end_range)
 
1308
  {
 
1309
    if (h->compare_key2(h->end_range) > 0)
 
1310
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
 
1311
  }
 
1312
  return (bool)h->pushed_idx_cond->val_int();
 
1313
}
 
1314
 
 
1315
#ifdef __cplusplus
 
1316
}
 
1317
#endif
 
1318
 
 
1319
 
 
1320
int ha_myisam::index_init(uint32_t idx, bool sorted __attribute__((unused)))
 
1321
1052
1322
  active_index=idx;
1053
1323
  //in_range_read= false;
1054
 
  return 0;
 
1324
  if (pushed_idx_cond_keyno == idx)
 
1325
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
 
1326
  return 0; 
1055
1327
}
1056
1328
 
1057
1329
 
1058
1330
int ha_myisam::index_end()
1059
1331
{
1060
1332
  active_index=MAX_KEY;
1061
 
  return 0;
 
1333
  //pushed_idx_cond_keyno= MAX_KEY;
 
1334
  mi_set_index_cond_func(file, NULL, 0);
 
1335
  in_range_check_pushed_down= false;
 
1336
  ds_mrr.dsmrr_close();
 
1337
  return 0; 
1062
1338
}
1063
1339
 
1064
1340
 
1067
1343
                              enum ha_rkey_function find_flag)
1068
1344
{
1069
1345
  assert(inited==INDEX);
1070
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1346
  ha_statistic_increment(&SSV::ha_read_key_count);
1071
1347
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1072
1348
  table->status=error ? STATUS_NOT_FOUND: 0;
1073
1349
  return error;
1077
1353
                                  key_part_map keypart_map,
1078
1354
                                  enum ha_rkey_function find_flag)
1079
1355
{
1080
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1356
  ha_statistic_increment(&SSV::ha_read_key_count);
1081
1357
  int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
1082
1358
  table->status=error ? STATUS_NOT_FOUND: 0;
1083
1359
  return error;
1087
1363
                                   key_part_map keypart_map)
1088
1364
{
1089
1365
  assert(inited==INDEX);
1090
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1366
  ha_statistic_increment(&SSV::ha_read_key_count);
1091
1367
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1092
1368
                    HA_READ_PREFIX_LAST);
1093
1369
  table->status=error ? STATUS_NOT_FOUND: 0;
1097
1373
int ha_myisam::index_next(unsigned char *buf)
1098
1374
{
1099
1375
  assert(inited==INDEX);
1100
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1376
  ha_statistic_increment(&SSV::ha_read_next_count);
1101
1377
  int error=mi_rnext(file,buf,active_index);
1102
1378
  table->status=error ? STATUS_NOT_FOUND: 0;
1103
1379
  return error;
1106
1382
int ha_myisam::index_prev(unsigned char *buf)
1107
1383
{
1108
1384
  assert(inited==INDEX);
1109
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
1385
  ha_statistic_increment(&SSV::ha_read_prev_count);
1110
1386
  int error=mi_rprev(file,buf, active_index);
1111
1387
  table->status=error ? STATUS_NOT_FOUND: 0;
1112
1388
  return error;
1115
1391
int ha_myisam::index_first(unsigned char *buf)
1116
1392
{
1117
1393
  assert(inited==INDEX);
1118
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1394
  ha_statistic_increment(&SSV::ha_read_first_count);
1119
1395
  int error=mi_rfirst(file, buf, active_index);
1120
1396
  table->status=error ? STATUS_NOT_FOUND: 0;
1121
1397
  return error;
1124
1400
int ha_myisam::index_last(unsigned char *buf)
1125
1401
{
1126
1402
  assert(inited==INDEX);
1127
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
1403
  ha_statistic_increment(&SSV::ha_read_last_count);
1128
1404
  int error=mi_rlast(file, buf, active_index);
1129
1405
  table->status=error ? STATUS_NOT_FOUND: 0;
1130
1406
  return error;
1131
1407
}
1132
1408
 
1133
1409
int ha_myisam::index_next_same(unsigned char *buf,
1134
 
                               const unsigned char *,
1135
 
                               uint32_t )
 
1410
                               const unsigned char *key __attribute__((unused)),
 
1411
                               uint32_t length __attribute__((unused)))
1136
1412
{
1137
1413
  int error;
1138
1414
  assert(inited==INDEX);
1139
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1415
  ha_statistic_increment(&SSV::ha_read_next_count);
1140
1416
  do
1141
1417
  {
1142
1418
    error= mi_rnext_same(file,buf);
1154
1430
  //if (!eq_range_arg)
1155
1431
  //  in_range_read= true;
1156
1432
 
1157
 
  res= Cursor::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
1433
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
1158
1434
 
1159
1435
  //if (res)
1160
1436
  //  in_range_read= false;
1164
1440
 
1165
1441
int ha_myisam::read_range_next()
1166
1442
{
1167
 
  int res= Cursor::read_range_next();
 
1443
  int res= handler::read_range_next();
1168
1444
  //if (res)
1169
1445
  //  in_range_read= false;
1170
1446
  return res;
1180
1456
 
1181
1457
int ha_myisam::rnd_next(unsigned char *buf)
1182
1458
{
1183
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1459
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1184
1460
  int error=mi_scan(file, buf);
1185
1461
  table->status=error ? STATUS_NOT_FOUND: 0;
1186
1462
  return error;
1193
1469
 
1194
1470
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
1195
1471
{
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));
 
1472
  ha_statistic_increment(&SSV::ha_read_rnd_count);
 
1473
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
1198
1474
  table->status=error ? STATUS_NOT_FOUND: 0;
1199
1475
  return error;
1200
1476
}
1201
1477
 
1202
1478
 
1203
 
void ha_myisam::position(const unsigned char *)
 
1479
void ha_myisam::position(const unsigned char *record __attribute__((unused)))
1204
1480
{
1205
 
  internal::my_off_t row_position= mi_position(file);
1206
 
  internal::my_store_ptr(ref, ref_length, row_position);
 
1481
  my_off_t row_position= mi_position(file);
 
1482
  my_store_ptr(ref, ref_length, row_position);
1207
1483
}
1208
1484
 
1209
1485
int ha_myisam::info(uint32_t flag)
1224
1500
  }
1225
1501
  if (flag & HA_STATUS_CONST)
1226
1502
  {
1227
 
    TableShare *share= table->s;
 
1503
    TABLE_SHARE *share= table->s;
1228
1504
    stats.max_data_file_length=  misam_info.max_data_file_length;
1229
1505
    stats.max_index_file_length= misam_info.max_index_file_length;
1230
1506
    stats.create_time= misam_info.create_time;
1231
1507
    ref_length= misam_info.reflength;
1232
1508
    share->db_options_in_use= misam_info.options;
1233
 
    stats.block_size= myisam_key_cache_block_size;        /* record block size */
 
1509
    stats.block_size= myisam_block_size;        /* record block size */
1234
1510
 
1235
1511
    /* Update share */
1236
 
    if (share->tmp_table == message::Table::STANDARD)
 
1512
    if (share->tmp_table == NO_TMP_TABLE)
1237
1513
      pthread_mutex_lock(&share->mutex);
1238
 
    set_prefix(share->keys_in_use, share->keys);
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;
 
1514
    share->keys_in_use.set_prefix(share->keys);
 
1515
    share->keys_in_use.intersect_extended(misam_info.key_map);
 
1516
    share->keys_for_keyread.intersect(share->keys_in_use);
1285
1517
    share->db_record_offset= misam_info.record_offset;
1286
1518
    if (share->key_parts)
1287
1519
      memcpy(table->key_info[0].rec_per_key,
1288
1520
             misam_info.rec_per_key,
1289
1521
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1290
 
    if (share->tmp_table == message::Table::STANDARD)
 
1522
    if (share->tmp_table == NO_TMP_TABLE)
1291
1523
      pthread_mutex_unlock(&share->mutex);
1292
1524
 
1293
1525
   /*
1295
1527
     if table is symlinked (Ie;  Real name is not same as generated name)
1296
1528
   */
1297
1529
    data_file_name= index_file_name= 0;
1298
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
 
1530
    fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
1299
1531
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1300
1532
    if (strcmp(name_buff, misam_info.data_file_name))
1301
1533
      data_file_name=misam_info.data_file_name;
1302
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
 
1534
    fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
1303
1535
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1304
1536
    if (strcmp(name_buff, misam_info.index_file_name))
1305
1537
      index_file_name=misam_info.index_file_name;
1307
1539
  if (flag & HA_STATUS_ERRKEY)
1308
1540
  {
1309
1541
    errkey  = misam_info.errkey;
1310
 
    internal::my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
 
1542
    my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
1311
1543
  }
1312
1544
  if (flag & HA_STATUS_TIME)
1313
1545
    stats.update_time = misam_info.update_time;
1325
1557
 
1326
1558
int ha_myisam::reset(void)
1327
1559
{
 
1560
  pushed_idx_cond= NULL;
 
1561
  pushed_idx_cond_keyno= MAX_KEY;
 
1562
  mi_set_index_cond_func(file, NULL, 0);
 
1563
  ds_mrr.dsmrr_close();
1328
1564
  return mi_reset(file);
1329
1565
}
1330
1566
 
1340
1576
  return mi_delete_all_rows(file);
1341
1577
}
1342
1578
 
1343
 
int MyisamEngine::doDropTable(Session &session,
1344
 
                              drizzled::TableIdentifier &identifier)
 
1579
int ha_myisam::delete_table(const char *name)
1345
1580
{
1346
 
  session.removeTableMessage(identifier);
1347
 
 
1348
 
  return mi_delete_table(identifier.getPath().c_str());
 
1581
  return mi_delete_table(name);
1349
1582
}
1350
1583
 
1351
1584
 
1352
 
int ha_myisam::external_lock(Session *session, int lock_type)
 
1585
int ha_myisam::external_lock(THD *thd, int lock_type)
1353
1586
{
1354
 
  file->in_use= session;
 
1587
  file->in_use.data= thd;
1355
1588
  return mi_lock_database(file, !table->s->tmp_table ?
1356
1589
                          lock_type : ((lock_type == F_UNLCK) ?
1357
1590
                                       F_UNLCK : F_EXTRA_LCK));
1358
1591
}
1359
1592
 
1360
 
int MyisamEngine::doCreateTable(Session &session,
1361
 
                                Table& table_arg,
1362
 
                                drizzled::TableIdentifier &identifier,
1363
 
                                message::Table& create_proto)
 
1593
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
 
1594
                                      THR_LOCK_DATA **to,
 
1595
                                      enum thr_lock_type lock_type)
 
1596
{
 
1597
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
1598
    file->lock.type=lock_type;
 
1599
  *to++= &file->lock;
 
1600
  return to;
 
1601
}
 
1602
 
 
1603
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
 
1604
{
 
1605
  ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
 
1606
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
1607
  {
 
1608
    create_info->auto_increment_value= stats.auto_increment_value;
 
1609
  }
 
1610
  create_info->data_file_name=data_file_name;
 
1611
  create_info->index_file_name=index_file_name;
 
1612
}
 
1613
 
 
1614
 
 
1615
int ha_myisam::create(const char *name, register Table *table_arg,
 
1616
                      HA_CREATE_INFO *ha_create_info)
1364
1617
{
1365
1618
  int error;
1366
 
  uint32_t create_flags= 0, create_records;
 
1619
  uint32_t create_flags= 0, records;
1367
1620
  char buff[FN_REFLEN];
1368
1621
  MI_KEYDEF *keydef;
1369
1622
  MI_COLUMNDEF *recinfo;
1370
1623
  MI_CREATE_INFO create_info;
1371
 
  TableShare *share= table_arg.s;
 
1624
  TABLE_SHARE *share= table_arg->s;
1372
1625
  uint32_t options= share->db_options_in_use;
1373
 
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1374
 
    return(error);
 
1626
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
 
1627
    return(error); /* purecov: inspected */
1375
1628
  memset(&create_info, 0, sizeof(create_info));
1376
 
  create_info.max_rows= create_proto.options().max_rows();
1377
 
  create_info.reloc_rows= create_proto.options().min_rows();
 
1629
  create_info.max_rows= share->max_rows;
 
1630
  create_info.reloc_rows= share->min_rows;
1378
1631
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1379
 
  create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1380
 
                               create_proto.options().auto_increment_value() -1 :
 
1632
  create_info.auto_increment= (ha_create_info->auto_increment_value ?
 
1633
                               ha_create_info->auto_increment_value -1 :
1381
1634
                               (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;
 
1635
  create_info.data_file_length= ((uint64_t) share->max_rows *
 
1636
                                 share->avg_row_length);
 
1637
  create_info.data_file_name= ha_create_info->data_file_name;
 
1638
  create_info.index_file_name= ha_create_info->index_file_name;
1386
1639
  create_info.language= share->table_charset->number;
1387
1640
 
1388
 
  if (create_proto.type() == message::Table::TEMPORARY)
 
1641
  if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1389
1642
    create_flags|= HA_CREATE_TMP_TABLE;
 
1643
  if (ha_create_info->options & HA_CREATE_KEEP_FILES)
 
1644
    create_flags|= HA_CREATE_KEEP_FILES;
1390
1645
  if (options & HA_OPTION_PACK_RECORD)
1391
1646
    create_flags|= HA_PACK_RECORD;
 
1647
  if (options & HA_OPTION_CHECKSUM)
 
1648
    create_flags|= HA_CREATE_CHECKSUM;
 
1649
  if (options & HA_OPTION_DELAY_KEY_WRITE)
 
1650
    create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1392
1651
 
1393
 
  /* TODO: Check that the following internal::fn_format is really needed */
1394
 
  error= mi_create(internal::fn_format(buff, identifier.getPath().c_str(), "", "",
1395
 
                                       MY_UNPACK_FILENAME|MY_APPEND_EXT),
 
1652
  /* TODO: Check that the following fn_format is really needed */
 
1653
  error= mi_create(fn_format(buff, name, "", "",
 
1654
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
1396
1655
                   share->keys, keydef,
1397
 
                   create_records, recinfo,
 
1656
                   records, recinfo,
1398
1657
                   0, (MI_UNIQUEDEF*) 0,
1399
1658
                   &create_info, create_flags);
1400
1659
  free((unsigned char*) recinfo);
1401
 
 
1402
 
  session.storeTableMessage(identifier, create_proto);
1403
 
 
1404
 
  return error;
 
1660
  return(error);
1405
1661
}
1406
1662
 
1407
1663
 
1408
 
int MyisamEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
1664
int ha_myisam::rename_table(const char * from, const char * to)
1409
1665
{
1410
 
  session.renameTableMessage(from, to);
1411
 
 
1412
 
  return mi_rename(from.getPath().c_str(), to.getPath().c_str());
 
1666
  return mi_rename(from,to);
1413
1667
}
1414
1668
 
1415
1669
 
1416
 
void ha_myisam::get_auto_increment(uint64_t ,
1417
 
                                   uint64_t ,
1418
 
                                   uint64_t ,
 
1670
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
 
1671
                                   uint64_t increment __attribute__((unused)),
 
1672
                                   uint64_t nb_desired_values __attribute__((unused)),
1419
1673
                                   uint64_t *first_value,
1420
1674
                                   uint64_t *nb_reserved_values)
1421
1675
{
1476
1730
      HA_READ_KEY_EXACT         Include the key in the range
1477
1731
      HA_READ_AFTER_KEY         Don't include key in range
1478
1732
 
1479
 
    max_key.flag can have one of the following values:
 
1733
    max_key.flag can have one of the following values:  
1480
1734
      HA_READ_BEFORE_KEY        Don't include key in range
1481
1735
      HA_READ_AFTER_KEY         Include all 'end_key' values in the range
1482
1736
 
1499
1753
  return (uint)file->state->checksum;
1500
1754
}
1501
1755
 
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
 
 
 
1756
 
 
1757
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
 
1758
                                           uint32_t table_changes)
 
1759
{
 
1760
  uint32_t options= table->s->db_options_in_use;
 
1761
 
 
1762
  if (info->auto_increment_value != stats.auto_increment_value ||
 
1763
      info->data_file_name != data_file_name ||
 
1764
      info->index_file_name != index_file_name ||
 
1765
      table_changes == IS_EQUAL_NO ||
 
1766
      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
 
1767
    return COMPATIBLE_DATA_NO;
 
1768
 
 
1769
  if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
1770
                  HA_OPTION_DELAY_KEY_WRITE)) !=
 
1771
      (info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
1772
                              HA_OPTION_DELAY_KEY_WRITE)))
 
1773
    return COMPATIBLE_DATA_NO;
 
1774
  return COMPATIBLE_DATA_YES;
 
1775
}
 
1776
 
 
1777
int myisam_deinit(void *hton __attribute__((unused)))
 
1778
{
 
1779
  return mi_panic(HA_PANIC_CLOSE);
 
1780
}
 
1781
 
 
1782
static int myisam_init(void *p)
 
1783
{
 
1784
  handlerton *myisam_hton;
 
1785
 
 
1786
  myisam_hton= (handlerton *)p;
 
1787
  myisam_hton->state= SHOW_OPTION_YES;
 
1788
  myisam_hton->create= myisam_create_handler;
 
1789
  myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1519
1790
  return 0;
1520
1791
}
1521
1792
 
1522
1793
 
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);
1669
 
 
1670
 
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
1671
 
                            PLUGIN_VAR_RQCMDARG,
1672
 
                            N_("Number of threads to use when repairing MyISAM tables. The value of "
1673
 
                            "1 disables parallel repair."),
1674
 
                            NULL, NULL, 1, 1, UINT32_MAX, 0);
1675
 
 
1676
 
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
1677
 
                                PLUGIN_VAR_RQCMDARG,
1678
 
                                N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
1679
 
                                NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
1680
 
 
1681
 
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
1682
 
                                PLUGIN_VAR_RQCMDARG,
1683
 
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
1684
 
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
1685
 
 
1686
 
extern uint32_t data_pointer_size;
1687
 
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
1688
 
                            PLUGIN_VAR_RQCMDARG,
1689
 
                            N_("Default pointer size to be used for MyISAM tables."),
1690
 
                            NULL, NULL, 6, 2, 7, 0);
1691
 
 
1692
 
static drizzle_sys_var* sys_variables[]= {
1693
 
  DRIZZLE_SYSVAR(key_cache_block_size),
1694
 
  DRIZZLE_SYSVAR(key_cache_size),
1695
 
  DRIZZLE_SYSVAR(key_cache_division_limit),
1696
 
  DRIZZLE_SYSVAR(key_cache_age_threshold),
1697
 
  DRIZZLE_SYSVAR(repair_threads),
1698
 
  DRIZZLE_SYSVAR(max_sort_file_size),
1699
 
  DRIZZLE_SYSVAR(sort_buffer_size),
1700
 
  DRIZZLE_SYSVAR(data_pointer_size),
1701
 
  NULL
1702
 
};
1703
 
 
1704
 
 
1705
 
DRIZZLE_DECLARE_PLUGIN
1706
 
{
1707
 
  DRIZZLE_VERSION_ID,
 
1794
 
 
1795
/****************************************************************************
 
1796
 * MyISAM MRR implementation: use DS-MRR
 
1797
 ***************************************************************************/
 
1798
 
 
1799
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
 
1800
                                     uint32_t n_ranges, uint32_t mode, 
 
1801
                                     HANDLER_BUFFER *buf)
 
1802
{
 
1803
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index], 
 
1804
                           seq, seq_init_param, n_ranges, mode, buf);
 
1805
}
 
1806
 
 
1807
int ha_myisam::multi_range_read_next(char **range_info)
 
1808
{
 
1809
  return ds_mrr.dsmrr_next(this, range_info);
 
1810
}
 
1811
 
 
1812
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
1813
                                               void *seq_init_param, 
 
1814
                                               uint32_t n_ranges, uint32_t *bufsz,
 
1815
                                               uint32_t *flags, COST_VECT *cost)
 
1816
{
 
1817
  /*
 
1818
    This call is here because there is no location where this->table would
 
1819
    already be known.
 
1820
    TODO: consider moving it into some per-query initialization call.
 
1821
  */
 
1822
  ds_mrr.init(this, table);
 
1823
  return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
 
1824
                                 flags, cost);
 
1825
}
 
1826
 
 
1827
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
 
1828
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
1829
{
 
1830
  ds_mrr.init(this, table);
 
1831
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 
1832
}
 
1833
 
 
1834
/* MyISAM MRR implementation ends */
 
1835
 
 
1836
 
 
1837
/* Index condition pushdown implementation*/
 
1838
 
 
1839
 
 
1840
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
 
1841
{
 
1842
  pushed_idx_cond_keyno= keyno_arg;
 
1843
  pushed_idx_cond= idx_cond_arg;
 
1844
  in_range_check_pushed_down= true;
 
1845
  if (active_index == pushed_idx_cond_keyno)
 
1846
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
 
1847
  return NULL;
 
1848
}
 
1849
 
 
1850
 
 
1851
mysql_declare_plugin(myisam)
 
1852
{
 
1853
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1708
1854
  "MyISAM",
1709
1855
  "1.0",
1710
1856
  "MySQL AB",
1711
1857
  "Default engine as of MySQL 3.23 with great performance",
1712
1858
  PLUGIN_LICENSE_GPL,
1713
1859
  myisam_init, /* Plugin Init */
1714
 
  sys_variables,           /* system variables */
 
1860
  myisam_deinit, /* Plugin Deinit */
 
1861
  NULL,                       /* status variables                */
 
1862
  NULL,                       /* system variables                */
1715
1863
  NULL                        /* config options                  */
1716
1864
}
1717
 
DRIZZLE_DECLARE_PLUGIN_END;
 
1865
mysql_declare_plugin_end;