~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/ha_myisam.cc

  • Committer: Brian Aker
  • Date: 2009-06-08 02:42:24 UTC
  • mfrom: (1054.1.6 merge)
  • Revision ID: brian@gaz-20090608024224-zlff1bpq62r8m5gy
Removal of LOCK TABLES.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
 
17
 
 
18
 
#include "config.h"
19
 
#include "drizzled/internal/my_bit.h"
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
 
 
17
 
 
18
#include <drizzled/server_includes.h>
 
19
#include <mysys/my_bit.h>
20
20
#include "myisampack.h"
21
21
#include "ha_myisam.h"
22
 
#include "myisam_priv.h"
23
 
#include "drizzled/option.h"
24
 
#include "drizzled/internal/my_bit.h"
25
 
#include "drizzled/internal/m_string.h"
26
 
#include "drizzled/util/test.h"
27
 
#include "drizzled/error.h"
28
 
#include "drizzled/errmsg_print.h"
29
 
#include "drizzled/gettext.h"
30
 
#include "drizzled/session.h"
31
 
#include "drizzled/plugin.h"
32
 
#include "drizzled/plugin/client.h"
33
 
#include "drizzled/table.h"
34
 
#include "drizzled/field/timestamp.h"
35
 
#include "drizzled/memory/multi_malloc.h"
36
 
#include "drizzled/plugin/daemon.h"
37
 
 
38
 
#include <boost/algorithm/string.hpp>
39
 
#include <boost/scoped_ptr.hpp>
 
22
#include "myisamdef.h"
 
23
#include <drizzled/util/test.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/errmsg_print.h>
 
26
#include <drizzled/gettext.h>
 
27
#include <drizzled/session.h>
 
28
#include <drizzled/protocol.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/field/timestamp.h>
40
31
 
41
32
#include <string>
42
 
#include <sstream>
43
 
#include <map>
44
 
#include <algorithm>
45
 
#include <memory>
46
 
#include <boost/program_options.hpp>
47
 
#include <drizzled/module/option_map.h>
48
 
 
49
 
namespace po= boost::program_options;
50
33
 
51
34
using namespace std;
52
 
using namespace drizzled;
53
35
 
54
36
static const string engine_name("MyISAM");
55
37
 
56
 
boost::mutex THR_LOCK_myisam;
 
38
ulong myisam_recover_options= HA_RECOVER_NONE;
 
39
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
57
40
 
58
 
static uint32_t myisam_key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
59
 
static uint32_t myisam_key_cache_size;
60
 
static uint32_t myisam_key_cache_division_limit;
61
 
static uint32_t myisam_key_cache_age_threshold;
 
41
static uint32_t repair_threads;
 
42
static uint32_t block_size;
62
43
static uint64_t max_sort_file_size;
63
 
typedef constrained_check<size_t, SIZE_MAX, 1024, 1024> sort_buffer_constraint;
64
 
static sort_buffer_constraint sort_buffer_size;
65
 
 
66
 
void st_mi_isam_share::setKeyCache()
67
 
{
68
 
  (void)init_key_cache(&key_cache,
69
 
                       myisam_key_cache_block_size,
70
 
                       myisam_key_cache_size,
71
 
                       myisam_key_cache_division_limit, 
72
 
                       myisam_key_cache_age_threshold);
73
 
}
 
44
static uint64_t sort_buffer_size;
 
45
 
 
46
/* bits in myisam_recover_options */
 
47
const char *myisam_recover_names[] =
 
48
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
 
49
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
 
50
                                 myisam_recover_names, NULL};
 
51
 
 
52
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
 
53
                                           "nulls_ignored", NULL};
 
54
TYPELIB myisam_stats_method_typelib= {
 
55
  array_elements(myisam_stats_method_names) - 1, "",
 
56
  myisam_stats_method_names, NULL};
 
57
 
74
58
 
75
59
/*****************************************************************************
76
60
** MyISAM tables
82
66
  NULL
83
67
};
84
68
 
85
 
class MyisamEngine : public plugin::StorageEngine
 
69
class MyisamEngine : public StorageEngine
86
70
{
87
 
  MyisamEngine();
88
 
  MyisamEngine(const MyisamEngine&);
89
 
  MyisamEngine& operator=(const MyisamEngine&);
90
71
public:
91
 
  explicit MyisamEngine(string name_arg) :
92
 
    plugin::StorageEngine(name_arg,
93
 
                          HTON_CAN_INDEX_BLOBS |
94
 
                          HTON_STATS_RECORDS_IS_EXACT |
95
 
                          HTON_TEMPORARY_ONLY |
96
 
                          HTON_NULL_IN_KEY |
97
 
                          HTON_HAS_RECORDS |
98
 
                          HTON_DUPLICATE_POS |
99
 
                          HTON_AUTO_PART_KEY |
100
 
                          HTON_SKIP_STORE_LOCK)
101
 
  {
102
 
  }
103
 
 
104
 
  virtual ~MyisamEngine()
105
 
  { 
106
 
    mi_panic(HA_PANIC_CLOSE);
107
 
  }
108
 
 
109
 
  virtual Cursor *create(Table &table)
110
 
  {
111
 
    return new ha_myisam(*this, table);
 
72
  MyisamEngine(string name_arg)
 
73
   : StorageEngine(name_arg, HTON_CAN_RECREATE) {}
 
74
 
 
75
  virtual handler *create(TableShare *table,
 
76
                          MEM_ROOT *mem_root)
 
77
  {
 
78
    return new (mem_root) ha_myisam(this, table);
112
79
  }
113
80
 
114
81
  const char **bas_ext() const {
115
82
    return ha_myisam_exts;
116
83
  }
117
84
 
118
 
  int doCreateTable(Session&,
119
 
                    Table& table_arg,
120
 
                    const TableIdentifier &identifier,
121
 
                    message::Table&);
122
 
 
123
 
  int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
124
 
 
125
 
  int doDropTable(Session&, const TableIdentifier &identifier);
126
 
 
127
 
  int doGetTableDefinition(Session& session,
128
 
                           const TableIdentifier &identifier,
129
 
                           message::Table &table_message);
130
 
 
131
 
  uint32_t max_supported_keys()          const { return MI_MAX_KEY; }
132
 
  uint32_t max_supported_key_length()    const { return MI_MAX_KEY_LENGTH; }
133
 
  uint32_t max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
134
 
 
135
 
  uint32_t index_flags(enum  ha_key_alg) const
136
 
  {
137
 
    return (HA_READ_NEXT |
138
 
            HA_READ_PREV |
139
 
            HA_READ_RANGE |
140
 
            HA_READ_ORDER |
141
 
            HA_KEYREAD_ONLY);
142
 
  }
143
 
  bool doDoesTableExist(Session& session, const TableIdentifier &identifier);
144
 
 
145
 
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
146
 
                             const drizzled::SchemaIdentifier &schema_identifier,
147
 
                             drizzled::TableIdentifier::vector &set_of_identifiers);
148
 
  bool validateCreateTableOption(const std::string &key, const std::string &state)
149
 
  {
150
 
    (void)state;
151
 
    if (boost::iequals(key, "ROW_FORMAT"))
152
 
    {
153
 
      return true;
154
 
    }
155
 
 
156
 
    return false;
157
 
  }
 
85
  int createTableImpl(Session *, const char *table_name,
 
86
                      Table *table_arg, HA_CREATE_INFO *ha_create_info);
 
87
 
 
88
  int renameTableImpl(Session*, const char *from, const char *to);
 
89
 
 
90
  int deleteTableImpl(Session*, const string table_name);
158
91
};
159
92
 
160
 
void MyisamEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
161
 
                                         const drizzled::SchemaIdentifier&,
162
 
                                         drizzled::TableIdentifier::vector&)
163
 
{
164
 
}
165
 
 
166
 
bool MyisamEngine::doDoesTableExist(Session &session, const TableIdentifier &identifier)
167
 
{
168
 
  return session.getMessageCache().doesTableMessageExist(identifier);
169
 
}
170
 
 
171
 
int MyisamEngine::doGetTableDefinition(Session &session,
172
 
                                       const TableIdentifier &identifier,
173
 
                                       message::Table &table_message)
174
 
{
175
 
  if (session.getMessageCache().getTableMessage(identifier, table_message))
176
 
    return EEXIST;
177
 
  return ENOENT;
178
 
}
179
 
 
180
 
/* 
181
 
  Convert to push_Warnings if you ever care about this, otherwise, it is a no-op.
182
 
*/
183
 
 
184
 
