~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

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