~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_create.c

Cleanup around SAFEMALLOC

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* Create a MyISAM table */
17
17
 
18
 
#include "myisam_priv.h"
19
 
#include "drizzled/internal/my_bit.h"
20
 
#include "drizzled/internal/my_sys.h"
21
 
 
22
 
#include "drizzled/util/test.h"
23
 
#include "drizzled/global_charset_info.h"
24
 
#include "drizzled/error.h"
25
 
 
26
 
#include <cassert>
27
 
#include <algorithm>
28
 
 
29
 
using namespace std;
30
 
using namespace drizzled;
 
18
#include "myisamdef.h"
 
19
#include <mysys/my_tree.h>
 
20
#include <mysys/queues.h>
 
21
#include <mysys/my_bit.h>
 
22
 
31
23
 
32
24
/*
33
25
  Old options is used when recreating database, from myisamchk
34
26
*/
35
27
 
36
 
int mi_create(const char *name,uint32_t keys,MI_KEYDEF *keydefs,
37
 
              uint32_t columns, MI_COLUMNDEF *recinfo,
38
 
              uint32_t uniques, MI_UNIQUEDEF *uniquedefs,
39
 
              MI_CREATE_INFO *ci,uint32_t flags)
 
28
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
 
29
              uint columns, MI_COLUMNDEF *recinfo,
 
30
              uint uniques, MI_UNIQUEDEF *uniquedefs,
 
31
              MI_CREATE_INFO *ci,uint flags)
40
32
{
41
 
  register uint32_t i, j;
42
 
  int dfile= 0, file= 0;
 
33
  register uint i, j;
 
34
  File dfile= 0, file= 0;
43
35
  int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
44
36
  myf create_flag;
45
 
  uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
 
37
  uint fields,length,max_key_length,packed,pointer,real_length_diff,
46
38
       key_length,info_length,key_segs,options,min_key_length_skip,
47
39
       base_pos,long_varchar_count,varchar_length,
48
40
       max_key_block_length,unique_key_parts,fulltext_keys,offset;
49
 
  uint32_t aligned_key_start, block_length;
 
41
  uint aligned_key_start, block_length;
50
42
  ulong reclength, real_reclength,min_pack_length;
51
43
  char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
52
44
  ulong pack_reclength;
58
50
  HA_KEYSEG *keyseg,tmp_keyseg;
59
51
  MI_COLUMNDEF *rec;
60
52
  ulong *rec_per_key_part;
61
 
  internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
 
53
  my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
62
54
  MI_CREATE_INFO tmp_create_info;
63
55
 
64
56
  if (!ci)
69
61
 
70
62
  if (keys + uniques > MI_MAX_KEY || columns == 0)
71
63
  {
72
 
    return(errno=HA_WRONG_CREATE_OPTION);
 
64
    return(my_errno=HA_WRONG_CREATE_OPTION);
73
65
  }
74
66
  errpos= 0;
75
67
  options= 0;
80
72
    if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
81
73
      options=ci->old_options &
82
74
        (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
83
 
         HA_OPTION_READ_ONLY_DATA |
84
 
         HA_OPTION_TMP_TABLE );
 
75
         HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
 
76
         HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
85
77
    else
86
78
      options=ci->old_options &
87
 
        (HA_OPTION_TMP_TABLE );
 
79
        (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
88
80
  }
89
81
 
90
82
  if (ci->reloc_rows > ci->max_rows)
91
83
    ci->reloc_rows=ci->max_rows;                /* Check if wrong parameter */
92
84
 
93
85
  if (!(rec_per_key_part=
94
 
        (ulong*) malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long))))
95
 
    return(errno);
96
 
  memset(rec_per_key_part, 0, (keys + uniques)*MI_MAX_KEY_SEG*sizeof(long));
 
86
        (ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long),
 
87
                           MYF(MY_WME | MY_ZEROFILL))))
 
88
    return(my_errno);
97
89
 
98
90
        /* Start by checking fields and field-types used */
99
91
 
169
161
 
170
162
  if (packed || (flags & HA_PACK_RECORD))
171
163
    options|=HA_OPTION_PACK_RECORD;     /* Must use packed records */
 
164
  /* We can't use checksum with static length rows */
 
165
  if (!(options & HA_OPTION_PACK_RECORD))
 
166
    options&= ~HA_OPTION_CHECKSUM;
172
167
  if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
173
168
    min_pack_length+= varchar_length;
174
169
  if (flags & HA_CREATE_TMP_TABLE)
175
170
  {
176
171
    options|= HA_OPTION_TMP_TABLE;
177
 
    create_mode|= O_EXCL;
178
 
  }
 