static void mi_check_print_msg(MI_CHECK *,      const char* ,
185
 
                               const char *, va_list )
186
 
{
 
93
// collect errors printed by mi_check routines
 
94
 
 
95
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
 
96
                               const char *fmt, va_list args)
 
97
{
 
98
  Session* session = (Session*)param->session;
 
99
  Protocol *protocol= session->protocol;
 
100
  uint32_t length, msg_length;
 
101
  char msgbuf[MI_MAX_MSG_BUF];
 
102
  char name[NAME_LEN*2+2];
 
103
 
 
104
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
 
105
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
 
106
 
 
107
  if (!session->protocol->isConnected())
 
108
  {
 
109
    errmsg_printf(ERRMSG_LVL_ERROR, "%s",msgbuf);
 
110
    return;
 
111
  }
 
112
 
 
113
  if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
 
114
                         T_AUTO_REPAIR))
 
115
  {
 
116
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
 
117
    return;
 
118
  }
 
119
  length= sprintf(name,"%s.%s",param->db_name,param->table_name);
 
120
 
 
121
  /*
 
122
    TODO: switch from protocol to push_warning here. The main reason we didn't
 
123
    it yet is parallel repair. Due to following trace:
 
124
    mi_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
 
125
 
 
126
    Also we likely need to lock mutex here (in both cases with protocol and
 
127
    push_warning).
 
128
  */
 
129
  protocol->prepareForResend();
 
130
  protocol->store(name, length, system_charset_info);
 
131
  protocol->store(param->op_name, system_charset_info);
 
132
  protocol->store(msg_type, system_charset_info);
 
133
  protocol->store(msgbuf, msg_length, system_charset_info);
 
134
  if (protocol->write())
 
135
    errmsg_printf(ERRMSG_LVL_ERROR, "Failed on drizzleclient_net_write, writing to stderr instead: %s\n",
 
136
                    msgbuf);
 
137
  return;
187
138
}
188
139
 
189
140
 
203
154
    table conformance in merge engine.
204
155
 
205
156
    The caller needs to free *recinfo_out after use. Since *recinfo_out
206
 
    and *keydef_out are allocated with a multi_malloc, *keydef_out
 
157
    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
207
158
    is freed automatically when *recinfo_out is freed.
208
159
 
209
160
  RETURN VALUE
211
162
    !0 error code
212
163
*/
213
164
 
214
 
static int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
215
 
                        MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
 
165
int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
 
166
                 MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
216
167
{
217
168
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
218
169
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
219
170
  unsigned char *record;
 
171
  KEY *pos;
220
172
  MI_KEYDEF *keydef;
221
173
  MI_COLUMNDEF *recinfo, *recinfo_pos;
222
174
  HA_KEYSEG *keyseg;
223
 
  TableShare *share= table_arg->getMutableShare();
 
175
  TableShare *share= table_arg->s;
224
176
  uint32_t options= share->db_options_in_use;
225
 
  if (!(memory::multi_malloc(false,
226
 
          recinfo_out, (share->sizeFields() * 2 + 2) * sizeof(MI_COLUMNDEF),
227
 
          keydef_out, share->sizeKeys() * sizeof(MI_KEYDEF),
228
 
          &keyseg, (share->key_parts + share->sizeKeys()) * sizeof(HA_KEYSEG),
 
177
  if (!(my_multi_malloc(MYF(MY_WME),
 
178
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
 
179
          keydef_out, share->keys * sizeof(MI_KEYDEF),
 
180
          &keyseg,
 
181
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
229
182
          NULL)))
230
 
    return(HA_ERR_OUT_OF_MEM);
 
183
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
231
184
  keydef= *keydef_out;
232
185
  recinfo= *recinfo_out;
233
 
  for (i= 0; i < share->sizeKeys(); i++)
 
186
  pos= table_arg->key_info;
 
187
  for (i= 0; i < share->keys; i++, pos++)
234
188
  {
235
 
    KeyInfo *pos= &table_arg->key_info[i];
236
189
    keydef[i].flag= ((uint16_t) pos->flags & (HA_NOSAME));
237
190
    keydef[i].key_alg= HA_KEY_ALG_BTREE;
238
191
    keydef[i].block_length= pos->block_size;
250
203
      {
251
204
        if (pos->key_part[j].length > 8 &&
252
205
            (type == HA_KEYTYPE_TEXT ||
 
206
             type == HA_KEYTYPE_NUM ||
253
207
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
254
208
        {
255
209
          /* No blobs here */
273
227
      {
274
228
        keydef[i].seg[j].null_bit= field->null_bit;
275
229
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
276
 
                                           (unsigned char*) table_arg->getInsertRecord());
 
230
                                           (unsigned char*) table_arg->record[0]);
277
231
      }
278
232
      else
279
233
      {
292
246
  }
293
247
  if (table_arg->found_next_number_field)
294
248
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
295
 
  record= table_arg->getInsertRecord();
 
249
  record= table_arg->record[0];
296
250
  recpos= 0;
297
251
  recinfo_pos= recinfo;
298
252
  while (recpos < (uint) share->stored_rec_length)
299
253
  {
300
254
    Field **field, *found= 0;
301
 
    minpos= share->getRecordLength();
 
255
    minpos= share->reclength;
302
256
    length= 0;
303
257
 
304
 
    for (field= table_arg->getFields(); *field; field++)
 
258
    for (field= table_arg->field; *field; field++)
305
259
    {
306
260
      if ((fieldpos= (*field)->offset(record)) >= recpos &&
307
261
          fieldpos <= minpos)
341
295
    {
342
296
      recinfo_pos->null_bit= found->null_bit;
343
297
      recinfo_pos->null_pos= (uint) (found->null_ptr -
344
 
                                     (unsigned char*) table_arg->getInsertRecord());
 
298
                                     (unsigned char*) table_arg->record[0]);
345
299
    }
346
300
    else
347
301
    {
355
309
  return(0);
356
310
}
357
311
 
358
 
int ha_myisam::reset_auto_increment(uint64_t value)
359
 
{
360
 
  file->s->state.auto_increment= value;
361
 
  return 0;
362
 
}
363
312
 
364
313
/*
365
314
  Check for underlying table conformance
401
350
      (should be corretly detected in table2myisam).
402
351
*/
403
352
 
404
 
static int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
405
 
                            uint32_t t1_keys, uint32_t t1_recs,
406
 
                            MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
407
 
                            uint32_t t2_keys, uint32_t t2_recs, bool strict)
 
353
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
 
354
                     uint32_t t1_keys, uint32_t t1_recs,
 
355
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
 
356
                     uint32_t t2_keys, uint32_t t2_recs, bool strict)
408
357
{
409
358
  uint32_t i, j;
410
359
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
439
388
      {
440
389
        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
441
390
            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
442
 
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1;
 
391
          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
443
392
        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
444
393
                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
445
 
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1;
 
394
          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
446
395
      }
447
396
 
448
397
      if (t1_keysegs_j__type != t2_keysegs[j].type ||
476
425
}
477
426
 
478
427
 
 
428
extern "C" {
 
429
 
479
430
volatile int *killed_ptr(MI_CHECK *param)
480
431
{
481
432
  /* In theory Unsafe conversion, but should be ok for now */
482
 
  return (int*) (((Session *)(param->session))->getKilledPtr());
 
433
  return (int*) &(((Session *)(param->session))->killed);
483
434
}
484
435
 
485
436
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
529
480
                        const char *sfile, uint32_t sline)
530
481
{
531
482
  Session *cur_session;
 
483
  pthread_mutex_lock(&file->s->intern_lock);
532
484
  if ((cur_session= file->in_use))
533
485
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
534
486
                    cur_session->thread_id,
543
495
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
544
496
    ++it;
545
497
  }
546
 
}
547
 
 
548
 
ha_myisam::ha_myisam(plugin::StorageEngine &engine_arg,
549
 
                     Table &table_arg)
550
 
  : Cursor(engine_arg, table_arg),
551
 
  file(0),
552
 
  can_enable_indexes(true),
553
 
  is_ordered(true)
554
 
{ }
555
 
 
556
 
Cursor *ha_myisam::clone(memory::Root *mem_root)
 
498
  pthread_mutex_unlock(&file->s->intern_lock);
 
499
}
 
500
 
 
501
}
 
502
 
 
503
ha_myisam::ha_myisam(StorageEngine *engine_arg, TableShare *table_arg)
 
504
  :handler(engine_arg, table_arg), file(0),
 
505
  int_table_flags(HA_NULL_IN_KEY |
 
506
                  HA_DUPLICATE_POS |
 
507
                  HA_CAN_INDEX_BLOBS |
 
508
                  HA_AUTO_PART_KEY |
 
509
                  HA_FILE_BASED |
 
510
                  HA_NO_TRANSACTIONS |
 
511
                  HA_HAS_RECORDS |
 
512
                  HA_STATS_RECORDS_IS_EXACT |
 
513
                  HA_NEED_READ_RANGE_BUFFER |
 
514
                  HA_MRR_CANT_SORT),
 
515
   can_enable_indexes(1)
 
516
{}
 
517
 
 
518
handler *ha_myisam::clone(MEM_ROOT *mem_root)
557
519
{
558
 
  ha_myisam *new_handler= static_cast <ha_myisam *>(Cursor::clone(mem_root));
 
520
  ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
559
521
  if (new_handler)
560
522
    new_handler->file->state= file->state;
561
523
  return new_handler;
567
529
}
568
530
 
569
531
/* Name is here without an extension */
570
 
int ha_myisam::doOpen(const drizzled::TableIdentifier &identifier, int mode, uint32_t test_if_locked)
 
532
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
571
533
{
572
534
  MI_KEYDEF *keyinfo;
573
535
  MI_COLUMNDEF *recinfo= 0;
589
551
    open of a table that is in use by other threads already (if the
590
552
    MyISAM share exists already).
591
553
  */
592
 
  if (!(file= mi_open(identifier, mode, test_if_locked)))
593
 
    return (errno ? errno : -1);
594
 
 
595
 
  if (!getTable()->getShare()->getType()) /* No need to perform a check for tmp table */
 
554
  if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
 
555
    return (my_errno ? my_errno : -1);
 
556
  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
596
557
  {
597
 
    if ((errno= table2myisam(getTable(), &keyinfo, &recinfo, &recs)))
 
558
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
598
559
    {
 
560
      /* purecov: begin inspected */
599
561
      goto err;
 
562
      /* purecov: end */
600
563
    }
601
 
    if (check_definition(keyinfo, recinfo, getTable()->getShare()->sizeKeys(), recs,
 
564
    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
602
565
                         file->s->keyinfo, file->s->rec,
603
566
                         file->s->base.keys, file->s->base.fields, true))
604
567
    {
605
 
      errno= HA_ERR_CRASHED;
 
568
      /* purecov: begin inspected */
 
569
      my_errno= HA_ERR_CRASHED;
606
570
      goto err;
 
571
      /* purecov: end */
607
572
    }
608
573
  }
609
574
 
610
 
  assert(test_if_locked);
611
575
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
612
576
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
613
577
 
614
578
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
615
579
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
616
580
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
617
 
  if (!getTable()->getShare()->db_record_offset)
618
 
    is_ordered= false;
619
 
 
 
581
  if (!table->s->db_record_offset)
 
582
    int_table_flags|=HA_REC_NOT_IN_SEQ;
 
583
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
584
    int_table_flags|=HA_HAS_CHECKSUM;
620
585
 
621
586
  keys_with_parts.reset();
622
 
  for (i= 0; i < getTable()->getShare()->sizeKeys(); i++)
 
587
  for (i= 0; i < table->s->keys; i++)
623
588
  {
624
 
    getTable()->key_info[i].block_size= file->s->keyinfo[i].block_length;
 
589
    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
625
590
 
626
 
    KeyPartInfo *kp= getTable()->key_info[i].key_part;
627
 
    KeyPartInfo *kp_end= kp + getTable()->key_info[i].key_parts;
 
591
    KEY_PART_INFO *kp= table->key_info[i].key_part;
 
592
    KEY_PART_INFO *kp_end= kp + table->key_info[i].key_parts;
628
593
    for (; kp != kp_end; kp++)
629
594
    {
630
595
      if (!kp->field->part_of_key.test(i))
634
599
      }
635
600
    }
636
601
  }
637
 
  errno= 0;
 
602
  my_errno= 0;
638
603
  goto end;
639
604
 err:
640
605
  this->close();
641
606
 end:
642
607
  /*
643
 
    Both recinfo and keydef are allocated by multi_malloc(), thus only
 
608
    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
644
609
    recinfo must be freed.
645
610
  */
646
611
  if (recinfo)
647
612
    free((unsigned char*) recinfo);
648
 
  return errno;
 
613
  return my_errno;
649
614
}
650
615
 
651
616
int ha_myisam::close(void)
655
620
  return mi_close(tmp);
656
621
}
657
622
 
658
 
int ha_myisam::doInsertRecord(unsigned char *buf)
 
623
int ha_myisam::write_row(unsigned char *buf)
659
624
{
 
625
  ha_statistic_increment(&SSV::ha_write_count);
 
626
 
660
627
  /*
661
628
    If we have an auto_increment column and we are writing a changed row
662
629
    or a new row, then update the auto_increment value in the record.
663
630
  */
664
 
  if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
 
631
  if (table->next_number_field && buf == table->record[0])
665
632
  {
666
633
    int error;
667
634
    if ((error= update_auto_increment()))
670
637
  return mi_write(file,buf);
671
638
}
672
639
 
 
640
int ha_myisam::check(Session* session, HA_CHECK_OPT* check_opt)
 
641
{
 
642
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
643
  int error;
 
644
  MI_CHECK param;
 
645
  MYISAM_SHARE* share = file->s;
 
646
  const char *old_proc_info= session->get_proc_info();
 
647
 
 
648
  session->set_proc_info("Checking table");
 
649
  myisamchk_init(&param);
 
650
  param.session = session;
 
651
  param.op_name =   "check";
 
652
  param.db_name=    table->s->db.str;
 
653
  param.table_name= table->alias;
 
654
  param.testflag = check_opt->flags | T_CHECK | T_SILENT;
 
655
  param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
 
656
 
 
657
  if (!(table->db_stat & HA_READ_ONLY))
 
658
    param.testflag|= T_STATISTICS;
 
659
  param.using_global_keycache = 1;
 
660
 
 
661
  if (!mi_is_crashed(file) &&
 
662
      (((param.testflag & T_CHECK_ONLY_CHANGED) &&
 
663
        !(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
 
664
                                  STATE_CRASHED_ON_REPAIR)) &&
 
665
        share->state.open_count == 0) ||
 
666
       ((param.testflag & T_FAST) && (share->state.open_count ==
 
667
                                      (uint) (share->global_changed ? 1 : 0)))))
 
668
    return HA_ADMIN_ALREADY_DONE;
 
669
 
 
670
  error = chk_status(&param, file);             // Not fatal
 
671
  error = chk_size(&param, file);
 
672
  if (!error)
 
673
    error |= chk_del(&param, file, param.testflag);
 
674
  if (!error)
 
675
    error = chk_key(&param, file);
 
676
  if (!error)
 
677
  {
 
678
    if ((!(param.testflag & T_QUICK) &&
 
679
         ((share->options &
 
680
           (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
 
681
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
 
682
        mi_is_crashed(file))
 
683
    {
 
684
      uint32_t old_testflag=param.testflag;
 
685
      param.testflag|=T_MEDIUM;
 
686
      if (!(error= init_io_cache(&param.read_cache, file->dfile,
 
687
                                 my_default_record_cache_size, READ_CACHE,
 
688
                                 share->pack.header_length, 1, MYF(MY_WME))))
 
689
      {
 
690
        error= chk_data_link(&param, file, param.testflag & T_EXTEND);
 
691
        end_io_cache(&(param.read_cache));
 
692
      }
 
693
      param.testflag= old_testflag;
 
694
    }
 
695
  }
 
696
  if (!error)
 
697
  {
 
698
    if ((share->state.changed & (STATE_CHANGED |
 
699
                                 STATE_CRASHED_ON_REPAIR |
 
700
                                 STATE_CRASHED | STATE_NOT_ANALYZED)) ||
 
701
        (param.testflag & T_STATISTICS) ||
 
702
        mi_is_crashed(file))
 
703
    {
 
704
      file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
705
      pthread_mutex_lock(&share->intern_lock);
 
706
      share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
 
707
                               STATE_CRASHED_ON_REPAIR);
 
708
      if (!(table->db_stat & HA_READ_ONLY))
 
709
        error=update_state_info(&param,file,UPDATE_TIME | UPDATE_OPEN_COUNT |
 
710
                                UPDATE_STAT);
 
711
      pthread_mutex_unlock(&share->intern_lock);
 
712
      info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 
713
           HA_STATUS_CONST);
 
714
    }
 
715
  }
 
716
  else if (!mi_is_crashed(file) && !session->killed)
 
717
  {
 
718
    mi_mark_crashed(file);
 
719
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
 
720
  }
 
721
 
 
722
  session->set_proc_info(old_proc_info);
 
723
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
724
}
 
725
 
 
726
 
 
727
/*
 
728
  analyze the key distribution in the table
 
729
  As the table may be only locked for read, we have to take into account that
 
730
  two threads may do an analyze at the same time!
 
731
*/
 
732
 
 
733
int ha_myisam::analyze(Session *session,
 
734
                       HA_CHECK_OPT* )
 
735
{
 
736
  int error=0;
 
737
  MI_CHECK param;
 
738
  MYISAM_SHARE* share = file->s;
 
739
 
 
740
  myisamchk_init(&param);
 
741
  param.session = session;
 
742
  param.op_name=    "analyze";
 
743
  param.db_name=    table->s->db.str;
 
744
  param.table_name= table->alias;
 
745
  param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
 
746
                   T_DONT_CHECK_CHECKSUM);
 
747
  param.using_global_keycache = 1;
 
748
  param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
 
749
 
 
750
  if (!(share->state.changed & STATE_NOT_ANALYZED))
 
751
    return HA_ADMIN_ALREADY_DONE;
 
752
 
 
753
  error = chk_key(&param, file);
 
754
  if (!error)
 
755
  {
 
756
    pthread_mutex_lock(&share->intern_lock);
 
757
    error=update_state_info(&param,file,UPDATE_STAT);
 
758
    pthread_mutex_unlock(&share->intern_lock);
 
759
  }
 
760
  else if (!mi_is_crashed(file) && !session->killed)
 
761
    mi_mark_crashed(file);
 
762
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 
763
}
 
764
 
 
765
 
 
766
int ha_myisam::repair(Session* session, HA_CHECK_OPT *check_opt)
 
767
{
 
768
  int error;
 
769
  MI_CHECK param;
 
770
  ha_rows start_records;
 
771
 
 
772
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
773
 
 
774
  myisamchk_init(&param);
 
775
  param.session = session;
 
776
  param.op_name=  "repair";
 
777
  param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
 
778
                   T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
 
779
                   (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
 
780
  param.sort_buffer_length=  (size_t)sort_buffer_size;
 
781
 
 
782
  // Release latches since this can take a long time
 
783
  ha_release_temporary_latches(session);
 
784
 
 
785
  start_records=file->state->records;
 
786
  while ((error=repair(session,param,0)) && param.retry_repair)
 
787
  {
 
788
    param.retry_repair=0;
 
789
    if (test_all_bits(param.testflag,
 
790
                      (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
 
791
    {
 
792
      param.testflag&= ~T_RETRY_WITHOUT_QUICK;
 
793
      errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' without quick",
 
794
                            table->s->path.str);
 
795
      continue;
 
796
    }
 
797
    param.testflag&= ~T_QUICK;
 
798
    if ((param.testflag & T_REP_BY_SORT))
 
799
    {
 
800
      param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
 
801
      errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' with keycache",
 
802
                            table->s->path.str);
 
803
      continue;
 
804
    }
 
805
    break;
 
806
  }
 
807
  if (!error && start_records != file->state->records &&
 
808
      !(check_opt->flags & T_VERY_SILENT))
 
809
  {
 
810
    char llbuff[22],llbuff2[22];
 
811
    errmsg_printf(ERRMSG_LVL_INFO, "Found %s of %s rows when repairing '%s'",
 
812
                          llstr(file->state->records, llbuff),
 
813
                          llstr(start_records, llbuff2),
 
814
                          table->s->path.str);
 
815
  }
 
816
  return error;
 
817
}
 
818
 
 
819
int ha_myisam::optimize(Session* session, HA_CHECK_OPT *check_opt)
 
820
{
 
821
  int error;
 
822
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
 
823
  MI_CHECK param;
 
824
 
 
825
  myisamchk_init(&param);
 
826
  param.session = session;
 
827
  param.op_name= "optimize";
 
828
  param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
 
829
                   T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
 
830
  param.sort_buffer_length= (size_t)sort_buffer_size;
 
831
  if ((error= repair(session,param,1)) && param.retry_repair)
 
832
  {
 
833
    errmsg_printf(ERRMSG_LVL_WARN, "Warning: Optimize table got errno %d on %s.%s, retrying",
 
834
                      my_errno, param.db_name, param.table_name);
 
835
    param.testflag&= ~T_REP_BY_SORT;
 
836
    error= repair(session,param,1);
 
837
  }
 
838
  return error;
 
839
}
 
840
 
673
841
 
674
842
int ha_myisam::repair(Session *session, MI_CHECK &param, bool do_optimize)
675
843
{
693
861
  {
694
862
    errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' failed. "
695
863
                          "Please try REPAIR EXTENDED or myisamchk",
696
 
                          getTable()->getShare()->getPath());
 
864
                          table->s->path.str);
697
865
    return(HA_ADMIN_FAILED);
698
866
  }
699
867
 
700
 
  param.db_name=    getTable()->getShare()->getSchemaName();
701
 
  param.table_name= getTable()->getAlias();
 
868
  param.db_name=    table->s->db.str;
 
869
  param.table_name= table->alias;
702
870
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
703
871
  param.using_global_keycache = 1;
704
872
  param.session= session;
705
873
  param.out_flag= 0;
706
 
  param.sort_buffer_length= static_cast<size_t>(sort_buffer_size);
 
874
  param.sort_buffer_length= (size_t)sort_buffer_size;
707
875
  strcpy(fixed_name,file->filename);
708
876
 
709
877
  // Don't lock tables if we have used LOCK Table
710
 
  if (mi_lock_database(file, getTable()->getShare()->getType() ? F_EXTRA_LCK : F_WRLCK))
 
878
  if (!session->locked_tables &&
 
879
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
711
880
  {
712
 
    mi_check_print_error(&param,ER(ER_CANT_LOCK),errno);
 
881
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
713
882
    return(HA_ADMIN_FAILED);
714
883
  }
715
884
 
728
897
      local_testflag|= T_STATISTICS;
729
898
      param.testflag|= T_STATISTICS;            // We get this for free
730
899
      statistics_done=1;
 
900
      if (repair_threads > 1)
 
901
      {
 
902
        char buf[40];
 
903
        /* TODO: respect myisam_repair_threads variable */
 
904
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
 
905
        session->set_proc_info(buf);
 
906
        error = mi_repair_parallel(&param, file, fixed_name,
 
907
            param.testflag & T_QUICK);
 
908
        session->set_proc_info("Repair done"); // to reset proc_info, as
 
909
                                      // it was pointing to local buffer
 
910
      }
 
911
      else
731
912
      {
732
913
        session->set_proc_info("Repair by sorting");
733
914
        error = mi_repair_by_sort(&param, file, fixed_name,
793
974
    {
794
975
      char llbuff[22],llbuff2[22];
795
976
      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));
 
977
                             llstr(rows,llbuff),
 
978
                             llstr(file->state->records,llbuff2));
798
979
    }
799
980
  }
800
981
  else
804
985
    update_state_info(&param, file, 0);
805
986
  }
806
987
  session->set_proc_info(old_proc_info);
807
 
  mi_lock_database(file,F_UNLCK);
808
 
 
 
988
  if (!session->locked_tables)
 
989
    mi_lock_database(file,F_UNLCK);
809
990
  return(error ? HA_ADMIN_FAILED :
810
991
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
811
992
}
812
993
 
813
994
 
814
995
/*
 
996
  Assign table indexes to a specific key cache.
 
997
*/
 
998
 
 
999
int ha_myisam::assign_to_keycache(Session* session, HA_CHECK_OPT *check_opt)
 
1000
{
 
1001
  KEY_CACHE *new_key_cache= check_opt->key_cache;
 
1002
  const char *errmsg= 0;
 
1003
  int error= HA_ADMIN_OK;
 
1004
  TableList *table_list= table->pos_in_table_list;
 
1005
 
 
1006
  table->keys_in_use_for_query.reset();
 
1007
 
 
1008
  if (table_list->process_index_hints(table))
 
1009
    return(HA_ADMIN_FAILED);
 
1010
 
 
1011
  if ((error= mi_assign_to_key_cache(file, new_key_cache)))
 
1012
  {
 
1013
    char buf[STRING_BUFFER_USUAL_SIZE];
 
1014
    snprintf(buf, sizeof(buf),
 
1015
                "Failed to flush to index file (errno: %d)", error);
 
1016
    errmsg= buf;
 
1017
    error= HA_ADMIN_CORRUPT;
 
1018
  }
 
1019
 
 
1020
  if (error != HA_ADMIN_OK)
 
1021
  {
 
1022
    /* Send error to user */
 
1023
    MI_CHECK param;
 
1024
    myisamchk_init(&param);
 
1025
    param.session= session;
 
1026
    param.op_name=    "assign_to_keycache";
 
1027
    param.db_name=    table->s->db.str;
 
1028
    param.table_name= table->s->table_name.str;
 
1029
    param.testflag= 0;
 
1030
    mi_check_print_error(&param, errmsg);
 
1031
  }
 
1032
  return(error);
 
1033
}
 
1034
 
 
1035
 
 
1036
/*
815
1037
  Disable indexes, making it persistent if requested.
816
1038
 
817
1039
  SYNOPSIS
870
1092
    Enable indexes, which might have been disabled by disable_index() before.
871
1093
    The modes without _SAVE work only if both data and indexes are empty,
872
1094
    since the MyISAM repair would enable them persistently.
873
 
    To be sure in these cases, call Cursor::delete_all_rows() before.
 
1095
    To be sure in these cases, call handler::delete_all_rows() before.
874
1096
 
875
1097
  IMPLEMENTATION
876
1098
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
904
1126
  }
905
1127
  else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
906
1128
  {
907
 
    Session *session= getTable()->in_use;
908
 
    boost::scoped_ptr<MI_CHECK> param_ap(new MI_CHECK);
909
 
    MI_CHECK &param= *param_ap.get();
 
1129
    Session *session=current_session;
 
1130
    MI_CHECK param;
910
1131
    const char *save_proc_info= session->get_proc_info();
911
1132
    session->set_proc_info("Creating index");
912
1133
    myisamchk_init(&param);
914
1135
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
915
1136
                     T_CREATE_MISSING_KEYS);
916
1137
    param.myf_rw&= ~MY_WAIT_IF_FULL;
917
 
    param.sort_buffer_length=  static_cast<size_t>(sort_buffer_size);
918
 
    param.stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
 
1138
    param.sort_buffer_length=  (size_t)sort_buffer_size;
 
1139
    param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
919
1140
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
920
1141
    {
921
1142
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
922
 
                        errno, param.db_name, param.table_name);
 
1143
                        my_errno, param.db_name, param.table_name);
923
1144
      /* Repairing by sort failed. Now try standard repair method. */
924
1145
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
925
1146
      error= (repair(session,param,0) != HA_ADMIN_OK);
981
1202
 
982
1203
void ha_myisam::start_bulk_insert(ha_rows rows)
983
1204
{
984
 
  Session *session= getTable()->in_use;
985
 
  ulong size= session->variables.read_buff_size;
 
1205
  Session *session= current_session;
 
1206
  ulong size= cmin(session->variables.read_buff_size,
 
1207
                  (ulong) (table->s->avg_row_length*rows));
986
1208
 
987
1209
  /* don't enable row cache if too few rows */
988
1210
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
1008
1230
                          (size_t)session->variables.bulk_insert_buff_size,
1009
1231
                          rows);
1010
1232
    }
 
1233
 
 
1234
  return;
1011
1235
}
1012
1236
 
1013
1237
/*
1032
1256
}
1033
1257
 
1034
1258
 
1035
 
 
1036
 
int ha_myisam::doUpdateRecord(const unsigned char *old_data, unsigned char *new_data)
1037
 
{
 
1259
bool ha_myisam::check_and_repair(Session *session)
 
1260
{
 
1261
  int error=0;
 
1262
  int marked_crashed;
 
1263
  char *old_query;
 
1264
  uint32_t old_query_length;
 
1265
  HA_CHECK_OPT check_opt;
 
1266
 
 
1267
  check_opt.init();
 
1268
  check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
 
1269
  // Don't use quick if deleted rows
 
1270
  if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
 
1271
    check_opt.flags|=T_QUICK;
 
1272
  errmsg_printf(ERRMSG_LVL_WARN, "Checking table:   '%s'",table->s->path.str);
 
1273
 
 
1274
  old_query= session->query;
 
1275
  old_query_length= session->query_length;
 
1276
  pthread_mutex_lock(&LOCK_thread_count);
 
1277
  session->query=        table->s->table_name.str;
 
1278
  session->query_length= table->s->table_name.length;
 
1279
  pthread_mutex_unlock(&LOCK_thread_count);
 
1280
 
 
1281
  if ((marked_crashed= mi_is_crashed(file)) || check(session, &check_opt))
 
1282
  {
 
1283
    errmsg_printf(ERRMSG_LVL_WARN, "Recovering table: '%s'",table->s->path.str);
 
1284
    check_opt.flags=
 
1285
      ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
 
1286
       (marked_crashed                             ? 0 : T_QUICK) |
 
1287
       (myisam_recover_options & HA_RECOVER_FORCE  ? 0 : T_SAFE_REPAIR) |
 
1288
       T_AUTO_REPAIR);
 
1289
    if (repair(session, &check_opt))
 
1290
      error=1;
 
1291
  }
 
1292
  pthread_mutex_lock(&LOCK_thread_count);
 
1293
  session->query= old_query;
 
1294
  session->query_length= old_query_length;
 
1295
  pthread_mutex_unlock(&LOCK_thread_count);
 
1296
  return(error);
 
1297
}
 
1298
 
 
1299
bool ha_myisam::is_crashed() const
 
1300
{
 
1301
  return (file->s->state.changed & STATE_CRASHED ||
 
1302
          (file->s->state.open_count));
 
1303
}
 
1304
 
 
1305
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
 
1306
{
 
1307
  ha_statistic_increment(&SSV::ha_update_count);
 
1308
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
1309
    table->timestamp_field->set_time();
1038
1310
  return mi_update(file,old_data,new_data);
1039
1311
}
1040
1312
 
1041
 
int ha_myisam::doDeleteRecord(const unsigned char *buf)
 
1313
int ha_myisam::delete_row(const unsigned char *buf)
1042
1314
{
 
1315
  ha_statistic_increment(&SSV::ha_delete_count);
1043
1316
  return mi_delete(file,buf);
1044
1317
}
1045
1318
 
1046
 
 
1047
 
int ha_myisam::doStartIndexScan(uint32_t idx, bool )
 
1319
#ifdef __cplusplus
 
1320
extern "C" {
 
1321
#endif
 
1322
 
 
1323
bool index_cond_func_myisam(void *arg)
 
1324
{
 
1325
  ha_myisam *h= (ha_myisam*)arg;
 
1326
  /*if (h->in_range_read)*/
 
1327
  if (h->end_range)
 
1328
  {
 
1329
    if (h->compare_key2(h->end_range) > 0)
 
1330
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
 
1331
  }
 
1332
  return (bool)h->pushed_idx_cond->val_int();
 
1333
}
 
1334
 
 
1335
#ifdef __cplusplus
 
1336
}
 
1337
#endif
 
1338
 
 
1339
 
 
1340
int ha_myisam::index_init(uint32_t idx, bool )
1048
1341
{
1049
1342
  active_index=idx;
1050
1343
  //in_range_read= false;
 
1344
  if (pushed_idx_cond_keyno == idx)
 
1345
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
1051
1346
  return 0;
1052
1347
}
1053
1348
 
1054
1349
 
1055
 
int ha_myisam::doEndIndexScan()
 
1350
int ha_myisam::index_end()
1056
1351
{
1057
1352
  active_index=MAX_KEY;
 
1353
  //pushed_idx_cond_keyno= MAX_KEY;
 
1354
  mi_set_index_cond_func(file, NULL, 0);
 
1355
  in_range_check_pushed_down= false;
 
1356
  ds_mrr.dsmrr_close();
1058
1357
  return 0;
1059
1358
}
1060
1359
 
1061
1360
 
 
1361
uint32_t ha_myisam::index_flags(uint32_t inx, uint32_t, bool) const
 
1362
{
 
1363
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
 
1364
          0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
 
1365
          HA_READ_ORDER | HA_KEYREAD_ONLY |
 
1366
          (keys_with_parts.test(inx)?0:HA_DO_INDEX_COND_PUSHDOWN));
 
1367
}
 
1368
 
 
1369
 
1062
1370
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
1063
1371
                              key_part_map keypart_map,
1064
1372
                              enum ha_rkey_function find_flag)
1065
1373
{
1066
1374
  assert(inited==INDEX);
1067
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1375
  ha_statistic_increment(&SSV::ha_read_key_count);
1068
1376
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1069
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1377
  table->status=error ? STATUS_NOT_FOUND: 0;
1070
1378
  return error;
1071
1379
}
1072
1380
 
1074
1382
                                  key_part_map keypart_map,
1075
1383
                                  enum ha_rkey_function find_flag)
1076
1384
{
1077
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1385
  ha_statistic_increment(&SSV::ha_read_key_count);
1078
1386
  int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
1079
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1387
  table->status=error ? STATUS_NOT_FOUND: 0;
1080
1388
  return error;
1081
1389
}
1082
1390
 
1084
1392
                                   key_part_map keypart_map)
1085
1393
{
1086
1394
  assert(inited==INDEX);
1087
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
1395
  ha_statistic_increment(&SSV::ha_read_key_count);
1088
1396
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1089
1397
                    HA_READ_PREFIX_LAST);
1090
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1398
  table->status=error ? STATUS_NOT_FOUND: 0;
1091
1399
  return(error);
1092
1400
}
1093
1401
 
1094
1402
int ha_myisam::index_next(unsigned char *buf)
1095
1403
{
1096
1404
  assert(inited==INDEX);
1097
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1405
  ha_statistic_increment(&SSV::ha_read_next_count);
1098
1406
  int error=mi_rnext(file,buf,active_index);
1099
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1407
  table->status=error ? STATUS_NOT_FOUND: 0;
1100
1408
  return error;
1101
1409
}
1102
1410
 
1103
1411
int ha_myisam::index_prev(unsigned char *buf)
1104
1412
{
1105
1413
  assert(inited==INDEX);
1106
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
1414
  ha_statistic_increment(&SSV::ha_read_prev_count);
1107
1415
  int error=mi_rprev(file,buf, active_index);
1108
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1416
  table->status=error ? STATUS_NOT_FOUND: 0;
1109
1417
  return error;
1110
1418
}
1111
1419
 
1112
1420
int ha_myisam::index_first(unsigned char *buf)
1113
1421
{
1114
1422
  assert(inited==INDEX);
1115
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
1423
  ha_statistic_increment(&SSV::ha_read_first_count);
1116
1424
  int error=mi_rfirst(file, buf, active_index);
1117
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1425
  table->status=error ? STATUS_NOT_FOUND: 0;
1118
1426
  return error;
1119
1427
}
1120
1428
 
1121
1429
int ha_myisam::index_last(unsigned char *buf)
1122
1430
{
1123
1431
  assert(inited==INDEX);
1124
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
1432
  ha_statistic_increment(&SSV::ha_read_last_count);
1125
1433
  int error=mi_rlast(file, buf, active_index);
1126
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1434
  table->status=error ? STATUS_NOT_FOUND: 0;
1127
1435
  return error;
1128
1436
}
1129
1437
 
1133
1441
{
1134
1442
  int error;
1135
1443
  assert(inited==INDEX);
1136
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
1444
  ha_statistic_increment(&SSV::ha_read_next_count);
1137
1445
  do
1138
1446
  {
1139
1447
    error= mi_rnext_same(file,buf);
1140
1448
  } while (error == HA_ERR_RECORD_DELETED);
1141
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1449
  table->status=error ? STATUS_NOT_FOUND: 0;
1142
1450
  return error;
1143
1451
}
1144
1452
 
1151
1459
  //if (!eq_range_arg)
1152
1460
  //  in_range_read= true;
1153
1461
 
1154
 
  res= Cursor::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
1462
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
1155
1463
 
1156
1464
  //if (res)
1157
1465
  //  in_range_read= false;
1161
1469
 
1162
1470
int ha_myisam::read_range_next()
1163
1471
{
1164
 
  int res= Cursor::read_range_next();
 
1472
  int res= handler::read_range_next();
1165
1473
  //if (res)
1166
1474
  //  in_range_read= false;
1167
1475
  return res;
1168
1476
}
1169
1477
 
1170
1478
 
1171
 
int ha_myisam::doStartTableScan(bool scan)
 
1479
int ha_myisam::rnd_init(bool scan)
1172
1480
{
1173
1481
  if (scan)
1174
1482
    return mi_scan_init(file);
1177
1485
 
1178
1486
int ha_myisam::rnd_next(unsigned char *buf)
1179
1487
{
1180
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
1488
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1181
1489
  int error=mi_scan(file, buf);
1182
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1490
  table->status=error ? STATUS_NOT_FOUND: 0;
1183
1491
  return error;
1184
1492
}
1185
1493
 
 
1494
int ha_myisam::restart_rnd_next(unsigned char *buf, unsigned char *pos)
 
1495
{
 
1496
  return rnd_pos(buf,pos);
 
1497
}
 
1498
 
1186
1499
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
1187
1500
{
1188
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
1189
 
  int error=mi_rrnd(file, buf, internal::my_get_ptr(pos,ref_length));
1190
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
1501
  ha_statistic_increment(&SSV::ha_read_rnd_count);
 
1502
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
 
1503
  table->status=error ? STATUS_NOT_FOUND: 0;
1191
1504
  return error;
1192
1505
}
1193
1506
 
1194
1507
 
1195
1508
void ha_myisam::position(const unsigned char *)
1196
1509
{
1197
 
  internal::my_off_t row_position= mi_position(file);
1198
 
  internal::my_store_ptr(ref, ref_length, row_position);
 
1510
  my_off_t row_position= mi_position(file);
 
1511
  my_store_ptr(ref, ref_length, row_position);
1199
1512
}
1200
1513
 
1201
1514
int ha_myisam::info(uint32_t flag)
1216
1529
  }
1217
1530
  if (flag & HA_STATUS_CONST)
1218
1531
  {
1219
 
    TableShare *share= getTable()->getMutableShare();
 
1532
    TableShare *share= table->s;
1220
1533
    stats.max_data_file_length=  misam_info.max_data_file_length;
1221
1534
    stats.max_index_file_length= misam_info.max_index_file_length;
1222
1535
    stats.create_time= misam_info.create_time;
1223
1536
    ref_length= misam_info.reflength;
1224
1537
    share->db_options_in_use= misam_info.options;
1225
 
    stats.block_size= myisam_key_cache_block_size;        /* record block size */
 
1538
    stats.block_size= block_size;        /* record block size */
1226
1539
 
1227
 
    set_prefix(share->keys_in_use, share->sizeKeys());
1228
 
    /*
1229
 
     * Due to bug 394932 (32-bit solaris build failure), we need
1230
 
     * to convert the uint64_t key_map member of the misam_info
1231
 
     * structure in to a std::bitset so that we can logically and
1232
 
     * it with the share->key_in_use key_map.
1233
 
     */
1234
 
    ostringstream ostr;
1235
 
    string binary_key_map;
1236
 
    uint64_t num= misam_info.key_map;
1237
 
    /*
1238
 
     * Convert the uint64_t to a binary
1239
 
     * string representation of it.
1240
 
     */
1241
 
    while (num > 0)
1242
 
    {
1243
 
      uint64_t bin_digit= num % 2;
1244
 
      ostr << bin_digit;
1245
 
      num/= 2;
1246
 
    }
1247
 
    binary_key_map.append(ostr.str());
1248
 
    /*
1249
 
     * Now we have the binary string representation of the
1250
 
     * flags, we need to fill that string representation out
1251
 
     * with the appropriate number of bits. This is needed
1252
 
     * since key_map is declared as a std::bitset of a certain bit
1253
 
     * width that depends on the MAX_INDEXES variable. 
1254
 
     */
1255
 
    if (MAX_INDEXES <= 64)
1256
 
    {
1257
 
      size_t len= 72 - binary_key_map.length();
1258
 
      string all_zeros(len, '0');
1259
 
      binary_key_map.insert(binary_key_map.begin(),
1260
 
                            all_zeros.begin(),
1261
 
                            all_zeros.end());
1262
 
    }
1263
 
    else
1264
 
    {
1265
 
      size_t len= (MAX_INDEXES + 7) / 8 * 8;
1266
 
      string all_zeros(len, '0');
1267
 
      binary_key_map.insert(binary_key_map.begin(),
1268
 
                            all_zeros.begin(),
1269
 
                            all_zeros.end());
1270
 
    }
1271
 
    key_map tmp_map(binary_key_map);
1272
 
    share->keys_in_use&= tmp_map;
 
1540
    /* Update share */
 
1541
    if (share->tmp_table == NO_TMP_TABLE)
 
1542
      pthread_mutex_lock(&share->mutex);
 
1543
    set_prefix(share->keys_in_use, share->keys);
 
1544
    share->keys_in_use&= misam_info.key_map;
1273
1545
    share->keys_for_keyread&= share->keys_in_use;
1274
1546
    share->db_record_offset= misam_info.record_offset;
1275
1547
    if (share->key_parts)
1276
 
      memcpy(getTable()->key_info[0].rec_per_key,
 
1548
      memcpy(table->key_info[0].rec_per_key,
1277
1549
             misam_info.rec_per_key,
1278
 
             sizeof(getTable()->key_info[0].rec_per_key)*share->key_parts);
1279
 
    assert(share->getType() != message::Table::STANDARD);
 
1550
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
 
1551
    if (share->tmp_table == NO_TMP_TABLE)
 
1552
      pthread_mutex_unlock(&share->mutex);
1280
1553
 
1281
1554
   /*
1282
1555
     Set data_file_name and index_file_name to point at the symlink value
1283
1556
     if table is symlinked (Ie;  Real name is not same as generated name)
1284
1557
   */
1285
1558
    data_file_name= index_file_name= 0;
1286
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
 
1559
    fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
1287
1560
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1288
1561
    if (strcmp(name_buff, misam_info.data_file_name))
1289
1562
      data_file_name=misam_info.data_file_name;
1290
 
    internal::fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
 
1563
    fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
1291
1564
              MY_APPEND_EXT | MY_UNPACK_FILENAME);
1292
1565
    if (strcmp(name_buff, misam_info.index_file_name))
1293
1566
      index_file_name=misam_info.index_file_name;
1295
1568
  if (flag & HA_STATUS_ERRKEY)
1296
1569
  {
1297
1570
    errkey  = misam_info.errkey;
1298
 
    internal::my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
 
1571
    my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
1299
1572
  }
1300
1573
  if (flag & HA_STATUS_TIME)
1301
1574
    stats.update_time = misam_info.update_time;
1313
1586
 
1314
1587
int ha_myisam::reset(void)
1315
1588
{
 
1589
  pushed_idx_cond= NULL;
 
1590
  pushed_idx_cond_keyno= MAX_KEY;
 
1591
  mi_set_index_cond_func(file, NULL, 0);
 
1592
  ds_mrr.dsmrr_close();
1316
1593
  return mi_reset(file);
1317
1594
}
1318
1595
 
1328
1605
  return mi_delete_all_rows(file);
1329
1606
}
1330
1607
 
1331
 
int MyisamEngine::doDropTable(Session &session,
1332
 
                              const TableIdentifier &identifier)
 
1608
int MyisamEngine::deleteTableImpl(Session*, const string table_name)
1333
1609
{
1334
 
  session.getMessageCache().removeTableMessage(identifier);
1335
 
 
1336
 
  return mi_delete_table(identifier.getPath().c_str());
 
1610
  return mi_delete_table(table_name.c_str());
1337
1611
}
1338
1612
 
1339
1613
 
1340
1614
int ha_myisam::external_lock(Session *session, int lock_type)
1341
1615
{
1342
1616
  file->in_use= session;
1343
 
  return mi_lock_database(file, !getTable()->getShare()->getType() ?
 
1617
  return mi_lock_database(file, !table->s->tmp_table ?
1344
1618
                          lock_type : ((lock_type == F_UNLCK) ?
1345
1619
                                       F_UNLCK : F_EXTRA_LCK));
1346
1620
}
1347
1621
 
1348
 
int MyisamEngine::doCreateTable(Session &session,
1349
 
                                Table& table_arg,
1350
 
                                const TableIdentifier &identifier,
1351
 
                                message::Table& create_proto)
 
1622
THR_LOCK_DATA **ha_myisam::store_lock(Session *,
 
1623
                                      THR_LOCK_DATA **to,
 
1624
                                      enum thr_lock_type lock_type)
 
1625
{
 
1626
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
1627
    file->lock.type=lock_type;
 
1628
  *to++= &file->lock;
 
1629
 
 
1630
  return to;
 
1631
}
 
1632
 
 
1633
void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
 
1634
{
 
1635
  ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
 
1636
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
1637
  {
 
1638
    create_info->auto_increment_value= stats.auto_increment_value;
 
1639
  }
 
1640
  create_info->data_file_name=data_file_name;
 
1641
  create_info->index_file_name=index_file_name;
 
1642
}
 
1643
 
 
1644
 
 
1645
int MyisamEngine::createTableImpl(Session *, const char *table_name,
 
1646
                                  Table *table_arg,
 
1647
                                  HA_CREATE_INFO *ha_create_info)
1352
1648
{
1353
1649
  int error;
1354
1650
  uint32_t create_flags= 0, create_records;
1356
1652
  MI_KEYDEF *keydef;
1357
1653
  MI_COLUMNDEF *recinfo;
1358
1654
  MI_CREATE_INFO create_info;
1359
 
  TableShare *share= table_arg.getMutableShare();
 
1655
  TableShare *share= table_arg->s;
1360
1656
  uint32_t options= share->db_options_in_use;
1361
 
  if ((error= table2myisam(&table_arg, &keydef, &recinfo, &create_records)))
1362
 
    return(error);
 
1657
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &create_records)))
 
1658
    return(error); /* purecov: inspected */
1363
1659
  memset(&create_info, 0, sizeof(create_info));
1364
 
  create_info.max_rows= create_proto.options().max_rows();
1365
 
  create_info.reloc_rows= create_proto.options().min_rows();
 
1660
  create_info.max_rows= share->max_rows;
 
1661
  create_info.reloc_rows= share->min_rows;
1366
1662
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1367
 
  create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
1368
 
                               create_proto.options().auto_increment_value() -1 :
 
1663
  create_info.auto_increment= (ha_create_info->auto_increment_value ?
 
1664
                               ha_create_info->auto_increment_value -1 :
1369
1665
                               (uint64_t) 0);
1370
 
  create_info.data_file_length= (create_proto.options().max_rows() *
1371
 
                                 create_proto.options().avg_row_length());
1372
 
  create_info.data_file_name= NULL;
1373
 
  create_info.index_file_name=  NULL;
 
1666
  create_info.data_file_length= ((uint64_t) share->max_rows *
 
1667
                                 share->avg_row_length);
 
1668
  create_info.data_file_name= ha_create_info->data_file_name;
 
1669
  create_info.index_file_name= ha_create_info->index_file_name;
1374
1670
  create_info.language= share->table_charset->number;
1375
1671
 
1376
 
  if (create_proto.type() == message::Table::TEMPORARY)
 
1672
  if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
1377
1673
    create_flags|= HA_CREATE_TMP_TABLE;
 
1674
  if (ha_create_info->options & HA_CREATE_KEEP_FILES)
 
1675
    create_flags|= HA_CREATE_KEEP_FILES;
1378
1676
  if (options & HA_OPTION_PACK_RECORD)
1379
1677
    create_flags|= HA_PACK_RECORD;
 
1678
  if (options & HA_OPTION_CHECKSUM)
 
1679
    create_flags|= HA_CREATE_CHECKSUM;
 
1680
  if (options & HA_OPTION_DELAY_KEY_WRITE)
 
1681
    create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1380
1682
 
1381
 
  /* TODO: Check that the following internal::fn_format is really needed */
1382
 
  error= mi_create(internal::fn_format(buff, identifier.getPath().c_str(), "", "",
1383
 
                                       MY_UNPACK_FILENAME|MY_APPEND_EXT),
1384
 
                   share->sizeKeys(), keydef,
 
1683
  /* TODO: Check that the following fn_format is really needed */
 
1684
  error= mi_create(fn_format(buff, table_name, "", "",
 
1685
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
 
1686
                   share->keys, keydef,
1385
1687
                   create_records, recinfo,
1386
1688
                   0, (MI_UNIQUEDEF*) 0,
1387
1689
                   &create_info, create_flags);
1388
1690
  free((unsigned char*) recinfo);
1389
 
 
1390
 
  session.getMessageCache().storeTableMessage(identifier, create_proto);
1391
 
 
1392
 
  return error;
 
1691
  return(error);
1393
1692
}
1394
1693
 
1395
1694
 
1396
 
int MyisamEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
1695
int MyisamEngine::renameTableImpl(Session*, const char *from, const char *to)
1397
1696
{
1398
 
  session.getMessageCache().renameTableMessage(from, to);
1399
 
 
1400
 
  return mi_rename(from.getPath().c_str(), to.getPath().c_str());
 
1697
  return mi_rename(from,to);
1401
1698
}
1402
1699
 
1403
1700
 
1411
1708
  int error;
1412
1709
  unsigned char key[MI_MAX_KEY_LENGTH];
1413
1710
 
1414
 
  if (!getTable()->getShare()->next_number_key_offset)
 
1711
  if (!table->s->next_number_key_offset)
1415
1712
  {                                             // Autoincrement at key-start
1416
1713
    ha_myisam::info(HA_STATUS_AUTO);
1417
1714
    *first_value= stats.auto_increment_value;
1421
1718
  }
1422
1719
 
1423
1720
  /* it's safe to call the following if bulk_insert isn't on */
1424
 
  mi_flush_bulk_insert(file, getTable()->getShare()->next_number_index);
 
1721
  mi_flush_bulk_insert(file, table->s->next_number_index);
1425
1722
 
1426
1723
  (void) extra(HA_EXTRA_KEYREAD);
1427
 
  key_copy(key, getTable()->getInsertRecord(),
1428
 
           &getTable()->key_info[getTable()->getShare()->next_number_index],
1429
 
           getTable()->getShare()->next_number_key_offset);
1430
 
  error= mi_rkey(file, getTable()->getUpdateRecord(), (int) getTable()->getShare()->next_number_index,
1431
 
                 key, make_prev_keypart_map(getTable()->getShare()->next_number_keypart),
 
1724
  key_copy(key, table->record[0],
 
1725
           table->key_info + table->s->next_number_index,
 
1726
           table->s->next_number_key_offset);
 
1727
  error= mi_rkey(file, table->record[1], (int) table->s->next_number_index,
 
1728
                 key, make_prev_keypart_map(table->s->next_number_keypart),
1432
1729
                 HA_READ_PREFIX_LAST);
1433
1730
  if (error)
1434
1731
    nr= 1;
1435
1732
  else
1436
1733
  {
1437
 
    /* Get data from getUpdateRecord() */
1438
 
    nr= ((uint64_t) getTable()->next_number_field->
1439
 
         val_int_offset(getTable()->getShare()->rec_buff_length)+1);
 
1734
    /* Get data from record[1] */
 
1735
    nr= ((uint64_t) table->next_number_field->
 
1736
         val_int_offset(table->s->rec_buff_length)+1);
1440
1737
  }
1441
1738
  extra(HA_EXTRA_NO_KEYREAD);
1442
1739
  *first_value= nr;
1487
1784
  return (uint)file->state->checksum;
1488
1785
}
1489
1786
 
1490
 
static int myisam_init(module::Context &context)
1491
 
1492
 
  context.add(new MyisamEngine(engine_name));
1493
 
  context.registerVariable(new sys_var_constrained_value<size_t>("sort-buffer-size",
1494
 
                                                                 sort_buffer_size));
1495
 
  context.registerVariable(new sys_var_uint64_t_ptr("max_sort_file_size",
1496
 
                                                    &max_sort_file_size,
1497
 
                                                    context.getOptions()["max-sort-file-size"].as<uint64_t>()));
 
1787
static MyisamEngine *engine= NULL;
 
1788
 
 
1789
static int myisam_init(PluginRegistry &registry)
 
1790
{
 
1791
  engine= new MyisamEngine(engine_name);
 
1792
  registry.add(engine);
 
1793
 
 
1794
  pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_FAST);
1498
1795
 
1499
1796
  return 0;
1500
1797
}
1501
1798
 
1502
 
 
1503
 
static void init_options(drizzled::module::option_context &context)
1504
 
{
1505
 
  context("max-sort-file-size",
1506
 
          po::value<uint64_t>(&max_sort_file_size)->default_value(INT32_MAX),
1507
 
          N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."));
1508
 
  context("sort-buffer-size",
1509
 
          po::value<sort_buffer_constraint>(&sort_buffer_size)->default_value(8192*1024),
1510
 
          N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."));
1511
 
}
1512
 
 
1513
 
 
1514
 
DRIZZLE_DECLARE_PLUGIN
1515
 
{
1516
 
  DRIZZLE_VERSION_ID,
 
1799
int myisam_deinit(PluginRegistry &registry)
 
1800
{
 
1801
  registry.remove(engine);
 
1802
  delete engine;
 
1803
 
 
1804
  pthread_mutex_destroy(&THR_LOCK_myisam);
 
1805
 
 
1806
  return mi_panic(HA_PANIC_CLOSE);
 
1807
}
 
1808
 
 
1809
 
 
1810
/****************************************************************************
 
1811
 * MyISAM MRR implementation: use DS-MRR
 
1812
 ***************************************************************************/
 
1813
 
 
1814
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
 
1815
                                     uint32_t n_ranges, uint32_t mode,
 
1816
                                     HANDLER_BUFFER *buf)
 
1817
{
 
1818
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
 
1819
                           seq, seq_init_param, n_ranges, mode, buf);
 
1820
}
 
1821
 
 
1822
int ha_myisam::multi_range_read_next(char **range_info)
 
1823
{
 
1824
  return ds_mrr.dsmrr_next(this, range_info);
 
1825
}
 
1826
 
 
1827
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
1828
                                               void *seq_init_param,
 
1829
                                               uint32_t n_ranges, uint32_t *bufsz,
 
1830
                                               uint32_t *flags, COST_VECT *cost)
 
1831
{
 
1832
  /*
 
1833
    This call is here because there is no location where this->table would
 
1834
    already be known.
 
1835
    TODO: consider moving it into some per-query initialization call.
 
1836
  */
 
1837
  ds_mrr.init(this, table);
 
1838
  return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
 
1839
                                 flags, cost);
 
1840
}
 
1841
 
 
1842
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
 
1843
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
1844
{
 
1845
  ds_mrr.init(this, table);
 
1846
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 
1847
}
 
1848
 
 
1849
/* MyISAM MRR implementation ends */
 
1850
 
 
1851
 
 
1852
/* Index condition pushdown implementation*/
 
1853
 
 
1854
 
 
1855
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
 
1856
{
 
1857
  pushed_idx_cond_keyno= keyno_arg;
 
1858
  pushed_idx_cond= idx_cond_arg;
 
1859
  in_range_check_pushed_down= true;
 
1860
  if (active_index == pushed_idx_cond_keyno)
 
1861
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
 
1862
  return NULL;
 
1863
}
 
1864
 
 
1865
static DRIZZLE_SYSVAR_UINT(block_size, block_size,
 
1866
                           PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
1867
                           N_("Block size to be used for MyISAM index pages."),
 
1868
                           NULL, NULL, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, 
 
1869
                           MI_MAX_KEY_BLOCK_LENGTH, 0);
 
1870
 
 
1871
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
 
1872
                           PLUGIN_VAR_RQCMDARG,
 
1873
                           N_("Number of threads to use when repairing MyISAM tables. The value of "
 
1874
                              "1 disables parallel repair."),
 
1875
                           NULL, NULL, 1, 1, UINT32_MAX, 0);
 
1876
 
 
1877
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
 
1878
                                PLUGIN_VAR_RQCMDARG,
 
1879
                                N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
 
1880
                                NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
 
1881
 
 
1882
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
 
1883
                                PLUGIN_VAR_RQCMDARG,
 
1884
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
 
1885
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
 
1886
 
 
1887
extern uint32_t data_pointer_size;
 
1888
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
 
1889
                           PLUGIN_VAR_RQCMDARG,
 
1890
                           N_("Default pointer size to be used for MyISAM tables."),
 
1891
                           NULL, NULL, 6, 2, 7, 0);
 
1892
 
 
1893
static struct st_mysql_sys_var* system_variables[]= {
 
1894
  DRIZZLE_SYSVAR(block_size),
 
1895
  DRIZZLE_SYSVAR(repair_threads),
 
1896
  DRIZZLE_SYSVAR(max_sort_file_size),
 
1897
  DRIZZLE_SYSVAR(sort_buffer_size),
 
1898
  DRIZZLE_SYSVAR(data_pointer_size),
 
1899
  NULL
 
1900
};
 
1901
 
 
1902
 
 
1903
drizzle_declare_plugin(myisam)
 
1904
{
1517
1905
  "MyISAM",
1518
 
  "2.0",
 
1906
  "1.0",
1519
1907
  "MySQL AB",
1520
1908
  "Default engine as of MySQL 3.23 with great performance",
1521
1909
  PLUGIN_LICENSE_GPL,
1522
1910
  myisam_init, /* Plugin Init */
1523
 
  NULL,           /* system variables */
1524
 
  init_options                        /* config options                  */
 
1911
  myisam_deinit, /* Plugin Deinit */
 
1912
  NULL,                       /* status variables                */
 
1913
  system_variables,           /* system variables */
 
1914
  NULL                        /* config options                  */
1525
1915
}
1526
 
DRIZZLE_DECLARE_PLUGIN_END;
 
1916
drizzle_declare_plugin_end;