~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Brian Aker
  • Date: 2008-07-15 06:45:16 UTC
  • Revision ID: brian@tangent.org-20080715064516-fnbq7kowh7w57bxj
Merge Monty's code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
 
17
 
 
18
 
#define DRIZZLE_SERVER 1
19
 
 
20
 
#include <drizzled/server_includes.h>
21
 
#include <mysys/my_bit.h>
 
17
#ifdef USE_PRAGMA_IMPLEMENTATION
 
18
#pragma implementation                          // gcc: Class implementation
 
19
#endif
 
20
 
 
21
#define MYSQL_SERVER 1
 
22
#include "mysql_priv.h"
 
23
#include <mysql/plugin.h>
 
24
#include <m_ctype.h>
 
25
#include <my_bit.h>
22
26
#include <myisampack.h>
23
27
#include "ha_myisam.h"
 
28
#include <stdarg.h>
24
29
#include "myisamdef.h"
25
 
#include <drizzled/drizzled_error_messages.h>
26
 
#include <drizzled/util/test.h>
27
30
 
28
31
ulong myisam_recover_options= HA_RECOVER_NONE;
29
32
 
30
33
/* bits in myisam_recover_options */
31
34
const char *myisam_recover_names[] =
32
 
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
 
35
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
33
36
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
34
37
                                 myisam_recover_names, NULL};
35
38
 
36
39
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
37
 
                                           "nulls_ignored", NULL};
 
40
                                           "nulls_ignored", NullS};
38
41
TYPELIB myisam_stats_method_typelib= {
39
42
  array_elements(myisam_stats_method_names) - 1, "",
40
43
  myisam_stats_method_names, NULL};
58
61
{
59
62
  THD* thd = (THD*)param->thd;
60
63
  Protocol *protocol= thd->protocol;
61
 
  uint32_t length, msg_length;
 
64
  uint length, msg_length;
62
65
  char msgbuf[MI_MAX_MSG_BUF];
63
66
  char name[NAME_LEN*2+2];
64
67
 
65
68
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
66
69
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
67
70
 
 
71
  DBUG_PRINT(msg_type,("message: %s",msgbuf));
 
72
 
68
73
  if (!thd->vio_ok())
69
74
  {
70
75
    sql_print_error(msgbuf);
77
82
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
78
83
    return;
79
84
  }
80
 
  length=(uint) (strxmov(name, param->db_name,".",param->table_name,NULL) -
 
85
  length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
81
86
                 name);
82
87
  /*
83
88
    TODO: switch from protocol to push_warning here. The main reason we didn't
100
105
 
101
106
 
102
107
/*
103
 
  Convert Table object to MyISAM key and column definition
 
108
  Convert TABLE object to MyISAM key and column definition
104
109
 
105
110
  SYNOPSIS
106
111
    table2myisam()
107
 
      table_arg   in     Table object.
 
112
      table_arg   in     TABLE object.
108
113
      keydef_out  out    MyISAM key definition.
109
114
      recinfo_out out    MyISAM column definition.
110
115
      records_out out    Number of fields.
123
128
    !0 error code
124
129
*/
125
130
 
126
 
int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
127
 
                 MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
 
131
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
 
132
                 MI_COLUMNDEF **recinfo_out, uint *records_out)
128
133
{
129
 
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
 
134
  uint i, j, recpos, minpos, fieldpos, temp_length, length;
130
135
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
131
 
  unsigned char *record;
 
136
  uchar *record;
132
137
  KEY *pos;
133
138
  MI_KEYDEF *keydef;
134
139
  MI_COLUMNDEF *recinfo, *recinfo_pos;
135
140
  HA_KEYSEG *keyseg;
136
141
  TABLE_SHARE *share= table_arg->s;
137
 
  uint32_t options= share->db_options_in_use;
 
142
  uint options= share->db_options_in_use;
 
143
  DBUG_ENTER("table2myisam");
138
144
  if (!(my_multi_malloc(MYF(MY_WME),
139
145
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
140
146
          keydef_out, share->keys * sizeof(MI_KEYDEF),
141
147
          &keyseg,
142
148
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
143
 
          NULL)))
144
 
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
 
149
          NullS)))
 
150
    DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
145
151
  keydef= *keydef_out;
146
152
  recinfo= *recinfo_out;
147
153
  pos= table_arg->key_info;
148
154
  for (i= 0; i < share->keys; i++, pos++)
149
155
  {
150
 
    keydef[i].flag= ((uint16_t) pos->flags & (HA_NOSAME));
151
 
    keydef[i].key_alg= HA_KEY_ALG_BTREE;
 
156
    keydef[i].flag= ((uint16) pos->flags & (HA_NOSAME | HA_FULLTEXT ));
 
157
    keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?  (HA_KEY_ALG_BTREE) : pos->algorithm;
152
158
    keydef[i].block_length= pos->block_size;
153
159
    keydef[i].seg= keyseg;
154
160
    keydef[i].keysegs= pos->key_parts;
170
176
          /* No blobs here */
171
177
          if (j == 0)
172
178
            keydef[i].flag|= HA_PACK_KEY;
173
 
          if ((((int) (pos->key_part[j].length - field->decimals())) >= 4))
 
179
          if (!(field->flags & ZEROFILL_FLAG) &&
 
180
              (field->type() == MYSQL_TYPE_STRING ||
 
181
               field->type() == MYSQL_TYPE_VAR_STRING ||
 
182
               ((int) (pos->key_part[j].length - field->decimals())) >= 4))
174
183
            keydef[i].seg[j].flag|= HA_SPACE_PACK;
175
184
        }
176
185
        else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
188
197
      {
189
198
        keydef[i].seg[j].null_bit= field->null_bit;
190
199
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
191
 
                                           (unsigned char*) table_arg->record[0]);
 
200
                                           (uchar*) table_arg->record[0]);
192
201
      }
193
202
      else
194
203
      {
195
204
        keydef[i].seg[j].null_bit= 0;
196
205
        keydef[i].seg[j].null_pos= 0;
197
206
      }
198
 
      if (field->type() == DRIZZLE_TYPE_BLOB)
 
207
      if (field->type() == MYSQL_TYPE_BLOB)
199
208
      {
200
209
        keydef[i].seg[j].flag|= HA_BLOB_PART;
201
210
        /* save number of bytes used to pack length */
210
219
  record= table_arg->record[0];
211
220
  recpos= 0;
212
221
  recinfo_pos= recinfo;
213
 
  while (recpos < (uint) share->stored_rec_length)
 
222
  while (recpos < (uint) share->reclength)
214
223
  {
215
224
    Field **field, *found= 0;
216
225
    minpos= share->reclength;
233
242
        }
234
243
      }
235
244
    }
 
245
    DBUG_PRINT("loop", ("found: 0x%lx  recpos: %d  minpos: %d  length: %d",
 
246
                        (long) found, recpos, minpos, length));
236
247
    if (recpos != minpos)
237
248
    { // Reserved space (Null bits?)
238
 
      memset(recinfo_pos, 0, sizeof(*recinfo_pos));
 
249
      bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
239
250
      recinfo_pos->type= (int) FIELD_NORMAL;
240
 
      recinfo_pos++->length= (uint16_t) (minpos - recpos);
 
251
      recinfo_pos++->length= (uint16) (minpos - recpos);
241
252
    }
242
253
    if (!found)
243
254
      break;
244
255
 
245
256
    if (found->flags & BLOB_FLAG)
246
257
      recinfo_pos->type= (int) FIELD_BLOB;
247
 
    else if (found->type() == DRIZZLE_TYPE_VARCHAR)
 
258
    else if (found->type() == MYSQL_TYPE_VARCHAR)
248
259
      recinfo_pos->type= FIELD_VARCHAR;
249
260
    else if (!(options & HA_OPTION_PACK_RECORD))
250
261
      recinfo_pos->type= (int) FIELD_NORMAL;
251
262
    else if (found->zero_pack())
252
263
      recinfo_pos->type= (int) FIELD_SKIP_ZERO;
253
264
    else
254
 
      recinfo_pos->type= (int) ((length <= 3) ?  FIELD_NORMAL : FIELD_SKIP_PRESPACE);
 
265
      recinfo_pos->type= (int) ((length <= 3 ||
 
266
                                 (found->flags & ZEROFILL_FLAG)) ?
 
267
                                  FIELD_NORMAL :
 
268
                                  found->type() == MYSQL_TYPE_STRING ||
 
269
                                  found->type() == MYSQL_TYPE_VAR_STRING ?
 
270
                                  FIELD_SKIP_ENDSPACE :
 
271
                                  FIELD_SKIP_PRESPACE);
255
272
    if (found->null_ptr)
256
273
    {
257
274
      recinfo_pos->null_bit= found->null_bit;
258
275
      recinfo_pos->null_pos= (uint) (found->null_ptr -
259
 
                                     (unsigned char*) table_arg->record[0]);
 
276
                                     (uchar*) table_arg->record[0]);
260
277
    }
261
278
    else
262
279
    {
263
280
      recinfo_pos->null_bit= 0;
264
281
      recinfo_pos->null_pos= 0;
265
282
    }
266
 
    (recinfo_pos++)->length= (uint16_t) length;
 
283
    (recinfo_pos++)->length= (uint16) length;
267
284
    recpos= minpos + length;
 
285
    DBUG_PRINT("loop", ("length: %d  type: %d",
 
286
                        recinfo_pos[-1].length,recinfo_pos[-1].type));
268
287
  }
269
288
  *records_out= (uint) (recinfo_pos - recinfo);
270
 
  return(0);
 
289
  DBUG_RETURN(0);
271
290
}
272
291
 
273
292
 
312
331
*/
313
332
 
314
333
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
315
 
                     uint32_t t1_keys, uint32_t t1_recs,
 
334
                     uint t1_keys, uint t1_recs,
316
335
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
317
 
                     uint32_t t2_keys, uint32_t t2_recs, bool strict)
 
336
                     uint t2_keys, uint t2_recs, bool strict)
318
337
{
319
 
  uint32_t i, j;
 
338
  uint i, j;
 
339
  DBUG_ENTER("check_definition");
320
340
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
321
341
  {
322
 
    return(1);
 
342
    DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
 
343
                         t1_keys, t2_keys));
 
344
    DBUG_RETURN(1);
323
345
  }
324
346
  if (t1_recs != t2_recs)
325
347
  {
326
 
    return(1);
 
348
    DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
 
349
                         t1_recs, t2_recs));
 
350
    DBUG_RETURN(1);
327
351
  }
328
352
  for (i= 0; i < t1_keys; i++)
329
353
  {
330
354
    HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
331
355
    HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
 
356
    if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
 
357
      continue;
 
358
    else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
 
359
             t2_keyinfo[i].flag & HA_FULLTEXT)
 
360
    {
 
361
       DBUG_PRINT("error", ("Key %d has different definition", i));
 
362
       DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
 
363
                            test(t1_keyinfo[i].flag & HA_FULLTEXT),
 
364
                            test(t2_keyinfo[i].flag & HA_FULLTEXT)));
 
365
       DBUG_RETURN(1);
 
366
    }
 
367
    if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
 
368
      continue;
 
369
    else if (t1_keyinfo[i].flag & HA_SPATIAL ||
 
370
             t2_keyinfo[i].flag & HA_SPATIAL)
 
371
    {
 
372
       DBUG_PRINT("error", ("Key %d has different definition", i));
 
373
       DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
 
374
                            test(t1_keyinfo[i].flag & HA_SPATIAL),
 
375
                            test(t2_keyinfo[i].flag & HA_SPATIAL)));
 
376
       DBUG_RETURN(1);
 
377
    }
332
378
    if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
333
379
        t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
334
380
    {
335
 
      return(1);
 
381
      DBUG_PRINT("error", ("Key %d has different definition", i));
 
382
      DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
 
383
                           t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
 
384
      DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
 
385
                           t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
 
386
      DBUG_RETURN(1);
336
387
    }
337
388
    for (j=  t1_keyinfo[i].keysegs; j--;)
338
389
    {
339
 
      uint8_t t1_keysegs_j__type= t1_keysegs[j].type;
 
390
      uint8 t1_keysegs_j__type= t1_keysegs[j].type;
340
391
 
341
392
      /*
342
393
        Table migration from 4.1 to 5.1. In 5.1 a *TEXT key part is
360
411
          t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
361
412
          t1_keysegs[j].length != t2_keysegs[j].length)
362
413
      {
363
 
        return(1);
 
414
        DBUG_PRINT("error", ("Key segment %d (key %d) has different "
 
415
                             "definition", j, i));
 
416
        DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
 
417
                             "t1_length=%d",
 
418
                             t1_keysegs[j].type, t1_keysegs[j].language,
 
419
                             t1_keysegs[j].null_bit, t1_keysegs[j].length));
 
420
        DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
 
421
                             "t2_length=%d",
 
422
                             t2_keysegs[j].type, t2_keysegs[j].language,
 
423
                             t2_keysegs[j].null_bit, t2_keysegs[j].length));
 
424
 
 
425
        DBUG_RETURN(1);
364
426
      }
365
427
    }
366
428
  }
379
441
        t1_rec->length != t2_rec->length ||
380
442
        t1_rec->null_bit != t2_rec->null_bit)
381
443
    {
382
 
      return(1);
 
444
      DBUG_PRINT("error", ("Field %d has different definition", i));
 
445
      DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
 
446
                           t1_rec->type, t1_rec->length, t1_rec->null_bit));
 
447
      DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
 
448
                           t2_rec->type, t2_rec->length, t2_rec->null_bit));
 
449
      DBUG_RETURN(1);
383
450
    }
384
451
  }
385
 
  return(0);
 
452
  DBUG_RETURN(0);
386
453
}
387
454
 
388
455
 
438
505
*/
439
506
 
440
507
void _mi_report_crashed(MI_INFO *file, const char *message,
441
 
                        const char *sfile, uint32_t sline)
 
508
                        const char *sfile, uint sline)
442
509
{
443
510
  THD *cur_thd;
444
511
  LIST *element;
 
512
  char buf[1024];
445
513
  pthread_mutex_lock(&file->s->intern_lock);
446
514
  if ((cur_thd= (THD*) file->in_use.data))
447
515
    sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
452
520
    sql_print_error("%s", message);
453
521
  for (element= file->s->in_use; element; element= list_rest(element))
454
522
  {
455
 
    sql_print_error("%s", "Unknown thread accessing table");
 
523
    THD *thd= (THD*) element->data;
 
524
    sql_print_error("%s", thd ? thd_security_context(thd, buf, sizeof(buf), 0)
 
525
                              : "Unknown thread accessing table");
456
526
  }
457
527
  pthread_mutex_unlock(&file->s->intern_lock);
458
528
}
461
531
 
462
532
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
463
533
  :handler(hton, table_arg), file(0),
464
 
  int_table_flags(HA_NULL_IN_KEY |
465
 
                  HA_BINLOG_ROW_CAPABLE |
466
 
                  HA_BINLOG_STMT_CAPABLE |
467
 
                  HA_DUPLICATE_POS |
468
 
                  HA_CAN_INDEX_BLOBS |
469
 
                  HA_AUTO_PART_KEY |
470
 
                  HA_FILE_BASED |
471
 
                  HA_NO_TRANSACTIONS |
472
 
                  HA_HAS_RECORDS |
473
 
                  HA_STATS_RECORDS_IS_EXACT |
474
 
                  HA_NEED_READ_RANGE_BUFFER |
475
 
                  HA_MRR_CANT_SORT),
 
534
  int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
 
535
                  HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
 
536
                  HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
 
537
                  HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
 
538
                  HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
 
539
                  HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT |
 
540
                  HA_NEED_READ_RANGE_BUFFER | HA_MRR_CANT_SORT),
476
541
   can_enable_indexes(1)
477
542
{}
478
543
 
488
553
static const char *ha_myisam_exts[] = {
489
554
  ".MYI",
490
555
  ".MYD",
491
 
  NULL
 
556
  NullS
492
557
};
493
558
 
494
559
const char **ha_myisam::bas_ext() const
497
562
}
498
563
 
499
564
 
500
 
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
 
565
const char *ha_myisam::index_type(uint key_number __attribute__((__unused__)))
501
566
{
502
567
  return "BTREE";
503
568
}
504
569
 
505
570
/* Name is here without an extension */
506
 
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
 
571
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
507
572
{
508
573
  MI_KEYDEF *keyinfo;
509
574
  MI_COLUMNDEF *recinfo= 0;
510
 
  uint32_t recs;
511
 
  uint32_t i;
 
575
  uint recs;
 
576
  uint i;
512
577
 
513
578
  /*
514
579
    If the user wants to have memory mapped data files, add an
532
597
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
533
598
    {
534
599
      /* purecov: begin inspected */
 
600
      DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM "
 
601
                           "key and column definition"));
535
602
      goto err;
536
603
      /* purecov: end */
537
604
    }
547
614
  }
548
615
  
549
616
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
550
 
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
 
617
    VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
551
618
 
552
619
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
553
620
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
554
 
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
 
621
    VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
555
622
  if (!table->s->db_record_offset)
556
623
    int_table_flags|=HA_REC_NOT_IN_SEQ;
557
624
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
583
650
    recinfo must be freed.
584
651
  */
585
652
  if (recinfo)
586
 
    free((unsigned char*) recinfo);
 
653
    my_free((uchar*) recinfo, MYF(0));
587
654
  return my_errno;
588
655
}
589
656
 
594
661
  return mi_close(tmp);
595
662
}
596
663
 
597
 
int ha_myisam::write_row(unsigned char *buf)
 
664
int ha_myisam::write_row(uchar *buf)
598
665
{
599
666
  ha_statistic_increment(&SSV::ha_write_count);
600
667
 
621
688
  int error;
622
689
  MI_CHECK param;
623
690
  MYISAM_SHARE* share = file->s;
624
 
  const char *old_proc_info= thd->get_proc_info();
 
691
  const char *old_proc_info=thd->proc_info;
625
692
 
626
 
  thd->set_proc_info("Checking table");
 
693
  thd_proc_info(thd, "Checking table");
627
694
  myisamchk_init(&param);
628
695
  param.thd = thd;
629
696
  param.op_name =   "check";
659
726
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
660
727
        mi_is_crashed(file))
661
728
    {
662
 
      uint32_t old_testflag=param.testflag;
 
729
      uint old_testflag=param.testflag;
663
730
      param.testflag|=T_MEDIUM;
664
731
      if (!(error= init_io_cache(&param.read_cache, file->dfile,
665
732
                                 my_default_record_cache_size, READ_CACHE,
697
764
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
698
765
  }
699
766
 
700
 
  thd->set_proc_info(old_proc_info);
 
767
  thd_proc_info(thd, old_proc_info);
701
768
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
702
769
}
703
770
 
709
776
*/
710
777
 
711
778
int ha_myisam::analyze(THD *thd,
712
 
                       HA_CHECK_OPT* check_opt __attribute__((unused)))
 
779
                       HA_CHECK_OPT* check_opt __attribute__((__unused__)))
713
780
{
714
781
  int error=0;
715
782
  MI_CHECK param;
816
883
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
817
884
{
818
885
  int error=0;
819
 
  uint32_t local_testflag=param.testflag;
 
886
  uint local_testflag=param.testflag;
820
887
  bool optimize_done= !do_optimize, statistics_done=0;
821
 
  const char *old_proc_info= thd->get_proc_info();
 
888
  const char *old_proc_info=thd->proc_info;
822
889
  char fixed_name[FN_REFLEN];
823
890
  MYISAM_SHARE* share = file->s;
824
891
  ha_rows rows= file->state->records;
 
892
  DBUG_ENTER("ha_myisam::repair");
825
893
 
826
894
  /*
827
895
    Normally this method is entered with a properly opened table. If the
836
904
    sql_print_information("Retrying repair of: '%s' failed. "
837
905
                          "Please try REPAIR EXTENDED or myisamchk",
838
906
                          table->s->path.str);
839
 
    return(HA_ADMIN_FAILED);
 
907
    DBUG_RETURN(HA_ADMIN_FAILED);
840
908
  }
841
909
 
842
910
  param.db_name=    table->s->db.str;
846
914
  param.thd= thd;
847
915
  param.tmpdir= &mysql_tmpdir_list;
848
916
  param.out_flag= 0;
849
 
  my_stpcpy(fixed_name,file->filename);
 
917
  strmov(fixed_name,file->filename);
850
918
 
851
 
  // Don't lock tables if we have used LOCK Table
 
919
  // Don't lock tables if we have used LOCK TABLE
852
920
  if (!thd->locked_tables && 
853
921
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
854
922
  {
855
923
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
856
 
    return(HA_ADMIN_FAILED);
 
924
    DBUG_RETURN(HA_ADMIN_FAILED);
857
925
  }
858
926
 
859
927
  if (!do_optimize ||
864
932
    uint64_t key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
865
933
                        mi_get_mask_all_keys_active(share->base.keys) :
866
934
                        share->state.key_map);
867
 
    uint32_t testflag=param.testflag;
 
935
    uint testflag=param.testflag;
868
936
    if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
869
937
        (local_testflag & T_REP_BY_SORT))
870
938
    {
876
944
        char buf[40];
877
945
        /* TODO: respect myisam_repair_threads variable */
878
946
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
879
 
        thd->set_proc_info(buf);
 
947
        thd_proc_info(thd, buf);
880
948
        error = mi_repair_parallel(&param, file, fixed_name,
881
949
            param.testflag & T_QUICK);
882
 
        thd->set_proc_info("Repair done"); // to reset proc_info, as
 
950
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
883
951
                                      // it was pointing to local buffer
884
952
      }
885
953
      else
886
954
      {
887
 
        thd->set_proc_info("Repair by sorting");
 
955
        thd_proc_info(thd, "Repair by sorting");
888
956
        error = mi_repair_by_sort(&param, file, fixed_name,
889
957
            param.testflag & T_QUICK);
890
958
      }
891
959
    }
892
960
    else
893
961
    {
894
 
      thd->set_proc_info("Repair with keycache");
 
962
      thd_proc_info(thd, "Repair with keycache");
895
963
      param.testflag &= ~T_REP_BY_SORT;
896
964
      error=  mi_repair(&param, file, fixed_name,
897
965
                        param.testflag & T_QUICK);
905
973
        (share->state.changed & STATE_NOT_SORTED_PAGES))
906
974
    {
907
975
      optimize_done=1;
908
 
      thd->set_proc_info("Sorting index");
 
976
      thd_proc_info(thd, "Sorting index");
909
977
      error=mi_sort_index(&param,file,fixed_name);
910
978
    }
911
979
    if (!statistics_done && (local_testflag & T_STATISTICS))
913
981
      if (share->state.changed & STATE_NOT_ANALYZED)
914
982
      {
915
983
        optimize_done=1;
916
 
        thd->set_proc_info("Analyzing");
 
984
        thd_proc_info(thd, "Analyzing");
917
985
        error = chk_key(&param, file);
918
986
      }
919
987
      else
920
988
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
921
989
    }
922
990
  }
923
 
  thd->set_proc_info("Saving state");
 
991
  thd_proc_info(thd, "Saving state");
924
992
  if (!error)
925
993
  {
926
994
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
958
1026
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
959
1027
    update_state_info(&param, file, 0);
960
1028
  }
961
 
  thd->set_proc_info(old_proc_info);
 
1029
  thd_proc_info(thd, old_proc_info);
962
1030
  if (!thd->locked_tables)
963
1031
    mi_lock_database(file,F_UNLCK);
964
 
  return(error ? HA_ADMIN_FAILED :
 
1032
  DBUG_RETURN(error ? HA_ADMIN_FAILED :
965
1033
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
966
1034
}
967
1035
 
976
1044
  const char *errmsg= 0;
977
1045
  int error= HA_ADMIN_OK;
978
1046
  uint64_t map;
979
 
  TableList *table_list= table->pos_in_table_list;
 
1047
  TABLE_LIST *table_list= table->pos_in_table_list;
 
1048
  DBUG_ENTER("ha_myisam::assign_to_keycache");
980
1049
 
981
1050
  table->keys_in_use_for_query.clear_all();
982
1051
 
983
1052
  if (table_list->process_index_hints(table))
984
 
    return(HA_ADMIN_FAILED);
 
1053
    DBUG_RETURN(HA_ADMIN_FAILED);
985
1054
  map= ~(uint64_t) 0;
986
1055
  if (!table->keys_in_use_for_query.is_clear_all())
987
1056
    /* use all keys if there's no list specified by the user through hints */
1008
1077
    param.testflag= 0;
1009
1078
    mi_check_print_error(&param, errmsg);
1010
1079
  }
1011
 
  return(error);
 
1080
  DBUG_RETURN(error);
1012
1081
}
1013
1082
 
1014
1083
 
1032
1101
    HA_ERR_WRONG_COMMAND  mode not implemented.
1033
1102
*/
1034
1103
 
1035
 
int ha_myisam::disable_indexes(uint32_t mode)
 
1104
int ha_myisam::disable_indexes(uint mode)
1036
1105
{
1037
1106
  int error;
1038
1107
 
1084
1153
    HA_ERR_WRONG_COMMAND  mode not implemented.
1085
1154
*/
1086
1155
 
1087
 
int ha_myisam::enable_indexes(uint32_t mode)
 
1156
int ha_myisam::enable_indexes(uint mode)
1088
1157
{
1089
1158
  int error;
1090
1159
 
1107
1176
  {
1108
1177
    THD *thd=current_thd;
1109
1178
    MI_CHECK param;
1110
 
    const char *save_proc_info= thd->get_proc_info();
1111
 
    thd->set_proc_info("Creating index");
 
1179
    const char *save_proc_info=thd->proc_info;
 
1180
    thd_proc_info(thd, "Creating index");
1112
1181
    myisamchk_init(&param);
1113
1182
    param.op_name= "recreating_index";
1114
1183
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
1133
1202
        thd->clear_error();
1134
1203
    }
1135
1204
    info(HA_STATUS_CONST);
1136
 
    thd->set_proc_info(save_proc_info);
 
1205
    thd_proc_info(thd, save_proc_info);
1137
1206
  }
1138
1207
  else
1139
1208
  {
1182
1251
 
1183
1252
void ha_myisam::start_bulk_insert(ha_rows rows)
1184
1253
{
 
1254
  DBUG_ENTER("ha_myisam::start_bulk_insert");
1185
1255
  THD *thd= current_thd;
1186
 
  ulong size= cmin(thd->variables.read_buff_size,
 
1256
  ulong size= min(thd->variables.read_buff_size,
1187
1257
                  (ulong) (table->s->avg_row_length*rows));
 
1258
  DBUG_PRINT("info",("start_bulk_insert: rows %lu size %lu",
 
1259
                     (ulong) rows, size));
1188
1260
 
1189
1261
  /* don't enable row cache if too few rows */
1190
1262
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
1193
1265
  can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
1194
1266
                                            file->s->base.keys);
1195
1267
 
1196
 
  /*
1197
 
    Only disable old index if the table was empty and we are inserting
1198
 
    a lot of rows.
1199
 
    We should not do this for only a few rows as this is slower and
1200
 
    we don't want to update the key statistics based of only a few rows.
1201
 
  */
1202
 
  if (file->state->records == 0 && can_enable_indexes &&
1203
 
      (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
1204
 
    mi_disable_non_unique_index(file,rows);
1205
 
  else
 
1268
  if (!(specialflag & SPECIAL_SAFE_MODE))
 
1269
  {
 
1270
    /*
 
1271
      Only disable old index if the table was empty and we are inserting
 
1272
      a lot of rows.
 
1273
      We should not do this for only a few rows as this is slower and
 
1274
      we don't want to update the key statistics based of only a few rows.
 
1275
    */
 
1276
    if (file->state->records == 0 && can_enable_indexes &&
 
1277
        (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
 
1278
      mi_disable_non_unique_index(file,rows);
 
1279
    else
1206
1280
    if (!file->bulk_insert &&
1207
1281
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1208
1282
    {
1209
1283
      mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
1210
1284
    }
1211
 
 
1212
 
  return;
 
1285
  }
 
1286
  DBUG_VOID_RETURN;
1213
1287
}
1214
1288
 
1215
1289
/*
1239
1313
  int error=0;
1240
1314
  int marked_crashed;
1241
1315
  char *old_query;
1242
 
  uint32_t old_query_length;
 
1316
  uint old_query_length;
1243
1317
  HA_CHECK_OPT check_opt;
 
1318
  DBUG_ENTER("ha_myisam::check_and_repair");
1244
1319
 
1245
1320
  check_opt.init();
1246
1321
  check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
1271
1346
  thd->query= old_query;
1272
1347
  thd->query_length= old_query_length;
1273
1348
  pthread_mutex_unlock(&LOCK_thread_count);
1274
 
  return(error);
 
1349
  DBUG_RETURN(error);
1275
1350
}
1276
1351
 
1277
1352
bool ha_myisam::is_crashed() const
1280
1355
          (file->s->state.open_count));
1281
1356
}
1282
1357
 
1283
 
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
 
1358
int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
1284
1359
{
1285
1360
  ha_statistic_increment(&SSV::ha_update_count);
1286
1361
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1288
1363
  return mi_update(file,old_data,new_data);
1289
1364
}
1290
1365
 
1291
 
int ha_myisam::delete_row(const unsigned char *buf)
 
1366
int ha_myisam::delete_row(const uchar *buf)
1292
1367
{
1293
1368
  ha_statistic_increment(&SSV::ha_delete_count);
1294
1369
  return mi_delete(file,buf);
1295
1370
}
1296
1371
 
1297
 
#ifdef __cplusplus
1298
 
extern "C" {
1299
 
#endif
 
1372
C_MODE_START
1300
1373
 
1301
 
bool index_cond_func_myisam(void *arg)
 
1374
my_bool index_cond_func_myisam(void *arg)
1302
1375
{
1303
1376
  ha_myisam *h= (ha_myisam*)arg;
1304
1377
  /*if (h->in_range_read)*/
1307
1380
    if (h->compare_key2(h->end_range) > 0)
1308
1381
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
1309
1382
  }
1310
 
  return (bool)h->pushed_idx_cond->val_int();
1311
 
}
1312
 
 
1313
 
#ifdef __cplusplus
1314
 
}
1315
 
#endif
1316
 
 
1317
 
 
1318
 
int ha_myisam::index_init(uint32_t idx, bool sorted __attribute__((unused)))
 
1383
  return (my_bool)h->pushed_idx_cond->val_int();
 
1384
}
 
1385
 
 
1386
C_MODE_END
 
1387
 
 
1388
 
 
1389
int ha_myisam::index_init(uint idx, bool sorted __attribute__((__unused__)))
1319
1390
1320
1391
  active_index=idx;
1321
1392
  //in_range_read= false;
1336
1407
}
1337
1408
 
1338
1409
 
1339
 
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
 
1410
int ha_myisam::index_read_map(uchar *buf, const uchar *key,
1340
1411
                              key_part_map keypart_map,
1341
1412
                              enum ha_rkey_function find_flag)
1342
1413
{
1343
 
  assert(inited==INDEX);
 
1414
  DBUG_ASSERT(inited==INDEX);
1344
1415
  ha_statistic_increment(&SSV::ha_read_key_count);
1345
1416
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1346
1417
  table->status=error ? STATUS_NOT_FOUND: 0;
1347
1418
  return error;
1348
1419
}
1349
1420
 
1350
 
int ha_myisam::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
 
1421
int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
1351
1422
                                  key_part_map keypart_map,
1352
1423
                                  enum ha_rkey_function find_flag)
1353
1424
{
1357
1428
  return error;
1358
1429
}
1359
1430
 
1360
 
int ha_myisam::index_read_last_map(unsigned char *buf, const unsigned char *key,
 
1431
int ha_myisam::index_read_last_map(uchar *buf, const uchar *key,
1361
1432
                                   key_part_map keypart_map)
1362
1433
{
1363
 
  assert(inited==INDEX);
 
1434
  DBUG_ENTER("ha_myisam::index_read_last");
 
1435
  DBUG_ASSERT(inited==INDEX);
1364
1436
  ha_statistic_increment(&SSV::ha_read_key_count);
1365
1437
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1366
1438
                    HA_READ_PREFIX_LAST);
1367
1439
  table->status=error ? STATUS_NOT_FOUND: 0;
1368
 
  return(error);
 
1440
  DBUG_RETURN(error);
1369
1441
}
1370
1442
 
1371
 
int ha_myisam::index_next(unsigned char *buf)
 
1443
int ha_myisam::index_next(uchar *buf)
1372
1444
{
1373
 
  assert(inited==INDEX);
 
1445
  DBUG_ASSERT(inited==INDEX);
1374
1446
  ha_statistic_increment(&SSV::ha_read_next_count);
1375
1447
  int error=mi_rnext(file,buf,active_index);
1376
1448
  table->status=error ? STATUS_NOT_FOUND: 0;
1377
1449
  return error;
1378
1450
}
1379
1451
 
1380
 
int ha_myisam::index_prev(unsigned char *buf)
 
1452
int ha_myisam::index_prev(uchar *buf)
1381
1453
{
1382
 
  assert(inited==INDEX);
 
1454
  DBUG_ASSERT(inited==INDEX);
1383
1455
  ha_statistic_increment(&SSV::ha_read_prev_count);
1384
1456
  int error=mi_rprev(file,buf, active_index);
1385
1457
  table->status=error ? STATUS_NOT_FOUND: 0;
1386
1458
  return error;
1387
1459
}
1388
1460
 
1389
 
int ha_myisam::index_first(unsigned char *buf)
 
1461
int ha_myisam::index_first(uchar *buf)
1390
1462
{
1391
 
  assert(inited==INDEX);
 
1463
  DBUG_ASSERT(inited==INDEX);
1392
1464
  ha_statistic_increment(&SSV::ha_read_first_count);
1393
1465
  int error=mi_rfirst(file, buf, active_index);
1394
1466
  table->status=error ? STATUS_NOT_FOUND: 0;
1395
1467
  return error;
1396
1468
}
1397
1469
 
1398
 
int ha_myisam::index_last(unsigned char *buf)
 
1470
int ha_myisam::index_last(uchar *buf)
1399
1471
{
1400
 
  assert(inited==INDEX);
 
1472
  DBUG_ASSERT(inited==INDEX);
1401
1473
  ha_statistic_increment(&SSV::ha_read_last_count);
1402
1474
  int error=mi_rlast(file, buf, active_index);
1403
1475
  table->status=error ? STATUS_NOT_FOUND: 0;
1404
1476
  return error;
1405
1477
}
1406
1478
 
1407
 
int ha_myisam::index_next_same(unsigned char *buf,
1408
 
                               const unsigned char *key __attribute__((unused)),
1409
 
                               uint32_t length __attribute__((unused)))
 
1479
int ha_myisam::index_next_same(uchar *buf,
 
1480
                               const uchar *key __attribute__((unused)),
 
1481
                               uint length __attribute__((unused)))
1410
1482
{
1411
1483
  int error;
1412
 
  assert(inited==INDEX);
 
1484
  DBUG_ASSERT(inited==INDEX);
1413
1485
  ha_statistic_increment(&SSV::ha_read_next_count);
1414
1486
  do
1415
1487
  {
1452
1524
  return mi_reset(file);                        // Free buffers
1453
1525
}
1454
1526
 
1455
 
int ha_myisam::rnd_next(unsigned char *buf)
 
1527
int ha_myisam::rnd_next(uchar *buf)
1456
1528
{
1457
1529
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1458
1530
  int error=mi_scan(file, buf);
1460
1532
  return error;
1461
1533
}
1462
1534
 
1463
 
int ha_myisam::restart_rnd_next(unsigned char *buf, unsigned char *pos)
 
1535
int ha_myisam::restart_rnd_next(uchar *buf, uchar *pos)
1464
1536
{
1465
1537
  return rnd_pos(buf,pos);
1466
1538
}
1467
1539
 
1468
 
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
 
1540
int ha_myisam::rnd_pos(uchar *buf, uchar *pos)
1469
1541
{
1470
1542
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1471
1543
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
1474
1546
}
1475
1547
 
1476
1548
 
1477
 
void ha_myisam::position(const unsigned char *record __attribute__((unused)))
 
1549
void ha_myisam::position(const uchar *record __attribute__((__unused__)))
1478
1550
{
1479
1551
  my_off_t row_position= mi_position(file);
1480
1552
  my_store_ptr(ref, ref_length, row_position);
1481
1553
}
1482
1554
 
1483
 
int ha_myisam::info(uint32_t flag)
 
1555
int ha_myisam::info(uint flag)
1484
1556
{
1485
1557
  MI_ISAMINFO misam_info;
1486
1558
  char name_buff[FN_REFLEN];
1514
1586
    share->keys_for_keyread.intersect(share->keys_in_use);
1515
1587
    share->db_record_offset= misam_info.record_offset;
1516
1588
    if (share->key_parts)
1517
 
      memcpy(table->key_info[0].rec_per_key,
1518
 
             misam_info.rec_per_key,
 
1589
      memcpy((char*) table->key_info[0].rec_per_key,
 
1590
             (char*) misam_info.rec_per_key,
1519
1591
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1520
1592
    if (share->tmp_table == NO_TMP_TABLE)
1521
1593
      pthread_mutex_unlock(&share->mutex);
1550
1622
 
1551
1623
int ha_myisam::extra(enum ha_extra_function operation)
1552
1624
{
 
1625
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD)
 
1626
    return 0;
1553
1627
  return mi_extra(file, operation, 0);
1554
1628
}
1555
1629
 
1566
1640
 
1567
1641
int ha_myisam::extra_opt(enum ha_extra_function operation, uint32_t cache_size)
1568
1642
{
 
1643
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
 
1644
    return 0;
1569
1645
  return mi_extra(file, operation, (void*) &cache_size);
1570
1646
}
1571
1647
 
1588
1664
                                       F_UNLCK : F_EXTRA_LCK));
1589
1665
}
1590
1666
 
1591
 
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
 
1667
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((__unused__)),
1592
1668
                                      THR_LOCK_DATA **to,
1593
1669
                                      enum thr_lock_type lock_type)
1594
1670
{
1610
1686
}
1611
1687
 
1612
1688
 
1613
 
int ha_myisam::create(const char *name, register Table *table_arg,
 
1689
int ha_myisam::create(const char *name, register TABLE *table_arg,
1614
1690
                      HA_CREATE_INFO *ha_create_info)
1615
1691
{
1616
1692
  int error;
1617
 
  uint32_t create_flags= 0, records;
 
1693
  uint create_flags= 0, records, i;
1618
1694
  char buff[FN_REFLEN];
1619
1695
  MI_KEYDEF *keydef;
1620
1696
  MI_COLUMNDEF *recinfo;
1621
1697
  MI_CREATE_INFO create_info;
1622
1698
  TABLE_SHARE *share= table_arg->s;
1623
 
  uint32_t options= share->db_options_in_use;
 
1699
  uint options= share->db_options_in_use;
 
1700
  DBUG_ENTER("ha_myisam::create");
 
1701
  for (i= 0; i < share->keys; i++)
 
1702
  {
 
1703
    if (table_arg->key_info[i].flags & HA_USES_PARSER)
 
1704
    {
 
1705
      create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
 
1706
      break;
 
1707
    }
 
1708
  }
1624
1709
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1625
 
    return(error); /* purecov: inspected */
1626
 
  memset(&create_info, 0, sizeof(create_info));
 
1710
    DBUG_RETURN(error); /* purecov: inspected */
 
1711
  bzero((char*) &create_info, sizeof(create_info));
1627
1712
  create_info.max_rows= share->max_rows;
1628
1713
  create_info.reloc_rows= share->min_rows;
1629
1714
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1654
1739
                   records, recinfo,
1655
1740
                   0, (MI_UNIQUEDEF*) 0,
1656
1741
                   &create_info, create_flags);
1657
 
  free((unsigned char*) recinfo);
1658
 
  return(error);
 
1742
  my_free((uchar*) recinfo, MYF(0));
 
1743
  DBUG_RETURN(error);
1659
1744
}
1660
1745
 
1661
1746
 
1665
1750
}
1666
1751
 
1667
1752
 
1668
 
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1669
 
                                   uint64_t increment __attribute__((unused)),
1670
 
                                   uint64_t nb_desired_values __attribute__((unused)),
 
1753
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((__unused__)),
 
1754
                                   uint64_t increment __attribute__((__unused__)),
 
1755
                                   uint64_t nb_desired_values __attribute__((__unused__)),
1671
1756
                                   uint64_t *first_value,
1672
1757
                                   uint64_t *nb_reserved_values)
1673
1758
{
1674
1759
  uint64_t nr;
1675
1760
  int error;
1676
 
  unsigned char key[MI_MAX_KEY_LENGTH];
 
1761
  uchar key[MI_MAX_KEY_LENGTH];
1677
1762
 
1678
1763
  if (!table->s->next_number_key_offset)
1679
1764
  {                                             // Autoincrement at key-start
1739
1824
                        the range.
1740
1825
*/
1741
1826
 
1742
 
ha_rows ha_myisam::records_in_range(uint32_t inx, key_range *min_key,
 
1827
ha_rows ha_myisam::records_in_range(uint inx, key_range *min_key,
1743
1828
                                    key_range *max_key)
1744
1829
{
1745
1830
  return (ha_rows) mi_records_in_range(file, (int) inx, min_key, max_key);
1746
1831
}
1747
1832
 
1748
1833
 
1749
 
uint32_t ha_myisam::checksum() const
 
1834
uint ha_myisam::checksum() const
1750
1835
{
1751
1836
  return (uint)file->state->checksum;
1752
1837
}
1753
1838
 
1754
1839
 
1755
1840
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1756
 
                                           uint32_t table_changes)
 
1841
                                           uint table_changes)
1757
1842
{
1758
 
  uint32_t options= table->s->db_options_in_use;
 
1843
  uint options= table->s->db_options_in_use;
1759
1844
 
1760
1845
  if (info->auto_increment_value != stats.auto_increment_value ||
1761
1846
      info->data_file_name != data_file_name ||
1772
1857
  return COMPATIBLE_DATA_YES;
1773
1858
}
1774
1859
 
1775
 
int myisam_deinit(void *hton __attribute__((unused)))
 
1860
int myisam_panic(handlerton *hton __attribute__((__unused__)), ha_panic_function flag)
1776
1861
{
1777
 
  return mi_panic(HA_PANIC_CLOSE);
 
1862
  return mi_panic(flag);
1778
1863
}
1779
1864
 
1780
1865
static int myisam_init(void *p)
1783
1868
 
1784
1869
  myisam_hton= (handlerton *)p;
1785
1870
  myisam_hton->state= SHOW_OPTION_YES;
 
1871
  myisam_hton->db_type= DB_TYPE_MYISAM;
1786
1872
  myisam_hton->create= myisam_create_handler;
 
1873
  myisam_hton->panic= myisam_panic;
1787
1874
  myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1788
1875
  return 0;
1789
1876
}
1795
1882
 ***************************************************************************/
1796
1883
 
1797
1884
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
1798
 
                                     uint32_t n_ranges, uint32_t mode, 
 
1885
                                     uint n_ranges, uint mode, 
1799
1886
                                     HANDLER_BUFFER *buf)
1800
1887
{
1801
1888
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index], 
1807
1894
  return ds_mrr.dsmrr_next(this, range_info);
1808
1895
}
1809
1896
 
1810
 
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
1897
ha_rows ha_myisam::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
1811
1898
                                               void *seq_init_param, 
1812
 
                                               uint32_t n_ranges, uint32_t *bufsz,
1813
 
                                               uint32_t *flags, COST_VECT *cost)
 
1899
                                               uint n_ranges, uint *bufsz,
 
1900
                                               uint *flags, COST_VECT *cost)
1814
1901
{
1815
1902
  /*
1816
1903
    This call is here because there is no location where this->table would
1822
1909
                                 flags, cost);
1823
1910
}
1824
1911
 
1825
 
int ha_myisam::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
1826
 
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
 
1912
int ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
 
1913
                                     uint *bufsz, uint *flags, COST_VECT *cost)
1827
1914
{
1828
1915
  ds_mrr.init(this, table);
1829
1916
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
1835
1922
/* Index condition pushdown implementation*/
1836
1923
 
1837
1924
 
1838
 
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
 
1925
Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
1839
1926
{
1840
1927
  pushed_idx_cond_keyno= keyno_arg;
1841
1928
  pushed_idx_cond= idx_cond_arg;
1846
1933
}
1847
1934
 
1848
1935
 
 
1936
struct st_mysql_storage_engine myisam_storage_engine=
 
1937
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1938
 
1849
1939
mysql_declare_plugin(myisam)
1850
1940
{
1851
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1941
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1942
  &myisam_storage_engine,
1852
1943
  "MyISAM",
1853
 
  "1.0",
1854
1944
  "MySQL AB",
1855
1945
  "Default engine as of MySQL 3.23 with great performance",
1856
1946
  PLUGIN_LICENSE_GPL,
1857
1947
  myisam_init, /* Plugin Init */
1858
 
  myisam_deinit, /* Plugin Deinit */
 
1948
  NULL, /* Plugin Deinit */
 
1949
  0x0100, /* 1.0 */
1859
1950
  NULL,                       /* status variables                */
1860
1951
  NULL,                       /* system variables                */
1861
1952
  NULL                        /* config options                  */
1862
1953
}
1863
1954
mysql_declare_plugin_end;
 
1955
 
 
1956
 
 
1957
#ifdef HAVE_QUERY_CACHE
 
1958
/**
 
1959
  @brief Register a named table with a call back function to the query cache.
 
1960
 
 
1961
  @param thd The thread handle
 
1962
  @param table_key A pointer to the table name in the table cache
 
1963
  @param key_length The length of the table name
 
1964
  @param[out] engine_callback The pointer to the storage engine call back
 
1965
    function, currently 0
 
1966
  @param[out] engine_data Engine data will be set to 0.
 
1967
 
 
1968
  @note Despite the name of this function, it is used to check each statement
 
1969
    before it is cached and not to register a table or callback function.
 
1970
 
 
1971
  @see handler::register_query_cache_table
 
1972
 
 
1973
  @return The error code. The engine_data and engine_callback will be set to 0.
 
1974
    @retval true Success
 
1975
    @retval false An error occured
 
1976
*/
 
1977
 
 
1978
my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name,
 
1979
                                              uint table_name_len,
 
1980
                                              qc_engine_callback
 
1981
                                              *engine_callback,
 
1982
                                              uint64_t *engine_data)
 
1983
{
 
1984
  DBUG_ENTER("ha_myisam::register_query_cache_table");
 
1985
  /*
 
1986
    No call back function is needed to determine if a cached statement
 
1987
    is valid or not.
 
1988
  */
 
1989
  *engine_callback= 0;
 
1990
 
 
1991
  /*
 
1992
    No engine data is needed.
 
1993
  */
 
1994
  *engine_data= 0;
 
1995
 
 
1996
  if (file->s->concurrent_insert)
 
1997
  {
 
1998
    /*
 
1999
      If a concurrent INSERT has happened just before the currently
 
2000
      processed SELECT statement, the total size of the table is
 
2001
      unknown.
 
2002
 
 
2003
      To determine if the table size is known, the current thread's snap
 
2004
      shot of the table size with the actual table size are compared.
 
2005
 
 
2006
      If the table size is unknown the SELECT statement can't be cached.
 
2007
 
 
2008
      When concurrent inserts are disabled at table open, mi_open()
 
2009
      does not assign a get_status() function. In this case the local
 
2010
      ("current") status is never updated. We would wrongly think that
 
2011
      we cannot cache the statement.
 
2012
    */
 
2013
    uint64_t actual_data_file_length;
 
2014
    uint64_t current_data_file_length;
 
2015
 
 
2016
    /*
 
2017
      POSIX visibility rules specify that "2. Whatever memory values a
 
2018
      thread can see when it unlocks a mutex <...> can also be seen by any
 
2019
      thread that later locks the same mutex". In this particular case,
 
2020
      concurrent insert thread had modified the data_file_length in
 
2021
      MYISAM_SHARE before it has unlocked (or even locked)
 
2022
      structure_guard_mutex. So, here we're guaranteed to see at least that
 
2023
      value after we've locked the same mutex. We can see a later value
 
2024
      (modified by some other thread) though, but it's ok, as we only want
 
2025
      to know if the variable was changed, the actual new value doesn't matter
 
2026
    */
 
2027
    actual_data_file_length= file->s->state.state.data_file_length;
 
2028
    current_data_file_length= file->save_state.data_file_length;
 
2029
 
 
2030
    if (current_data_file_length != actual_data_file_length)
 
2031
    {
 
2032
      /* Don't cache current statement. */
 
2033
      DBUG_RETURN(false);
 
2034
    }
 
2035
  }
 
2036
 
 
2037
  /* It is ok to try to cache current statement. */
 
2038
  DBUG_RETURN(true);
 
2039
}
 
2040
#endif