~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Monty Taylor
  • Date: 2008-12-06 22:41:03 UTC
  • mto: (656.1.7 devel)
  • mto: This revision was merged to the branch mainline in revision 665.
  • Revision ID: monty@inaugust.com-20081206224103-jdouqwt9hb0f01y1
Moved non-working tests into broken suite for easier running of working tests.

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