172
    create_mode|= O_EXCL | O_NOFOLLOW;
 
173
  }
 
174
  if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
 
175
  {
 
176
    options|= HA_OPTION_CHECKSUM;
 
177
    min_pack_length++;
 
178
  }
 
179
  if (flags & HA_CREATE_DELAY_KEY_WRITE)
 
180
    options|= HA_OPTION_DELAY_KEY_WRITE;
 
181
  if (flags & HA_CREATE_RELIES_ON_SQL_LAYER)
 
182
    options|= HA_OPTION_RELIES_ON_SQL_LAYER;
179
183
 
180
184
  packed=(packed+7)/8;
181
185
  if (pack_reclength != INT32_MAX)
182
186
    pack_reclength+= reclength+packed +
183
 
      test(test_all_bits(options,
184
 
                         uint32_t(HA_PACK_RECORD)));
 
187
      test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
185
188
  min_pack_length+=packed;
186
189
 
187
190
  if (!ci->data_file_length && ci->max_rows)
198
201
                                          3 : 0)));
199
202
 
200
203
  if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
201
 
    pointer=mi_get_pointer_length(ci->data_file_length, data_pointer_size);
 
204
    pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
202
205
  else
203
 
    pointer=mi_get_pointer_length(ci->max_rows, data_pointer_size);
 
206
    pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
204
207
  if (!(max_rows=(uint64_t) ci->max_rows))
205
208
    max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
206
209
 
236
239
      /* Test if prefix compression */
237
240
      if (keydef->flag & HA_PACK_KEY)
238
241
      {
 
242
        /* Can't use space_compression on number keys */
 
243
        if ((keydef->seg[0].flag & HA_SPACE_PACK) &&
 
244
            keydef->seg[0].type == (int) HA_KEYTYPE_NUM)
 
245
          keydef->seg[0].flag&= ~HA_SPACE_PACK;
 
246
 
239
247
        /* Only use HA_PACK_KEY when first segment is a variable length key */
240
248
        if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
241
249
                                     HA_VAR_LENGTH_PART)))
260
268
      {
261
269
        /* numbers are stored with high by first to make compression easier */
262
270
        switch (keyseg->type) {
 
271
        case HA_KEYTYPE_SHORT_INT:
263
272
        case HA_KEYTYPE_LONG_INT:
 
273
        case HA_KEYTYPE_FLOAT:
264
274
        case HA_KEYTYPE_DOUBLE:
 
275
        case HA_KEYTYPE_USHORT_INT:
265
276
        case HA_KEYTYPE_ULONG_INT:
266
277
        case HA_KEYTYPE_LONGLONG:
267
278
        case HA_KEYTYPE_ULONGLONG:
 
279
        case HA_KEYTYPE_INT24:
268
280
        case HA_KEYTYPE_UINT24:
 
281
        case HA_KEYTYPE_INT8:
269
282
          keyseg->flag|= HA_SWAP_KEY;
270
283
          break;
271
284
        case HA_KEYTYPE_VARTEXT1:
325
338
    key_segs+=keydef->keysegs;
326
339
    if (keydef->keysegs > MI_MAX_KEY_SEG)
327
340
    {
328
 
      errno=HA_WRONG_CREATE_OPTION;
 
341
      my_errno=HA_WRONG_CREATE_OPTION;
329
342
      goto err;
330
343
    }
331
344
    /*
338
351
      share.state.rec_per_key_part[key_segs-1]=1L;
339
352
    length+=key_length;
340
353
    /* Get block length for key, if defined by user */
341
 
    block_length= (keydef->block_length ?
 
354
    block_length= (keydef->block_length ? 
342
355
                   my_round_up_to_next_power(keydef->block_length) :
343
356
                   myisam_block_size);
344
 
    block_length= max(block_length, (uint32_t)MI_MIN_KEY_BLOCK_LENGTH);
345
 
    block_length= min(block_length, (uint32_t)MI_MAX_KEY_BLOCK_LENGTH);
 
357
    block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
 
358
    block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
346
359
 
347
360
    keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
348
361
                                                 pointer,MI_MAX_KEYPTR_SIZE,
350
363
    if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
351
364
        length >= MI_MAX_KEY_BUFF)
352
365
    {
353
 
      errno=HA_WRONG_CREATE_OPTION;
 
366
      my_errno=HA_WRONG_CREATE_OPTION;
354
367
      goto err;
355
368
    }
356
 
    set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
 
369
    set_if_bigger(max_key_block_length,keydef->block_length);
357
370
    keydef->keylength= (uint16_t) key_length;
358
371
    keydef->minlength= (uint16_t) (length-min_key_length_skip);
359
372
    keydef->maxlength= (uint16_t) length;
395
408
  {
396
409
    my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
397
410
                    "indexes and/or unique constraints.",
398
 
                    MYF(0), name + internal::dirname_length(name));
399
 
    errno= HA_WRONG_CREATE_OPTION;
 
411
                    MYF(0), name + dirname_length(name));
 
412
    my_errno= HA_WRONG_CREATE_OPTION;
400
413
    goto err;
401
414
  }
402
415
 
403
 
  memmove(share.state.header.file_version,myisam_file_magic,4);
 
416
  memcpy(share.state.header.file_version,myisam_file_magic,4);
404
417
  ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
405
418
                        HA_OPTION_COMPRESS_RECORD |
406
419
                        HA_OPTION_TEMP_COMPRESS_RECORD: 0);
449
462
  share.base.records=ci->max_rows;
450
463
  share.base.reloc=  ci->reloc_rows;
451
464
  share.base.reclength=real_reclength;
452
 
  share.base.pack_reclength=reclength;
 
465
  share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);
453
466
  share.base.max_pack_length=pack_reclength;
454
467
  share.base.min_pack_length=min_pack_length;
455
468
  share.base.pack_bits=packed;
458
471
 
459
472
  /* max_data_file_length and max_key_file_length are recalculated on open */
460
473
  if (options & HA_OPTION_TMP_TABLE)
461
 
    share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
 
474
    share.base.max_data_file_length=(my_off_t) ci->data_file_length;
462
475
 
463
476
  share.base.min_block_length=
464
477
    (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
465
478
     ! share.base.blobs) ?
466
 
    max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
 
479
    max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
467
480
    MI_EXTEND_BLOCK_LENGTH;
468
481
  if (! (flags & HA_DONT_TOUCH_DATA))
469
482
    share.state.create_time= (long) time((time_t*) 0);
472
485
 
473
486
  /*
474
487
    NOTE: For test_if_reopen() we need a real path name. Hence we need
475
 
    MY_RETURN_REAL_PATH for every internal::fn_format(filename, ...).
 
488
    MY_RETURN_REAL_PATH for every fn_format(filename, ...).
476
489
  */
477
490
  if (ci->index_file_name)
478
491
  {
479
 
    char *iext= strrchr((char *)ci->index_file_name, '.');
 
492
    char *iext= strrchr(ci->index_file_name, '.');
480
493
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
481
494
    if (options & HA_OPTION_TMP_TABLE)
482
495
    {
483
496
      char *path;
484
497
      /* chop off the table name, tempory tables use generated name */
485
 
      if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
 
498
      if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
486
499
        *path= '\0';
487
 
      internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
 
500
      fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
488
501
                MY_REPLACE_DIR | MY_UNPACK_FILENAME |
489
502
                MY_RETURN_REAL_PATH | MY_APPEND_EXT);
490
503
    }
491
504
    else
492
505
    {
493
 
      internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
 
506
      fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
494
507
                MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
495
508
                (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
496
509
    }
497
 
    internal::fn_format(linkname, name, "", MI_NAME_IEXT,
 
510
    fn_format(linkname, name, "", MI_NAME_IEXT,
498
511
              MY_UNPACK_FILENAME|MY_APPEND_EXT);
499
512
    linkname_ptr=linkname;
500
513
    /*
505
518
  }
506
519
  else
507
520
  {
508
 
    char *iext= strrchr((char *)name, '.');
 
521
    char *iext= strrchr(name, '.');
509
522
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
510
 
    internal::fn_format(filename, name, "", MI_NAME_IEXT,
 
523
    fn_format(filename, name, "", MI_NAME_IEXT,
511
524
              MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
512
525
              (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
513
526
    linkname_ptr=0;
529
542
  {
530
543
    my_printf_error(0, "MyISAM table '%s' is in use "
531
544
                    "(most likely by a MERGE table). Try FLUSH TABLES.",
532
 
                    MYF(0), name + internal::dirname_length(name));
533
 
    errno= HA_ERR_TABLE_EXIST;
 
545
                    MYF(0), name + dirname_length(name));
 
546
    my_errno= HA_ERR_TABLE_EXIST;
534
547
    goto err;
535
548
  }
536
549
 
537
 
  if ((file= internal::my_create_with_symlink(linkname_ptr,
538
 
                                              filename,
539
 
                                              0,
540
 
                                              create_mode,
541
 
                                              MYF(MY_WME | create_flag))) < 0)
 
550
  if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
 
551
                                    MYF(MY_WME | create_flag))) < 0)
542
552
    goto err;
543
553
  errpos=1;
544
554
 
547
557
    {
548
558
      if (ci->data_file_name)
549
559
      {
550
 
        char *dext= strrchr((char *)ci->data_file_name, '.');
 
560
        char *dext= strrchr(ci->data_file_name, '.');
551
561
        int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
552
562
 
553
563
        if (options & HA_OPTION_TMP_TABLE)
554
564
        {
555
565
          char *path;
556
566
          /* chop off the table name, tempory tables use generated name */
557
 
          if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
 
567
          if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
558
568
            *path= '\0';
559
 
          internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
 
569
          fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
560
570
                    MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
561
571
        }
562
572
        else
563
573
        {
564
 
          internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
 
574
          fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
565
575
                    MY_UNPACK_FILENAME |
566
576
                    (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
567
577
        }
568
578
 
569
 
        internal::fn_format(linkname, name, "",MI_NAME_DEXT,
 
579
        fn_format(linkname, name, "",MI_NAME_DEXT,
570
580
                  MY_UNPACK_FILENAME | MY_APPEND_EXT);
571
581
        linkname_ptr=linkname;
572
582
        create_flag=0;
573
583
      }
574
584
      else
575
585
      {
576
 
        internal::fn_format(filename,name,"", MI_NAME_DEXT,
 
586
        fn_format(filename,name,"", MI_NAME_DEXT,
577
587
                  MY_UNPACK_FILENAME | MY_APPEND_EXT);
578
588
        linkname_ptr=0;
579
589
        create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
580
590
      }
581
 
      if ((dfile= internal::my_create_with_symlink(linkname_ptr,
582
 
                                                   filename, 0, create_mode,
583
 
                                                   MYF(MY_WME | create_flag))) < 0)
 
591
      if ((dfile=
 
592
           my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
 
593
                                  MYF(MY_WME | create_flag))) < 0)
584
594
        goto err;
585
595
    }
586
596
    errpos=3;
593
603
  /* Write key and keyseg definitions */
594
604
  for (i=0 ; i < share.base.keys - uniques; i++)
595
605
  {
596
 
    uint32_t sp_segs= 0;
 
606
    uint sp_segs= 0;
597
607
 
598
608
    if (mi_keydef_write(file, &keydefs[i]))
599
609
      goto err;
667
677
      goto err;
668
678
#endif
669
679
    errpos=2;
670
 
    if (internal::my_close(dfile,MYF(0)))
 
680
    if (my_close(dfile,MYF(0)))
671
681
      goto err;
672
682
  }
673
683
  errpos=0;
674
684
  pthread_mutex_unlock(&THR_LOCK_myisam);
675
 
  if (internal::my_close(file,MYF(0)))
 
685
  if (my_close(file,MYF(0)))
676
686
    goto err;
677
 
  free((char*) rec_per_key_part);
 
687
  my_free((char*) rec_per_key_part,MYF(0));
678
688
  return(0);
679
689
 
680
690
err:
681
691
  pthread_mutex_unlock(&THR_LOCK_myisam);
682
 
  save_errno=errno;
 
692
  save_errno=my_errno;
683
693
  switch (errpos) {
684
694
  case 3:
685
 
    internal::my_close(dfile,MYF(0));
 
695
    VOID(my_close(dfile,MYF(0)));
686
696
    /* fall through */
687
697
  case 2:
 
698
    /* QQ: T�nu should add a call to my_raid_delete() here */
688
699
  if (! (flags & HA_DONT_TOUCH_DATA))
689
 
    internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
 
700
    my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,
690
701
                                     MY_UNPACK_FILENAME | MY_APPEND_EXT),
691
702
                           MYF(0));
692
703
    /* fall through */
693
704
  case 1:
694
 
    internal::my_close(file,MYF(0));
 
705
    VOID(my_close(file,MYF(0)));
695
706
    if (! (flags & HA_DONT_TOUCH_DATA))
696
 
      internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
 
707
      my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,
697
708
                                       MY_UNPACK_FILENAME | MY_APPEND_EXT),
698
709
                             MYF(0));
699
710
  }
700
 
  free((char*) rec_per_key_part);
701
 
  return(errno=save_errno);             /* return the fatal errno */
 
711
  my_free((char*) rec_per_key_part, MYF(0));
 
712
  return(my_errno=save_errno);          /* return the fatal errno */
702
713
}
703
714
 
704
715
 
705
 
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
 
716
uint mi_get_pointer_length(uint64_t file_length, uint def)
706
717
{
707
718
  assert(def >= 2 && def <= 7);
708
719
  if (file_length)                              /* If not default */