16
16
/* Create a MyISAM table */
18
#include "myisam_priv.h"
19
#include "drizzled/internal/my_bit.h"
20
#include "drizzled/internal/my_sys.h"
22
#include "drizzled/util/test.h"
23
#include "drizzled/global_charset_info.h"
24
#include "drizzled/error.h"
30
using namespace drizzled;
18
#include "myisamdef.h"
22
#include <mysql/plugin.h>
33
28
Old options is used when recreating database, from myisamchk
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)
31
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
32
uint columns, MI_COLUMNDEF *recinfo,
33
uint uniques, MI_UNIQUEDEF *uniquedefs,
34
MI_CREATE_INFO *ci,uint flags)
41
register uint32_t i, j;
42
int dfile= 0, file= 0;
43
38
int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
45
uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
40
uint fields,length,max_key_length,packed,pointer,real_length_diff,
46
41
key_length,info_length,key_segs,options,min_key_length_skip,
47
42
base_pos,long_varchar_count,varchar_length,
48
43
max_key_block_length,unique_key_parts,fulltext_keys,offset;
49
uint32_t aligned_key_start, block_length;
44
uint aligned_key_start, block_length;
50
45
ulong reclength, real_reclength,min_pack_length;
51
46
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
52
47
ulong pack_reclength;
53
uint64_t tot_length,max_rows, tmp;
48
ulonglong tot_length,max_rows, tmp;
54
49
enum en_fieldtype type;
55
50
MYISAM_SHARE share;
56
51
MI_KEYDEF *keydef,tmp_keydef;
58
53
HA_KEYSEG *keyseg,tmp_keyseg;
60
55
ulong *rec_per_key_part;
61
internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
56
my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
62
57
MI_CREATE_INFO tmp_create_info;
58
DBUG_ENTER("mi_create");
59
DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u",
60
keys, columns, uniques, flags));
66
memset(&tmp_create_info, 0, sizeof(tmp_create_info));
64
bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
67
65
ci=&tmp_create_info;
70
68
if (keys + uniques > MI_MAX_KEY || columns == 0)
72
return(errno=HA_WRONG_CREATE_OPTION);
70
DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
76
memset(&share, 0, sizeof(share));
74
bzero((uchar*) &share,sizeof(share));
78
76
if (flags & HA_DONT_TOUCH_DATA)
80
78
if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
81
79
options=ci->old_options &
82
80
(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
83
HA_OPTION_READ_ONLY_DATA |
84
HA_OPTION_TMP_TABLE );
81
HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
82
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
86
84
options=ci->old_options &
87
(HA_OPTION_TMP_TABLE );
85
(HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
90
88
if (ci->reloc_rows > ci->max_rows)
91
89
ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
93
91
if (!(rec_per_key_part=
94
(ulong*) malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long))))
96
memset(rec_per_key_part, 0, (keys + uniques)*MI_MAX_KEY_SEG*sizeof(long));
92
(ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long),
93
MYF(MY_WME | MY_ZEROFILL))))
94
DBUG_RETURN(my_errno);
98
96
/* Start by checking fields and field-types used */
170
168
if (packed || (flags & HA_PACK_RECORD))
171
169
options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
170
/* We can't use checksum with static length rows */
171
if (!(options & HA_OPTION_PACK_RECORD))
172
options&= ~HA_OPTION_CHECKSUM;
172
173
if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
173
174
min_pack_length+= varchar_length;
174
175
if (flags & HA_CREATE_TMP_TABLE)
176
177
options|= HA_OPTION_TMP_TABLE;
177
create_mode|= O_EXCL;
178
create_mode|= O_EXCL | O_NOFOLLOW;
180
if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
182
options|= HA_OPTION_CHECKSUM;
185
if (flags & HA_CREATE_DELAY_KEY_WRITE)
186
options|= HA_OPTION_DELAY_KEY_WRITE;
187
if (flags & HA_CREATE_RELIES_ON_SQL_LAYER)
188
options|= HA_OPTION_RELIES_ON_SQL_LAYER;
180
190
packed=(packed+7)/8;
181
if (pack_reclength != INT32_MAX)
191
if (pack_reclength != INT_MAX32)
182
192
pack_reclength+= reclength+packed +
183
test(test_all_bits(options,
184
uint32_t(HA_PACK_RECORD)));
193
test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
185
194
min_pack_length+=packed;
187
196
if (!ci->data_file_length && ci->max_rows)
189
if (pack_reclength == INT32_MAX ||
190
(~(uint64_t) 0)/ci->max_rows < (uint64_t) pack_reclength)
191
ci->data_file_length= ~(uint64_t) 0;
198
if (pack_reclength == INT_MAX32 ||
199
(~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
200
ci->data_file_length= ~(ulonglong) 0;
193
ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
202
ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
195
204
else if (!ci->max_rows)
196
205
ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
200
209
if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
201
pointer=mi_get_pointer_length(ci->data_file_length, data_pointer_size);
210
pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
203
pointer=mi_get_pointer_length(ci->max_rows, data_pointer_size);
204
if (!(max_rows=(uint64_t) ci->max_rows))
205
max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
212
pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
213
if (!(max_rows=(ulonglong) ci->max_rows))
214
max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
208
217
real_reclength=reclength;
337
357
share.state.rec_per_key_part[key_segs-1]=1L;
338
358
length+=key_length;
339
359
/* Get block length for key, if defined by user */
340
block_length= (keydef->block_length ?
360
block_length= (keydef->block_length ?
341
361
my_round_up_to_next_power(keydef->block_length) :
342
362
myisam_block_size);
343
block_length= max(block_length, (uint32_t)MI_MIN_KEY_BLOCK_LENGTH);
344
block_length= min(block_length, (uint32_t)MI_MAX_KEY_BLOCK_LENGTH);
363
block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
364
block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
346
keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
366
keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
347
367
pointer,MI_MAX_KEYPTR_SIZE,
349
369
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
350
370
length >= MI_MAX_KEY_BUFF)
352
errno=HA_WRONG_CREATE_OPTION;
372
my_errno=HA_WRONG_CREATE_OPTION;
355
set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
356
keydef->keylength= (uint16_t) key_length;
357
keydef->minlength= (uint16_t) (length-min_key_length_skip);
358
keydef->maxlength= (uint16_t) length;
375
set_if_bigger(max_key_block_length,keydef->block_length);
376
keydef->keylength= (uint16) key_length;
377
keydef->minlength= (uint16) (length-min_key_length_skip);
378
keydef->maxlength= (uint16) length;
360
380
if (length > max_key_length)
361
381
max_key_length= length;
389
409
uniques * MI_UNIQUEDEF_SIZE +
390
410
(key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
391
411
columns*MI_COLUMNDEF_SIZE);
412
DBUG_PRINT("info", ("info_length: %u", info_length));
392
413
/* There are only 16 bits for the total header length. */
393
414
if (info_length > 65535)
395
416
my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
396
417
"indexes and/or unique constraints.",
397
MYF(0), name + internal::dirname_length(name));
398
errno= HA_WRONG_CREATE_OPTION;
418
MYF(0), name + dirname_length(name));
419
my_errno= HA_WRONG_CREATE_OPTION;
402
memmove(share.state.header.file_version,myisam_file_magic,4);
423
bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
403
424
ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
404
425
HA_OPTION_COMPRESS_RECORD |
405
426
HA_OPTION_TEMP_COMPRESS_RECORD: 0);
458
479
/* max_data_file_length and max_key_file_length are recalculated on open */
459
480
if (options & HA_OPTION_TMP_TABLE)
460
share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
481
share.base.max_data_file_length=(my_off_t) ci->data_file_length;
462
483
share.base.min_block_length=
463
484
(share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
464
485
! share.base.blobs) ?
465
max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
486
max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
466
487
MI_EXTEND_BLOCK_LENGTH;
467
488
if (! (flags & HA_DONT_TOUCH_DATA))
468
489
share.state.create_time= (long) time((time_t*) 0);
470
THR_LOCK_myisam.lock();
491
pthread_mutex_lock(&THR_LOCK_myisam);
473
494
NOTE: For test_if_reopen() we need a real path name. Hence we need
474
MY_RETURN_REAL_PATH for every internal::fn_format(filename, ...).
495
MY_RETURN_REAL_PATH for every fn_format(filename, ...).
476
497
if (ci->index_file_name)
478
char *iext= strrchr((char *)ci->index_file_name, '.');
499
char *iext= strrchr(ci->index_file_name, '.');
479
500
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
480
501
if (options & HA_OPTION_TMP_TABLE)
483
504
/* chop off the table name, tempory tables use generated name */
484
if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
505
if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
486
internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
507
fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
487
508
MY_REPLACE_DIR | MY_UNPACK_FILENAME |
488
509
MY_RETURN_REAL_PATH | MY_APPEND_EXT);
492
internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
513
fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
493
514
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
494
515
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
496
internal::fn_format(linkname, name, "", MI_NAME_IEXT,
517
fn_format(linkname, name, "", MI_NAME_IEXT,
497
518
MY_UNPACK_FILENAME|MY_APPEND_EXT);
498
519
linkname_ptr=linkname;
507
char *iext= strrchr((char *)name, '.');
528
char *iext= strrchr(name, '.');
508
529
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
509
internal::fn_format(filename, name, "", MI_NAME_IEXT,
530
fn_format(filename, name, "", MI_NAME_IEXT,
510
531
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
511
532
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
529
550
my_printf_error(0, "MyISAM table '%s' is in use "
530
551
"(most likely by a MERGE table). Try FLUSH TABLES.",
531
MYF(0), name + internal::dirname_length(name));
532
errno= HA_ERR_TABLE_EXIST;
552
MYF(0), name + dirname_length(name));
553
my_errno= HA_ERR_TABLE_EXIST;
536
if ((file= internal::my_create_with_symlink(linkname_ptr,
540
MYF(MY_WME | create_flag))) < 0)
557
if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
558
MYF(MY_WME | create_flag))) < 0)
547
565
if (ci->data_file_name)
549
char *dext= strrchr((char *)ci->data_file_name, '.');
567
char *dext= strrchr(ci->data_file_name, '.');
550
568
int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
552
570
if (options & HA_OPTION_TMP_TABLE)
555
573
/* chop off the table name, tempory tables use generated name */
556
if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
574
if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
558
internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
576
fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
559
577
MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
563
internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
581
fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
564
582
MY_UNPACK_FILENAME |
565
583
(have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
568
internal::fn_format(linkname, name, "",MI_NAME_DEXT,
586
fn_format(linkname, name, "",MI_NAME_DEXT,
569
587
MY_UNPACK_FILENAME | MY_APPEND_EXT);
570
588
linkname_ptr=linkname;
575
internal::fn_format(filename,name,"", MI_NAME_DEXT,
593
fn_format(filename,name,"", MI_NAME_DEXT,
576
594
MY_UNPACK_FILENAME | MY_APPEND_EXT);
578
596
create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
580
if ((dfile= internal::my_create_with_symlink(linkname_ptr,
581
filename, 0, create_mode,
582
MYF(MY_WME | create_flag))) < 0)
599
my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
600
MYF(MY_WME | create_flag))) < 0)
606
DBUG_PRINT("info", ("write state info and base info"));
588
607
if (mi_state_info_write(file, &share.state, 2) ||
589
608
mi_base_info_write(file, &share.base))
611
if ((uint) my_tell(file,MYF(0)) != base_pos+ MI_BASE_INFO_SIZE)
613
uint pos=(uint) my_tell(file,MYF(0));
614
DBUG_PRINT("warning",("base_length: %d != used_length: %d",
615
base_pos+ MI_BASE_INFO_SIZE, pos));
592
619
/* Write key and keyseg definitions */
620
DBUG_PRINT("info", ("write key and keyseg definitions"));
593
621
for (i=0 ; i < share.base.keys - uniques; i++)
597
625
if (mi_keydef_write(file, &keydefs[i]))
603
631
/* Create extra keys for unique definitions */
604
632
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
605
memset(&tmp_keydef, 0, sizeof(tmp_keydef));
606
memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
633
bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
634
bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
607
635
for (i=0; i < uniques ; i++)
609
637
tmp_keydef.keysegs=1;
610
638
tmp_keydef.flag= HA_UNIQUE_CHECK;
611
tmp_keydef.block_length= (uint16_t)myisam_block_size;
639
tmp_keydef.block_length= (uint16)myisam_block_size;
612
640
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
613
641
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
614
642
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
683
DBUG_PRINT("info", ("write field definitions"));
654
684
for (i=0 ; i < share.base.fields ; i++)
655
685
if (mi_recinfo_write(file, &recinfo[i]))
689
if ((uint) my_tell(file,MYF(0)) != info_length)
691
uint pos= (uint) my_tell(file,MYF(0));
692
DBUG_PRINT("warning",("info_length: %d != used_length: %d",
658
697
/* Enlarge files */
698
DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
659
699
if (ftruncate(file, (off_t) share.base.keystart))
669
if (internal::my_close(dfile,MYF(0)))
709
if (my_close(dfile,MYF(0)))
673
THR_LOCK_myisam.unlock();
674
if (internal::my_close(file,MYF(0)))
713
pthread_mutex_unlock(&THR_LOCK_myisam);
714
if (my_close(file,MYF(0)))
676
free((char*) rec_per_key_part);
716
my_free((char*) rec_per_key_part,MYF(0));
680
THR_LOCK_myisam.unlock();
720
pthread_mutex_unlock(&THR_LOCK_myisam);
682
722
switch (errpos) {
684
internal::my_close(dfile,MYF(0));
724
VOID(my_close(dfile,MYF(0)));
685
725
/* fall through */
727
/* QQ: T�nu should add a call to my_raid_delete() here */
687
728
if (! (flags & HA_DONT_TOUCH_DATA))
688
internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
729
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,
689
730
MY_UNPACK_FILENAME | MY_APPEND_EXT),
691
732
/* fall through */
693
internal::my_close(file,MYF(0));
734
VOID(my_close(file,MYF(0)));
694
735
if (! (flags & HA_DONT_TOUCH_DATA))
695
internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
736
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,
696
737
MY_UNPACK_FILENAME | MY_APPEND_EXT),
699
free((char*) rec_per_key_part);
700
return(errno=save_errno); /* return the fatal errno */
740
my_free((char*) rec_per_key_part, MYF(0));
741
DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */
704
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
745
uint mi_get_pointer_length(ulonglong file_length, uint def)
706
assert(def >= 2 && def <= 7);
747
DBUG_ASSERT(def >= 2 && def <= 7);
707
748
if (file_length) /* If not default */
709
750
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS