~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Monty Taylor
  • Date: 2008-07-02 14:35:48 UTC
  • mto: This revision was merged to the branch mainline in revision 51.
  • Revision ID: monty@inaugust.com-20080702143548-onj30ry0sugr01uw
Removed all references to THREAD.

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>
 
30
#include "rt_index.h"
27
31
 
28
32
ulong myisam_recover_options= HA_RECOVER_NONE;
29
33
 
30
34
/* bits in myisam_recover_options */
31
35
const char *myisam_recover_names[] =
32
 
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
 
36
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
33
37
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
34
38
                                 myisam_recover_names, NULL};
35
39
 
36
40
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
37
 
                                           "nulls_ignored", NULL};
 
41
                                           "nulls_ignored", NullS};
38
42
TYPELIB myisam_stats_method_typelib= {
39
43
  array_elements(myisam_stats_method_names) - 1, "",
40
44
  myisam_stats_method_names, NULL};
58
62
{
59
63
  THD* thd = (THD*)param->thd;
60
64
  Protocol *protocol= thd->protocol;
61
 
  uint32_t length, msg_length;
 
65
  uint length, msg_length;
62
66
  char msgbuf[MI_MAX_MSG_BUF];
63
67
  char name[NAME_LEN*2+2];
64
68
 
65
 
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
 
69
  msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
66
70
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
67
71
 
 
72
  DBUG_PRINT(msg_type,("message: %s",msgbuf));
 
73
 
68
74
  if (!thd->vio_ok())
69
75
  {
70
76
    sql_print_error(msgbuf);
77
83
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
78
84
    return;
79
85
  }
80
 
  length=(uint) (strxmov(name, param->db_name,".",param->table_name,NULL) -
 
86
  length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
81
87
                 name);
82
88
  /*
83
89
    TODO: switch from protocol to push_warning here. The main reason we didn't
100
106
 
101
107
 
102
108
/*
103
 
  Convert Table object to MyISAM key and column definition
 
109
  Convert TABLE object to MyISAM key and column definition
104
110
 
105
111
  SYNOPSIS
106
112
    table2myisam()
107
 
      table_arg   in     Table object.
 
113
      table_arg   in     TABLE object.
108
114
      keydef_out  out    MyISAM key definition.
109
115
      recinfo_out out    MyISAM column definition.
110
116
      records_out out    Number of fields.
123
129
    !0 error code
124
130
*/
125
131
 
126
 
int table2myisam(Table *table_arg, MI_KEYDEF **keydef_out,
127
 
                 MI_COLUMNDEF **recinfo_out, uint32_t *records_out)
 
132
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
 
133
                 MI_COLUMNDEF **recinfo_out, uint *records_out)
128
134
{
129
 
  uint32_t i, j, recpos, minpos, fieldpos, temp_length, length;
 
135
  uint i, j, recpos, minpos, fieldpos, temp_length, length;
130
136
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
131
 
  unsigned char *record;
 
137
  uchar *record;
132
138
  KEY *pos;
133
139
  MI_KEYDEF *keydef;
134
140
  MI_COLUMNDEF *recinfo, *recinfo_pos;
135
141
  HA_KEYSEG *keyseg;
136
142
  TABLE_SHARE *share= table_arg->s;
137
 
  uint32_t options= share->db_options_in_use;
 
143
  uint options= share->db_options_in_use;
 
144
  DBUG_ENTER("table2myisam");
138
145
  if (!(my_multi_malloc(MYF(MY_WME),
139
146
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
140
147
          keydef_out, share->keys * sizeof(MI_KEYDEF),
141
148
          &keyseg,
142
149
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
143
 
          NULL)))
144
 
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
 
150
          NullS)))
 
151
    DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
145
152
  keydef= *keydef_out;
146
153
  recinfo= *recinfo_out;
147
154
  pos= table_arg->key_info;
148
155
  for (i= 0; i < share->keys; i++, pos++)
149
156
  {
150
 
    keydef[i].flag= ((uint16_t) pos->flags & (HA_NOSAME));
151
 
    keydef[i].key_alg= HA_KEY_ALG_BTREE;
 
157
    keydef[i].flag= ((uint16) pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
 
158
    keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
 
159
      (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
 
160
      pos->algorithm;
152
161
    keydef[i].block_length= pos->block_size;
153
162
    keydef[i].seg= keyseg;
154
163
    keydef[i].keysegs= pos->key_parts;
170
179
          /* No blobs here */
171
180
          if (j == 0)
172
181
            keydef[i].flag|= HA_PACK_KEY;
173
 
          if ((((int) (pos->key_part[j].length - field->decimals())) >= 4))
 
182
          if (!(field->flags & ZEROFILL_FLAG) &&
 
183
              (field->type() == MYSQL_TYPE_STRING ||
 
184
               field->type() == MYSQL_TYPE_VAR_STRING ||
 
185
               ((int) (pos->key_part[j].length - field->decimals())) >= 4))
174
186
            keydef[i].seg[j].flag|= HA_SPACE_PACK;
175
187
        }
176
188
        else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
188
200
      {
189
201
        keydef[i].seg[j].null_bit= field->null_bit;
190
202
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
191
 
                                           (unsigned char*) table_arg->record[0]);
 
203
                                           (uchar*) table_arg->record[0]);
192
204
      }
193
205
      else
194
206
      {
195
207
        keydef[i].seg[j].null_bit= 0;
196
208
        keydef[i].seg[j].null_pos= 0;
197
209
      }
198
 
      if (field->type() == DRIZZLE_TYPE_BLOB)
 
210
      if (field->type() == MYSQL_TYPE_BLOB ||
 
211
          field->type() == MYSQL_TYPE_GEOMETRY)
199
212
      {
200
213
        keydef[i].seg[j].flag|= HA_BLOB_PART;
201
214
        /* save number of bytes used to pack length */
202
215
        keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
203
216
                                            share->blob_ptr_size);
204
217
      }
 
218
      else if (field->type() == MYSQL_TYPE_BIT)
 
219
      {
 
220
        keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
 
221
        keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
 
222
        keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
 
223
                                          (uchar*) table_arg->record[0]);
 
224
      }
205
225
    }
206
226
    keyseg+= pos->key_parts;
207
227
  }
210
230
  record= table_arg->record[0];
211
231
  recpos= 0;
212
232
  recinfo_pos= recinfo;
213
 
  while (recpos < (uint) share->stored_rec_length)
 
233
  while (recpos < (uint) share->reclength)
214
234
  {
215
235
    Field **field, *found= 0;
216
236
    minpos= share->reclength;
233
253
        }
234
254
      }
235
255
    }
 
256
    DBUG_PRINT("loop", ("found: 0x%lx  recpos: %d  minpos: %d  length: %d",
 
257
                        (long) found, recpos, minpos, length));
236
258
    if (recpos != minpos)
237
259
    { // Reserved space (Null bits?)
238
 
      memset(recinfo_pos, 0, sizeof(*recinfo_pos));
 
260
      bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
239
261
      recinfo_pos->type= (int) FIELD_NORMAL;
240
 
      recinfo_pos++->length= (uint16_t) (minpos - recpos);
 
262
      recinfo_pos++->length= (uint16) (minpos - recpos);
241
263
    }
242
264
    if (!found)
243
265
      break;
244
266
 
245
267
    if (found->flags & BLOB_FLAG)
246
268
      recinfo_pos->type= (int) FIELD_BLOB;
247
 
    else if (found->type() == DRIZZLE_TYPE_VARCHAR)
 
269
    else if (found->type() == MYSQL_TYPE_VARCHAR)
248
270
      recinfo_pos->type= FIELD_VARCHAR;
249
271
    else if (!(options & HA_OPTION_PACK_RECORD))
250
272
      recinfo_pos->type= (int) FIELD_NORMAL;
251
273
    else if (found->zero_pack())
252
274
      recinfo_pos->type= (int) FIELD_SKIP_ZERO;
253
275
    else
254
 
      recinfo_pos->type= (int) ((length <= 3) ?  FIELD_NORMAL : FIELD_SKIP_PRESPACE);
 
276
      recinfo_pos->type= (int) ((length <= 3 ||
 
277
                                 (found->flags & ZEROFILL_FLAG)) ?
 
278
                                  FIELD_NORMAL :
 
279
                                  found->type() == MYSQL_TYPE_STRING ||
 
280
                                  found->type() == MYSQL_TYPE_VAR_STRING ?
 
281
                                  FIELD_SKIP_ENDSPACE :
 
282
                                  FIELD_SKIP_PRESPACE);
255
283
    if (found->null_ptr)
256
284
    {
257
285
      recinfo_pos->null_bit= found->null_bit;
258
286
      recinfo_pos->null_pos= (uint) (found->null_ptr -
259
 
                                     (unsigned char*) table_arg->record[0]);
 
287
                                     (uchar*) table_arg->record[0]);
260
288
    }
261
289
    else
262
290
    {
263
291
      recinfo_pos->null_bit= 0;
264
292
      recinfo_pos->null_pos= 0;
265
293
    }
266
 
    (recinfo_pos++)->length= (uint16_t) length;
 
294
    (recinfo_pos++)->length= (uint16) length;
267
295
    recpos= minpos + length;
 
296
    DBUG_PRINT("loop", ("length: %d  type: %d",
 
297
                        recinfo_pos[-1].length,recinfo_pos[-1].type));
268
298
  }
269
299
  *records_out= (uint) (recinfo_pos - recinfo);
270
 
  return(0);
 
300
  DBUG_RETURN(0);
271
301
}
272
302
 
273
303
 
312
342
*/
313
343
 
314
344
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
315
 
                     uint32_t t1_keys, uint32_t t1_recs,
 
345
                     uint t1_keys, uint t1_recs,
316
346
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
317
 
                     uint32_t t2_keys, uint32_t t2_recs, bool strict)
 
347
                     uint t2_keys, uint t2_recs, bool strict)
318
348
{
319
 
  uint32_t i, j;
 
349
  uint i, j;
 
350
  DBUG_ENTER("check_definition");
320
351
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
321
352
  {
322
 
    return(1);
 
353
    DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
 
354
                         t1_keys, t2_keys));
 
355
    DBUG_RETURN(1);
323
356
  }
324
357
  if (t1_recs != t2_recs)
325
358
  {
326
 
    return(1);
 
359
    DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
 
360
                         t1_recs, t2_recs));
 
361
    DBUG_RETURN(1);
327
362
  }
328
363
  for (i= 0; i < t1_keys; i++)
329
364
  {
330
365
    HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
331
366
    HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
 
367
    if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
 
368
      continue;
 
369
    else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
 
370
             t2_keyinfo[i].flag & HA_FULLTEXT)
 
371
    {
 
372
       DBUG_PRINT("error", ("Key %d has different definition", i));
 
373
       DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
 
374
                            test(t1_keyinfo[i].flag & HA_FULLTEXT),
 
375
                            test(t2_keyinfo[i].flag & HA_FULLTEXT)));
 
376
       DBUG_RETURN(1);
 
377
    }
 
378
    if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
 
379
      continue;
 
380
    else if (t1_keyinfo[i].flag & HA_SPATIAL ||
 
381
             t2_keyinfo[i].flag & HA_SPATIAL)
 
382
    {
 
383
       DBUG_PRINT("error", ("Key %d has different definition", i));
 
384
       DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
 
385
                            test(t1_keyinfo[i].flag & HA_SPATIAL),
 
386
                            test(t2_keyinfo[i].flag & HA_SPATIAL)));
 
387
       DBUG_RETURN(1);
 
388
    }
332
389
    if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
333
390
        t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
334
391
    {
335
 
      return(1);
 
392
      DBUG_PRINT("error", ("Key %d has different definition", i));
 
393
      DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
 
394
                           t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
 
395
      DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
 
396
                           t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
 
397
      DBUG_RETURN(1);
336
398
    }
337
399
    for (j=  t1_keyinfo[i].keysegs; j--;)
338
400
    {
339
 
      uint8_t t1_keysegs_j__type= t1_keysegs[j].type;
 
401
      uint8 t1_keysegs_j__type= t1_keysegs[j].type;
340
402
 
341
403
      /*
342
404
        Table migration from 4.1 to 5.1. In 5.1 a *TEXT key part is
360
422
          t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
361
423
          t1_keysegs[j].length != t2_keysegs[j].length)
362
424
      {
363
 
        return(1);
 
425
        DBUG_PRINT("error", ("Key segment %d (key %d) has different "
 
426
                             "definition", j, i));
 
427
        DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
 
428
                             "t1_length=%d",
 
429
                             t1_keysegs[j].type, t1_keysegs[j].language,
 
430
                             t1_keysegs[j].null_bit, t1_keysegs[j].length));
 
431
        DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
 
432
                             "t2_length=%d",
 
433
                             t2_keysegs[j].type, t2_keysegs[j].language,
 
434
                             t2_keysegs[j].null_bit, t2_keysegs[j].length));
 
435
 
 
436
        DBUG_RETURN(1);
364
437
      }
365
438
    }
366
439
  }
379
452
        t1_rec->length != t2_rec->length ||
380
453
        t1_rec->null_bit != t2_rec->null_bit)
381
454
    {
382
 
      return(1);
 
455
      DBUG_PRINT("error", ("Field %d has different definition", i));
 
456
      DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
 
457
                           t1_rec->type, t1_rec->length, t1_rec->null_bit));
 
458
      DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
 
459
                           t2_rec->type, t2_rec->length, t2_rec->null_bit));
 
460
      DBUG_RETURN(1);
383
461
    }
384
462
  }
385
 
  return(0);
 
463
  DBUG_RETURN(0);
386
464
}
387
465
 
388
466
 
422
500
  va_end(args);
423
501
}
424
502
 
 
503
 
425
504
/**
426
505
  Report list of threads (and queries) accessing a table, thread_id of a
427
506
  thread that detected corruption, ource file name and line number where
438
517
*/
439
518
 
440
519
void _mi_report_crashed(MI_INFO *file, const char *message,
441
 
                        const char *sfile, uint32_t sline)
 
520
                        const char *sfile, uint sline)
442
521
{
443
522
  THD *cur_thd;
444
523
  LIST *element;
 
524
  char buf[1024];
445
525
  pthread_mutex_lock(&file->s->intern_lock);
446
526
  if ((cur_thd= (THD*) file->in_use.data))
447
527
    sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
452
532
    sql_print_error("%s", message);
453
533
  for (element= file->s->in_use; element; element= list_rest(element))
454
534
  {
455
 
    sql_print_error("%s", "Unknown thread accessing table");
 
535
    THD *thd= (THD*) element->data;
 
536
    sql_print_error("%s", thd ? thd_security_context(thd, buf, sizeof(buf), 0)
 
537
                              : "Unknown thread accessing table");
456
538
  }
457
539
  pthread_mutex_unlock(&file->s->intern_lock);
458
540
}
459
541
 
460
542
}
461
543
 
 
544
 
462
545
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
463
546
  :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),
 
547
  int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
 
548
                  HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
 
549
                  HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
 
550
                  HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
 
551
                  HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
 
552
                  HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT |
 
553
                  HA_NEED_READ_RANGE_BUFFER | HA_MRR_CANT_SORT),
476
554
   can_enable_indexes(1)
477
555
{}
478
556
 
488
566
static const char *ha_myisam_exts[] = {
489
567
  ".MYI",
490
568
  ".MYD",
491
 
  NULL
 
569
  NullS
492
570
};
493
571
 
494
572
const char **ha_myisam::bas_ext() const
497
575
}
498
576
 
499
577
 
500
 
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
 
578
const char *ha_myisam::index_type(uint key_number)
501
579
{
502
 
  return "BTREE";
 
580
  return ((table->key_info[key_number].flags & HA_FULLTEXT) ? 
 
581
          "FULLTEXT" :
 
582
          (table->key_info[key_number].flags & HA_SPATIAL) ?
 
583
          "SPATIAL" :
 
584
          (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
 
585
          "RTREE" :
 
586
          "BTREE");
503
587
}
504
588
 
505
589
/* Name is here without an extension */
506
 
int ha_myisam::open(const char *name, int mode, uint32_t test_if_locked)
 
590
int ha_myisam::open(const char *name, int mode, uint test_if_locked)
507
591
{
508
592
  MI_KEYDEF *keyinfo;
509
593
  MI_COLUMNDEF *recinfo= 0;
510
 
  uint32_t recs;
511
 
  uint32_t i;
 
594
  uint recs;
 
595
  uint i;
512
596
 
513
597
  /*
514
598
    If the user wants to have memory mapped data files, add an
532
616
    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
533
617
    {
534
618
      /* purecov: begin inspected */
 
619
      DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM "
 
620
                           "key and column definition"));
535
621
      goto err;
536
622
      /* purecov: end */
537
623
    }
547
633
  }
548
634
  
549
635
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
550
 
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
 
636
    VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
551
637
 
552
638
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
553
639
  if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
554
 
    mi_extra(file, HA_EXTRA_WAIT_LOCK, 0);
 
640
    VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
555
641
  if (!table->s->db_record_offset)
556
642
    int_table_flags|=HA_REC_NOT_IN_SEQ;
557
643
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
583
669
    recinfo must be freed.
584
670
  */
585
671
  if (recinfo)
586
 
    free((unsigned char*) recinfo);
 
672
    my_free((uchar*) recinfo, MYF(0));
587
673
  return my_errno;
588
674
}
589
675
 
594
680
  return mi_close(tmp);
595
681
}
596
682
 
597
 
int ha_myisam::write_row(unsigned char *buf)
 
683
int ha_myisam::write_row(uchar *buf)
598
684
{
599
685
  ha_statistic_increment(&SSV::ha_write_count);
600
686
 
621
707
  int error;
622
708
  MI_CHECK param;
623
709
  MYISAM_SHARE* share = file->s;
624
 
  const char *old_proc_info= thd->get_proc_info();
 
710
  const char *old_proc_info=thd->proc_info;
625
711
 
626
 
  thd->set_proc_info("Checking table");
 
712
  thd_proc_info(thd, "Checking table");
627
713
  myisamchk_init(&param);
628
714
  param.thd = thd;
629
715
  param.op_name =   "check";
659
745
          (param.testflag & (T_EXTEND | T_MEDIUM)))) ||
660
746
        mi_is_crashed(file))
661
747
    {
662
 
      uint32_t old_testflag=param.testflag;
 
748
      uint old_testflag=param.testflag;
663
749
      param.testflag|=T_MEDIUM;
664
750
      if (!(error= init_io_cache(&param.read_cache, file->dfile,
665
751
                                 my_default_record_cache_size, READ_CACHE,
697
783
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
698
784
  }
699
785
 
700
 
  thd->set_proc_info(old_proc_info);
 
786
  thd_proc_info(thd, old_proc_info);
701
787
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
702
788
}
703
789
 
708
794
  two threads may do an analyze at the same time!
709
795
*/
710
796
 
711
 
int ha_myisam::analyze(THD *thd,
712
 
                       HA_CHECK_OPT* check_opt __attribute__((unused)))
 
797
int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
713
798
{
714
799
  int error=0;
715
800
  MI_CHECK param;
816
901
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
817
902
{
818
903
  int error=0;
819
 
  uint32_t local_testflag=param.testflag;
 
904
  uint local_testflag=param.testflag;
820
905
  bool optimize_done= !do_optimize, statistics_done=0;
821
 
  const char *old_proc_info= thd->get_proc_info();
 
906
  const char *old_proc_info=thd->proc_info;
822
907
  char fixed_name[FN_REFLEN];
823
908
  MYISAM_SHARE* share = file->s;
824
909
  ha_rows rows= file->state->records;
 
910
  DBUG_ENTER("ha_myisam::repair");
825
911
 
826
912
  /*
827
913
    Normally this method is entered with a properly opened table. If the
836
922
    sql_print_information("Retrying repair of: '%s' failed. "
837
923
                          "Please try REPAIR EXTENDED or myisamchk",
838
924
                          table->s->path.str);
839
 
    return(HA_ADMIN_FAILED);
 
925
    DBUG_RETURN(HA_ADMIN_FAILED);
840
926
  }
841
927
 
842
928
  param.db_name=    table->s->db.str;
846
932
  param.thd= thd;
847
933
  param.tmpdir= &mysql_tmpdir_list;
848
934
  param.out_flag= 0;
849
 
  my_stpcpy(fixed_name,file->filename);
 
935
  strmov(fixed_name,file->filename);
850
936
 
851
 
  // Don't lock tables if we have used LOCK Table
 
937
  // Don't lock tables if we have used LOCK TABLE
852
938
  if (!thd->locked_tables && 
853
939
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
854
940
  {
855
941
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
856
 
    return(HA_ADMIN_FAILED);
 
942
    DBUG_RETURN(HA_ADMIN_FAILED);
857
943
  }
858
944
 
859
945
  if (!do_optimize ||
864
950
    uint64_t key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ?
865
951
                        mi_get_mask_all_keys_active(share->base.keys) :
866
952
                        share->state.key_map);
867
 
    uint32_t testflag=param.testflag;
 
953
    uint testflag=param.testflag;
868
954
    if (mi_test_if_sort_rep(file,file->state->records,key_map,0) &&
869
955
        (local_testflag & T_REP_BY_SORT))
870
956
    {
875
961
      {
876
962
        char buf[40];
877
963
        /* TODO: respect myisam_repair_threads variable */
878
 
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
879
 
        thd->set_proc_info(buf);
 
964
        my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
 
965
        thd_proc_info(thd, buf);
880
966
        error = mi_repair_parallel(&param, file, fixed_name,
881
967
            param.testflag & T_QUICK);
882
 
        thd->set_proc_info("Repair done"); // to reset proc_info, as
 
968
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
883
969
                                      // it was pointing to local buffer
884
970
      }
885
971
      else
886
972
      {
887
 
        thd->set_proc_info("Repair by sorting");
 
973
        thd_proc_info(thd, "Repair by sorting");
888
974
        error = mi_repair_by_sort(&param, file, fixed_name,
889
975
            param.testflag & T_QUICK);
890
976
      }
891
977
    }
892
978
    else
893
979
    {
894
 
      thd->set_proc_info("Repair with keycache");
 
980
      thd_proc_info(thd, "Repair with keycache");
895
981
      param.testflag &= ~T_REP_BY_SORT;
896
982
      error=  mi_repair(&param, file, fixed_name,
897
983
                        param.testflag & T_QUICK);
905
991
        (share->state.changed & STATE_NOT_SORTED_PAGES))
906
992
    {
907
993
      optimize_done=1;
908
 
      thd->set_proc_info("Sorting index");
 
994
      thd_proc_info(thd, "Sorting index");
909
995
      error=mi_sort_index(&param,file,fixed_name);
910
996
    }
911
997
    if (!statistics_done && (local_testflag & T_STATISTICS))
913
999
      if (share->state.changed & STATE_NOT_ANALYZED)
914
1000
      {
915
1001
        optimize_done=1;
916
 
        thd->set_proc_info("Analyzing");
 
1002
        thd_proc_info(thd, "Analyzing");
917
1003
        error = chk_key(&param, file);
918
1004
      }
919
1005
      else
920
1006
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
921
1007
    }
922
1008
  }
923
 
  thd->set_proc_info("Saving state");
 
1009
  thd_proc_info(thd, "Saving state");
924
1010
  if (!error)
925
1011
  {
926
1012
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
958
1044
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
959
1045
    update_state_info(&param, file, 0);
960
1046
  }
961
 
  thd->set_proc_info(old_proc_info);
 
1047
  thd_proc_info(thd, old_proc_info);
962
1048
  if (!thd->locked_tables)
963
1049
    mi_lock_database(file,F_UNLCK);
964
 
  return(error ? HA_ADMIN_FAILED :
 
1050
  DBUG_RETURN(error ? HA_ADMIN_FAILED :
965
1051
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
966
1052
}
967
1053
 
976
1062
  const char *errmsg= 0;
977
1063
  int error= HA_ADMIN_OK;
978
1064
  uint64_t map;
979
 
  TableList *table_list= table->pos_in_table_list;
 
1065
  TABLE_LIST *table_list= table->pos_in_table_list;
 
1066
  DBUG_ENTER("ha_myisam::assign_to_keycache");
980
1067
 
981
1068
  table->keys_in_use_for_query.clear_all();
982
1069
 
983
1070
  if (table_list->process_index_hints(table))
984
 
    return(HA_ADMIN_FAILED);
 
1071
    DBUG_RETURN(HA_ADMIN_FAILED);
985
1072
  map= ~(uint64_t) 0;
986
1073
  if (!table->keys_in_use_for_query.is_clear_all())
987
1074
    /* use all keys if there's no list specified by the user through hints */
988
 
    map= table->keys_in_use_for_query.to_uint64_t();
 
1075
    map= table->keys_in_use_for_query.to_ulonglong();
989
1076
 
990
1077
  if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
991
1078
  { 
992
1079
    char buf[STRING_BUFFER_USUAL_SIZE];
993
 
    snprintf(buf, sizeof(buf),
 
1080
    my_snprintf(buf, sizeof(buf),
994
1081
                "Failed to flush to index file (errno: %d)", error);
995
1082
    errmsg= buf;
996
1083
    error= HA_ADMIN_CORRUPT;
1008
1095
    param.testflag= 0;
1009
1096
    mi_check_print_error(&param, errmsg);
1010
1097
  }
1011
 
  return(error);
 
1098
  DBUG_RETURN(error);
 
1099
}
 
1100
 
 
1101
 
 
1102
/*
 
1103
  Preload pages of the index file for a table into the key cache.
 
1104
*/
 
1105
 
 
1106
int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
 
1107
{
 
1108
  int error;
 
1109
  const char *errmsg;
 
1110
  uint64_t map;
 
1111
  TABLE_LIST *table_list= table->pos_in_table_list;
 
1112
  my_bool ignore_leaves= table_list->ignore_leaves;
 
1113
  char buf[ERRMSGSIZE+20];
 
1114
 
 
1115
  DBUG_ENTER("ha_myisam::preload_keys");
 
1116
 
 
1117
  table->keys_in_use_for_query.clear_all();
 
1118
 
 
1119
  if (table_list->process_index_hints(table))
 
1120
    DBUG_RETURN(HA_ADMIN_FAILED);
 
1121
 
 
1122
  map= ~(uint64_t) 0;
 
1123
  /* Check validity of the index references */
 
1124
  if (!table->keys_in_use_for_query.is_clear_all())
 
1125
    /* use all keys if there's no list specified by the user through hints */
 
1126
    map= table->keys_in_use_for_query.to_ulonglong();
 
1127
 
 
1128
  mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
 
1129
           (void *) &thd->variables.preload_buff_size);
 
1130
 
 
1131
  if ((error= mi_preload(file, map, ignore_leaves)))
 
1132
  {
 
1133
    switch (error) {
 
1134
    case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
 
1135
      errmsg= "Indexes use different block sizes";
 
1136
      break;
 
1137
    case HA_ERR_OUT_OF_MEM:
 
1138
      errmsg= "Failed to allocate buffer";
 
1139
      break;
 
1140
    default:
 
1141
      my_snprintf(buf, ERRMSGSIZE,
 
1142
                  "Failed to read from index file (errno: %d)", my_errno);
 
1143
      errmsg= buf;
 
1144
    }
 
1145
    error= HA_ADMIN_FAILED;
 
1146
    goto err;
 
1147
  }
 
1148
 
 
1149
  DBUG_RETURN(HA_ADMIN_OK);
 
1150
 
 
1151
 err:
 
1152
  {
 
1153
    MI_CHECK param;
 
1154
    myisamchk_init(&param);
 
1155
    param.thd= thd;
 
1156
    param.op_name=    "preload_keys";
 
1157
    param.db_name=    table->s->db.str;
 
1158
    param.table_name= table->s->table_name.str;
 
1159
    param.testflag=   0;
 
1160
    mi_check_print_error(&param, errmsg);
 
1161
    DBUG_RETURN(error);
 
1162
  }
1012
1163
}
1013
1164
 
1014
1165
 
1032
1183
    HA_ERR_WRONG_COMMAND  mode not implemented.
1033
1184
*/
1034
1185
 
1035
 
int ha_myisam::disable_indexes(uint32_t mode)
 
1186
int ha_myisam::disable_indexes(uint mode)
1036
1187
{
1037
1188
  int error;
1038
1189
 
1084
1235
    HA_ERR_WRONG_COMMAND  mode not implemented.
1085
1236
*/
1086
1237
 
1087
 
int ha_myisam::enable_indexes(uint32_t mode)
 
1238
int ha_myisam::enable_indexes(uint mode)
1088
1239
{
1089
1240
  int error;
1090
1241
 
1107
1258
  {
1108
1259
    THD *thd=current_thd;
1109
1260
    MI_CHECK param;
1110
 
    const char *save_proc_info= thd->get_proc_info();
1111
 
    thd->set_proc_info("Creating index");
 
1261
    const char *save_proc_info=thd->proc_info;
 
1262
    thd_proc_info(thd, "Creating index");
1112
1263
    myisamchk_init(&param);
1113
1264
    param.op_name= "recreating_index";
1114
1265
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
1133
1284
        thd->clear_error();
1134
1285
    }
1135
1286
    info(HA_STATUS_CONST);
1136
 
    thd->set_proc_info(save_proc_info);
 
1287
    thd_proc_info(thd, save_proc_info);
1137
1288
  }
1138
1289
  else
1139
1290
  {
1182
1333
 
1183
1334
void ha_myisam::start_bulk_insert(ha_rows rows)
1184
1335
{
 
1336
  DBUG_ENTER("ha_myisam::start_bulk_insert");
1185
1337
  THD *thd= current_thd;
1186
 
  ulong size= cmin(thd->variables.read_buff_size,
 
1338
  ulong size= min(thd->variables.read_buff_size,
1187
1339
                  (ulong) (table->s->avg_row_length*rows));
 
1340
  DBUG_PRINT("info",("start_bulk_insert: rows %lu size %lu",
 
1341
                     (ulong) rows, size));
1188
1342
 
1189
1343
  /* don't enable row cache if too few rows */
1190
1344
  if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE))
1193
1347
  can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map,
1194
1348
                                            file->s->base.keys);
1195
1349
 
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
 
1350
  if (!(specialflag & SPECIAL_SAFE_MODE))
 
1351
  {
 
1352
    /*
 
1353
      Only disable old index if the table was empty and we are inserting
 
1354
      a lot of rows.
 
1355
      We should not do this for only a few rows as this is slower and
 
1356
      we don't want to update the key statistics based of only a few rows.
 
1357
    */
 
1358
    if (file->state->records == 0 && can_enable_indexes &&
 
1359
        (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
 
1360
      mi_disable_non_unique_index(file,rows);
 
1361
    else
1206
1362
    if (!file->bulk_insert &&
1207
1363
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1208
1364
    {
1209
1365
      mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
1210
1366
    }
1211
 
 
1212
 
  return;
 
1367
  }
 
1368
  DBUG_VOID_RETURN;
1213
1369
}
1214
1370
 
1215
1371
/*
1239
1395
  int error=0;
1240
1396
  int marked_crashed;
1241
1397
  char *old_query;
1242
 
  uint32_t old_query_length;
 
1398
  uint old_query_length;
1243
1399
  HA_CHECK_OPT check_opt;
 
1400
  DBUG_ENTER("ha_myisam::check_and_repair");
1244
1401
 
1245
1402
  check_opt.init();
1246
1403
  check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
1271
1428
  thd->query= old_query;
1272
1429
  thd->query_length= old_query_length;
1273
1430
  pthread_mutex_unlock(&LOCK_thread_count);
1274
 
  return(error);
 
1431
  DBUG_RETURN(error);
1275
1432
}
1276
1433
 
1277
1434
bool ha_myisam::is_crashed() const
1278
1435
{
1279
1436
  return (file->s->state.changed & STATE_CRASHED ||
1280
 
          (file->s->state.open_count));
 
1437
          (my_disable_locking && file->s->state.open_count));
1281
1438
}
1282
1439
 
1283
 
int ha_myisam::update_row(const unsigned char *old_data, unsigned char *new_data)
 
1440
int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
1284
1441
{
1285
1442
  ha_statistic_increment(&SSV::ha_update_count);
1286
1443
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
1288
1445
  return mi_update(file,old_data,new_data);
1289
1446
}
1290
1447
 
1291
 
int ha_myisam::delete_row(const unsigned char *buf)
 
1448
int ha_myisam::delete_row(const uchar *buf)
1292
1449
{
1293
1450
  ha_statistic_increment(&SSV::ha_delete_count);
1294
1451
  return mi_delete(file,buf);
1295
1452
}
1296
1453
 
1297
 
#ifdef __cplusplus
1298
 
extern "C" {
1299
 
#endif
 
1454
C_MODE_START
1300
1455
 
1301
 
bool index_cond_func_myisam(void *arg)
 
1456
my_bool index_cond_func_myisam(void *arg)
1302
1457
{
1303
1458
  ha_myisam *h= (ha_myisam*)arg;
1304
1459
  /*if (h->in_range_read)*/
1307
1462
    if (h->compare_key2(h->end_range) > 0)
1308
1463
      return 2; /* caller should return HA_ERR_END_OF_FILE already */
1309
1464
  }
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)))
 
1465
  return (my_bool)h->pushed_idx_cond->val_int();
 
1466
}
 
1467
 
 
1468
C_MODE_END
 
1469
 
 
1470
 
 
1471
int ha_myisam::index_init(uint idx, bool sorted)
1319
1472
1320
1473
  active_index=idx;
1321
 
  //in_range_read= false;
 
1474
  //in_range_read= FALSE;
1322
1475
  if (pushed_idx_cond_keyno == idx)
1323
1476
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
1324
1477
  return 0; 
1330
1483
  active_index=MAX_KEY;
1331
1484
  //pushed_idx_cond_keyno= MAX_KEY;
1332
1485
  mi_set_index_cond_func(file, NULL, 0);
1333
 
  in_range_check_pushed_down= false;
 
1486
  in_range_check_pushed_down= FALSE;
1334
1487
  ds_mrr.dsmrr_close();
1335
1488
  return 0; 
1336
1489
}
1337
1490
 
1338
1491
 
1339
 
int ha_myisam::index_read_map(unsigned char *buf, const unsigned char *key,
 
1492
int ha_myisam::index_read_map(uchar *buf, const uchar *key,
1340
1493
                              key_part_map keypart_map,
1341
1494
                              enum ha_rkey_function find_flag)
1342
1495
{
1343
 
  assert(inited==INDEX);
 
1496
  DBUG_ASSERT(inited==INDEX);
1344
1497
  ha_statistic_increment(&SSV::ha_read_key_count);
1345
1498
  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
1346
1499
  table->status=error ? STATUS_NOT_FOUND: 0;
1347
1500
  return error;
1348
1501
}
1349
1502
 
1350
 
int ha_myisam::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
 
1503
int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
1351
1504
                                  key_part_map keypart_map,
1352
1505
                                  enum ha_rkey_function find_flag)
1353
1506
{
1357
1510
  return error;
1358
1511
}
1359
1512
 
1360
 
int ha_myisam::index_read_last_map(unsigned char *buf, const unsigned char *key,
 
1513
int ha_myisam::index_read_last_map(uchar *buf, const uchar *key,
1361
1514
                                   key_part_map keypart_map)
1362
1515
{
1363
 
  assert(inited==INDEX);
 
1516
  DBUG_ENTER("ha_myisam::index_read_last");
 
1517
  DBUG_ASSERT(inited==INDEX);
1364
1518
  ha_statistic_increment(&SSV::ha_read_key_count);
1365
1519
  int error=mi_rkey(file, buf, active_index, key, keypart_map,
1366
1520
                    HA_READ_PREFIX_LAST);
1367
1521
  table->status=error ? STATUS_NOT_FOUND: 0;
1368
 
  return(error);
 
1522
  DBUG_RETURN(error);
1369
1523
}
1370
1524
 
1371
 
int ha_myisam::index_next(unsigned char *buf)
 
1525
int ha_myisam::index_next(uchar *buf)
1372
1526
{
1373
 
  assert(inited==INDEX);
 
1527
  DBUG_ASSERT(inited==INDEX);
1374
1528
  ha_statistic_increment(&SSV::ha_read_next_count);
1375
1529
  int error=mi_rnext(file,buf,active_index);
1376
1530
  table->status=error ? STATUS_NOT_FOUND: 0;
1377
1531
  return error;
1378
1532
}
1379
1533
 
1380
 
int ha_myisam::index_prev(unsigned char *buf)
 
1534
int ha_myisam::index_prev(uchar *buf)
1381
1535
{
1382
 
  assert(inited==INDEX);
 
1536
  DBUG_ASSERT(inited==INDEX);
1383
1537
  ha_statistic_increment(&SSV::ha_read_prev_count);
1384
1538
  int error=mi_rprev(file,buf, active_index);
1385
1539
  table->status=error ? STATUS_NOT_FOUND: 0;
1386
1540
  return error;
1387
1541
}
1388
1542
 
1389
 
int ha_myisam::index_first(unsigned char *buf)
 
1543
int ha_myisam::index_first(uchar *buf)
1390
1544
{
1391
 
  assert(inited==INDEX);
 
1545
  DBUG_ASSERT(inited==INDEX);
1392
1546
  ha_statistic_increment(&SSV::ha_read_first_count);
1393
1547
  int error=mi_rfirst(file, buf, active_index);
1394
1548
  table->status=error ? STATUS_NOT_FOUND: 0;
1395
1549
  return error;
1396
1550
}
1397
1551
 
1398
 
int ha_myisam::index_last(unsigned char *buf)
 
1552
int ha_myisam::index_last(uchar *buf)
1399
1553
{
1400
 
  assert(inited==INDEX);
 
1554
  DBUG_ASSERT(inited==INDEX);
1401
1555
  ha_statistic_increment(&SSV::ha_read_last_count);
1402
1556
  int error=mi_rlast(file, buf, active_index);
1403
1557
  table->status=error ? STATUS_NOT_FOUND: 0;
1404
1558
  return error;
1405
1559
}
1406
1560
 
1407
 
int ha_myisam::index_next_same(unsigned char *buf,
1408
 
                               const unsigned char *key __attribute__((unused)),
1409
 
                               uint32_t length __attribute__((unused)))
 
1561
int ha_myisam::index_next_same(uchar *buf,
 
1562
                               const uchar *key __attribute__((unused)),
 
1563
                               uint length __attribute__((unused)))
1410
1564
{
1411
1565
  int error;
1412
 
  assert(inited==INDEX);
 
1566
  DBUG_ASSERT(inited==INDEX);
1413
1567
  ha_statistic_increment(&SSV::ha_read_next_count);
1414
1568
  do
1415
1569
  {
1426
1580
{
1427
1581
  int res;
1428
1582
  //if (!eq_range_arg)
1429
 
  //  in_range_read= true;
 
1583
  //  in_range_read= TRUE;
1430
1584
 
1431
1585
  res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
1432
1586
 
1433
1587
  //if (res)
1434
 
  //  in_range_read= false;
 
1588
  //  in_range_read= FALSE;
1435
1589
  return res;
1436
1590
}
1437
1591
 
1440
1594
{
1441
1595
  int res= handler::read_range_next();
1442
1596
  //if (res)
1443
 
  //  in_range_read= false;
 
1597
  //  in_range_read= FALSE;
1444
1598
  return res;
1445
1599
}
1446
1600
 
1452
1606
  return mi_reset(file);                        // Free buffers
1453
1607
}
1454
1608
 
1455
 
int ha_myisam::rnd_next(unsigned char *buf)
 
1609
int ha_myisam::rnd_next(uchar *buf)
1456
1610
{
1457
1611
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1458
1612
  int error=mi_scan(file, buf);
1460
1614
  return error;
1461
1615
}
1462
1616
 
1463
 
int ha_myisam::restart_rnd_next(unsigned char *buf, unsigned char *pos)
 
1617
int ha_myisam::restart_rnd_next(uchar *buf, uchar *pos)
1464
1618
{
1465
1619
  return rnd_pos(buf,pos);
1466
1620
}
1467
1621
 
1468
 
int ha_myisam::rnd_pos(unsigned char *buf, unsigned char *pos)
 
1622
int ha_myisam::rnd_pos(uchar *buf, uchar *pos)
1469
1623
{
1470
1624
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1471
1625
  int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
1474
1628
}
1475
1629
 
1476
1630
 
1477
 
void ha_myisam::position(const unsigned char *record __attribute__((unused)))
 
1631
void ha_myisam::position(const uchar *record)
1478
1632
{
1479
1633
  my_off_t row_position= mi_position(file);
1480
1634
  my_store_ptr(ref, ref_length, row_position);
1481
1635
}
1482
1636
 
1483
 
int ha_myisam::info(uint32_t flag)
 
1637
int ha_myisam::info(uint flag)
1484
1638
{
1485
1639
  MI_ISAMINFO misam_info;
1486
1640
  char name_buff[FN_REFLEN];
1514
1668
    share->keys_for_keyread.intersect(share->keys_in_use);
1515
1669
    share->db_record_offset= misam_info.record_offset;
1516
1670
    if (share->key_parts)
1517
 
      memcpy(table->key_info[0].rec_per_key,
1518
 
             misam_info.rec_per_key,
 
1671
      memcpy((char*) table->key_info[0].rec_per_key,
 
1672
             (char*) misam_info.rec_per_key,
1519
1673
             sizeof(table->key_info[0].rec_per_key)*share->key_parts);
1520
1674
    if (share->tmp_table == NO_TMP_TABLE)
1521
1675
      pthread_mutex_unlock(&share->mutex);
1550
1704
 
1551
1705
int ha_myisam::extra(enum ha_extra_function operation)
1552
1706
{
 
1707
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD)
 
1708
    return 0;
1553
1709
  return mi_extra(file, operation, 0);
1554
1710
}
1555
1711
 
1564
1720
 
1565
1721
/* To be used with WRITE_CACHE and EXTRA_CACHE */
1566
1722
 
1567
 
int ha_myisam::extra_opt(enum ha_extra_function operation, uint32_t cache_size)
 
1723
int ha_myisam::extra_opt(enum ha_extra_function operation, ulong cache_size)
1568
1724
{
 
1725
  if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
 
1726
    return 0;
1569
1727
  return mi_extra(file, operation, (void*) &cache_size);
1570
1728
}
1571
1729
 
1588
1746
                                       F_UNLCK : F_EXTRA_LCK));
1589
1747
}
1590
1748
 
1591
 
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
 
1749
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd,
1592
1750
                                      THR_LOCK_DATA **to,
1593
1751
                                      enum thr_lock_type lock_type)
1594
1752
{
1610
1768
}
1611
1769
 
1612
1770
 
1613
 
int ha_myisam::create(const char *name, register Table *table_arg,
 
1771
int ha_myisam::create(const char *name, register TABLE *table_arg,
1614
1772
                      HA_CREATE_INFO *ha_create_info)
1615
1773
{
1616
1774
  int error;
1617
 
  uint32_t create_flags= 0, records;
 
1775
  uint create_flags= 0, records, i;
1618
1776
  char buff[FN_REFLEN];
1619
1777
  MI_KEYDEF *keydef;
1620
1778
  MI_COLUMNDEF *recinfo;
1621
1779
  MI_CREATE_INFO create_info;
1622
1780
  TABLE_SHARE *share= table_arg->s;
1623
 
  uint32_t options= share->db_options_in_use;
 
1781
  uint options= share->db_options_in_use;
 
1782
  DBUG_ENTER("ha_myisam::create");
 
1783
  for (i= 0; i < share->keys; i++)
 
1784
  {
 
1785
    if (table_arg->key_info[i].flags & HA_USES_PARSER)
 
1786
    {
 
1787
      create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
 
1788
      break;
 
1789
    }
 
1790
  }
1624
1791
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
1625
 
    return(error); /* purecov: inspected */
1626
 
  memset(&create_info, 0, sizeof(create_info));
 
1792
    DBUG_RETURN(error); /* purecov: inspected */
 
1793
  bzero((char*) &create_info, sizeof(create_info));
1627
1794
  create_info.max_rows= share->max_rows;
1628
1795
  create_info.reloc_rows= share->min_rows;
1629
1796
  create_info.with_auto_increment= share->next_number_key_offset == 0;
1654
1821
                   records, recinfo,
1655
1822
                   0, (MI_UNIQUEDEF*) 0,
1656
1823
                   &create_info, create_flags);
1657
 
  free((unsigned char*) recinfo);
1658
 
  return(error);
 
1824
  my_free((uchar*) recinfo, MYF(0));
 
1825
  DBUG_RETURN(error);
1659
1826
}
1660
1827
 
1661
1828
 
1665
1832
}
1666
1833
 
1667
1834
 
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)),
 
1835
void ha_myisam::get_auto_increment(uint64_t offset, uint64_t increment,
 
1836
                                   uint64_t nb_desired_values,
1671
1837
                                   uint64_t *first_value,
1672
1838
                                   uint64_t *nb_reserved_values)
1673
1839
{
1674
1840
  uint64_t nr;
1675
1841
  int error;
1676
 
  unsigned char key[MI_MAX_KEY_LENGTH];
 
1842
  uchar key[MI_MAX_KEY_LENGTH];
1677
1843
 
1678
1844
  if (!table->s->next_number_key_offset)
1679
1845
  {                                             // Autoincrement at key-start
1680
1846
    ha_myisam::info(HA_STATUS_AUTO);
1681
1847
    *first_value= stats.auto_increment_value;
1682
1848
    /* MyISAM has only table-level lock, so reserves to +inf */
1683
 
    *nb_reserved_values= UINT64_MAX;
 
1849
    *nb_reserved_values= ULONGLONG_MAX;
1684
1850
    return;
1685
1851
  }
1686
1852
 
1739
1905
                        the range.
1740
1906
*/
1741
1907
 
1742
 
ha_rows ha_myisam::records_in_range(uint32_t inx, key_range *min_key,
 
1908
ha_rows ha_myisam::records_in_range(uint inx, key_range *min_key,
1743
1909
                                    key_range *max_key)
1744
1910
{
1745
1911
  return (ha_rows) mi_records_in_range(file, (int) inx, min_key, max_key);
1746
1912
}
1747
1913
 
1748
1914
 
1749
 
uint32_t ha_myisam::checksum() const
 
1915
int ha_myisam::ft_read(uchar *buf)
 
1916
{
 
1917
  int error;
 
1918
 
 
1919
  if (!ft_handler)
 
1920
    return -1;
 
1921
 
 
1922
  thread_safe_increment(table->in_use->status_var.ha_read_next_count,
 
1923
                        &LOCK_status); // why ?
 
1924
 
 
1925
  error=ft_handler->please->read_next(ft_handler,(char*) buf);
 
1926
 
 
1927
  table->status=error ? STATUS_NOT_FOUND: 0;
 
1928
  return error;
 
1929
}
 
1930
 
 
1931
uint ha_myisam::checksum() const
1750
1932
{
1751
1933
  return (uint)file->state->checksum;
1752
1934
}
1753
1935
 
1754
1936
 
1755
1937
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
1756
 
                                           uint32_t table_changes)
 
1938
                                           uint table_changes)
1757
1939
{
1758
 
  uint32_t options= table->s->db_options_in_use;
 
1940
  uint options= table->s->db_options_in_use;
1759
1941
 
1760
1942
  if (info->auto_increment_value != stats.auto_increment_value ||
1761
1943
      info->data_file_name != data_file_name ||
1772
1954
  return COMPATIBLE_DATA_YES;
1773
1955
}
1774
1956
 
1775
 
int myisam_deinit(void *hton __attribute__((unused)))
 
1957
extern int mi_panic(enum ha_panic_function flag);
 
1958
int myisam_panic(handlerton *hton, ha_panic_function flag)
1776
1959
{
1777
 
  return mi_panic(HA_PANIC_CLOSE);
 
1960
  return mi_panic(flag);
1778
1961
}
1779
1962
 
1780
1963
static int myisam_init(void *p)
1783
1966
 
1784
1967
  myisam_hton= (handlerton *)p;
1785
1968
  myisam_hton->state= SHOW_OPTION_YES;
 
1969
  myisam_hton->db_type= DB_TYPE_MYISAM;
1786
1970
  myisam_hton->create= myisam_create_handler;
 
1971
  myisam_hton->panic= myisam_panic;
1787
1972
  myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1788
1973
  return 0;
1789
1974
}
1795
1980
 ***************************************************************************/
1796
1981
 
1797
1982
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
1798
 
                                     uint32_t n_ranges, uint32_t mode, 
 
1983
                                     uint n_ranges, uint mode, 
1799
1984
                                     HANDLER_BUFFER *buf)
1800
1985
{
1801
1986
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index], 
1807
1992
  return ds_mrr.dsmrr_next(this, range_info);
1808
1993
}
1809
1994
 
1810
 
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
1995
ha_rows ha_myisam::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
1811
1996
                                               void *seq_init_param, 
1812
 
                                               uint32_t n_ranges, uint32_t *bufsz,
1813
 
                                               uint32_t *flags, COST_VECT *cost)
 
1997
                                               uint n_ranges, uint *bufsz,
 
1998
                                               uint *flags, COST_VECT *cost)
1814
1999
{
1815
2000
  /*
1816
2001
    This call is here because there is no location where this->table would
1822
2007
                                 flags, cost);
1823
2008
}
1824
2009
 
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)
 
2010
int ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
 
2011
                                     uint *bufsz, uint *flags, COST_VECT *cost)
1827
2012
{
1828
2013
  ds_mrr.init(this, table);
1829
2014
  return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
1835
2020
/* Index condition pushdown implementation*/
1836
2021
 
1837
2022
 
1838
 
Item *ha_myisam::idx_cond_push(uint32_t keyno_arg, Item* idx_cond_arg)
 
2023
Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
1839
2024
{
1840
2025
  pushed_idx_cond_keyno= keyno_arg;
1841
2026
  pushed_idx_cond= idx_cond_arg;
1842
 
  in_range_check_pushed_down= true;
 
2027
  in_range_check_pushed_down= TRUE;
1843
2028
  if (active_index == pushed_idx_cond_keyno)
1844
2029
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
1845
2030
  return NULL;
1846
2031
}
1847
2032
 
1848
2033
 
 
2034
struct st_mysql_storage_engine myisam_storage_engine=
 
2035
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
2036
 
1849
2037
mysql_declare_plugin(myisam)
1850
2038
{
1851
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
2039
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
2040
  &myisam_storage_engine,
1852
2041
  "MyISAM",
1853
 
  "1.0",
1854
2042
  "MySQL AB",
1855
2043
  "Default engine as of MySQL 3.23 with great performance",
1856
2044
  PLUGIN_LICENSE_GPL,
1857
2045
  myisam_init, /* Plugin Init */
1858
 
  myisam_deinit, /* Plugin Deinit */
 
2046
  NULL, /* Plugin Deinit */
 
2047
  0x0100, /* 1.0 */
1859
2048
  NULL,                       /* status variables                */
1860
2049
  NULL,                       /* system variables                */
1861
2050
  NULL                        /* config options                  */
1862
2051
}
1863
2052
mysql_declare_plugin_end;
 
2053
 
 
2054
 
 
2055
#ifdef HAVE_QUERY_CACHE
 
2056
/**
 
2057
  @brief Register a named table with a call back function to the query cache.
 
2058
 
 
2059
  @param thd The thread handle
 
2060
  @param table_key A pointer to the table name in the table cache
 
2061
  @param key_length The length of the table name
 
2062
  @param[out] engine_callback The pointer to the storage engine call back
 
2063
    function, currently 0
 
2064
  @param[out] engine_data Engine data will be set to 0.
 
2065
 
 
2066
  @note Despite the name of this function, it is used to check each statement
 
2067
    before it is cached and not to register a table or callback function.
 
2068
 
 
2069
  @see handler::register_query_cache_table
 
2070
 
 
2071
  @return The error code. The engine_data and engine_callback will be set to 0.
 
2072
    @retval TRUE Success
 
2073
    @retval FALSE An error occured
 
2074
*/
 
2075
 
 
2076
my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name,
 
2077
                                              uint table_name_len,
 
2078
                                              qc_engine_callback
 
2079
                                              *engine_callback,
 
2080
                                              uint64_t *engine_data)
 
2081
{
 
2082
  DBUG_ENTER("ha_myisam::register_query_cache_table");
 
2083
  /*
 
2084
    No call back function is needed to determine if a cached statement
 
2085
    is valid or not.
 
2086
  */
 
2087
  *engine_callback= 0;
 
2088
 
 
2089
  /*
 
2090
    No engine data is needed.
 
2091
  */
 
2092
  *engine_data= 0;
 
2093
 
 
2094
  if (file->s->concurrent_insert)
 
2095
  {
 
2096
    /*
 
2097
      If a concurrent INSERT has happened just before the currently
 
2098
      processed SELECT statement, the total size of the table is
 
2099
      unknown.
 
2100
 
 
2101
      To determine if the table size is known, the current thread's snap
 
2102
      shot of the table size with the actual table size are compared.
 
2103
 
 
2104
      If the table size is unknown the SELECT statement can't be cached.
 
2105
 
 
2106
      When concurrent inserts are disabled at table open, mi_open()
 
2107
      does not assign a get_status() function. In this case the local
 
2108
      ("current") status is never updated. We would wrongly think that
 
2109
      we cannot cache the statement.
 
2110
    */
 
2111
    uint64_t actual_data_file_length;
 
2112
    uint64_t current_data_file_length;
 
2113
 
 
2114
    /*
 
2115
      POSIX visibility rules specify that "2. Whatever memory values a
 
2116
      thread can see when it unlocks a mutex <...> can also be seen by any
 
2117
      thread that later locks the same mutex". In this particular case,
 
2118
      concurrent insert thread had modified the data_file_length in
 
2119
      MYISAM_SHARE before it has unlocked (or even locked)
 
2120
      structure_guard_mutex. So, here we're guaranteed to see at least that
 
2121
      value after we've locked the same mutex. We can see a later value
 
2122
      (modified by some other thread) though, but it's ok, as we only want
 
2123
      to know if the variable was changed, the actual new value doesn't matter
 
2124
    */
 
2125
    actual_data_file_length= file->s->state.state.data_file_length;
 
2126
    current_data_file_length= file->save_state.data_file_length;
 
2127
 
 
2128
    if (current_data_file_length != actual_data_file_length)
 
2129
    {
 
2130
      /* Don't cache current statement. */
 
2131
      DBUG_RETURN(FALSE);
 
2132
    }
 
2133
  }
 
2134
 
 
2135
  /* It is ok to try to cache current statement. */
 
2136
  DBUG_RETURN(TRUE);
 
2137
}
 
2138
#endif