16
16
/* Create a MyISAM table */
18
18
#include "myisamdef.h"
19
#include <mysys/my_tree.h>
20
#include <mysys/queues.h>
21
#include <mysys/my_bit.h>
22
#include <mysql/plugin.h>
23
#include <drizzled/util/test.h>
26
28
Old options is used when recreating database, from myisamchk
29
int mi_create(const char *name,uint32_t keys,MI_KEYDEF *keydefs,
30
uint32_t columns, MI_COLUMNDEF *recinfo,
31
uint32_t uniques, MI_UNIQUEDEF *uniquedefs,
32
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)
34
register uint32_t i, j;
35
File dfile= 0, file= 0;
36
38
int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
38
uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
40
uint fields,length,max_key_length,packed,pointer,real_length_diff,
39
41
key_length,info_length,key_segs,options,min_key_length_skip,
40
42
base_pos,long_varchar_count,varchar_length,
41
43
max_key_block_length,unique_key_parts,fulltext_keys,offset;
42
uint32_t aligned_key_start, block_length;
44
uint aligned_key_start, block_length;
43
45
ulong reclength, real_reclength,min_pack_length;
44
46
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
45
47
ulong pack_reclength;
46
uint64_t tot_length,max_rows, tmp;
48
ulonglong tot_length,max_rows, tmp;
47
49
enum en_fieldtype type;
48
50
MYISAM_SHARE share;
49
51
MI_KEYDEF *keydef,tmp_keydef;
53
55
ulong *rec_per_key_part;
54
56
my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
55
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));
59
memset(&tmp_create_info, 0, sizeof(tmp_create_info));
64
bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
60
65
ci=&tmp_create_info;
63
68
if (keys + uniques > MI_MAX_KEY || columns == 0)
65
return(my_errno=HA_WRONG_CREATE_OPTION);
70
DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
69
memset(&share, 0, sizeof(share));
74
bzero((uchar*) &share,sizeof(share));
71
76
if (flags & HA_DONT_TOUCH_DATA)
183
188
options|= HA_OPTION_RELIES_ON_SQL_LAYER;
185
190
packed=(packed+7)/8;
186
if (pack_reclength != INT32_MAX)
191
if (pack_reclength != INT_MAX32)
187
192
pack_reclength+= reclength+packed +
188
193
test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
189
194
min_pack_length+=packed;
191
196
if (!ci->data_file_length && ci->max_rows)
193
if (pack_reclength == INT32_MAX ||
194
(~(uint64_t) 0)/ci->max_rows < (uint64_t) pack_reclength)
195
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;
197
ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
202
ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
199
204
else if (!ci->max_rows)
200
205
ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
205
210
pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
207
212
pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
208
if (!(max_rows=(uint64_t) ci->max_rows))
209
max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
213
if (!(max_rows=(ulonglong) ci->max_rows))
214
max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
212
217
real_reclength=reclength;
315
320
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
317
assert(!test_all_bits(keyseg->flag,
322
DBUG_ASSERT(!test_all_bits(keyseg->flag,
318
323
(HA_VAR_LENGTH_PART | HA_BLOB_PART)));
319
324
keydef->flag|=HA_VAR_LENGTH_KEY;
320
325
length++; /* At least one length byte */
355
360
block_length= (keydef->block_length ?
356
361
my_round_up_to_next_power(keydef->block_length) :
357
362
myisam_block_size);
358
block_length= cmax(block_length, MI_MIN_KEY_BLOCK_LENGTH);
359
block_length= cmin(block_length, 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);
361
keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
366
keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
362
367
pointer,MI_MAX_KEYPTR_SIZE,
364
369
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
370
375
set_if_bigger(max_key_block_length,keydef->block_length);
371
keydef->keylength= (uint16_t) key_length;
372
keydef->minlength= (uint16_t) (length-min_key_length_skip);
373
keydef->maxlength= (uint16_t) length;
376
keydef->keylength= (uint16) key_length;
377
keydef->minlength= (uint16) (length-min_key_length_skip);
378
keydef->maxlength= (uint16) length;
375
380
if (length > max_key_length)
376
381
max_key_length= length;
417
memcpy(share.state.header.file_version,myisam_file_magic,4);
423
bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
418
424
ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
419
425
HA_OPTION_COMPRESS_RECORD |
420
426
HA_OPTION_TEMP_COMPRESS_RECORD: 0);
432
438
share.state.unique= (ulong) 0;
433
439
share.state.update_count=(ulong) 0;
434
440
share.state.version= (ulong) time((time_t*) 0);
435
share.state.sortkey= UINT16_MAX;
441
share.state.sortkey= (ushort) ~0;
436
442
share.state.auto_increment=ci->auto_increment;
437
443
share.options=options;
438
444
share.base.rec_reflength=pointer;
444
450
got from MYI file header (see also myisampack.c:save_state)
446
452
share.base.key_reflength=
447
mi_get_pointer_length(cmax(ci->key_file_length,tmp),3);
453
mi_get_pointer_length(max(ci->key_file_length,tmp),3);
448
454
share.base.keys= share.state.header.keys= keys;
449
455
share.state.header.uniques= uniques;
450
456
share.state.header.fulltext_keys= fulltext_keys;
477
483
share.base.min_block_length=
478
484
(share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
479
485
! share.base.blobs) ?
480
cmax(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
486
max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
481
487
MI_EXTEND_BLOCK_LENGTH;
482
488
if (! (flags & HA_DONT_TOUCH_DATA))
483
489
share.state.create_time= (long) time((time_t*) 0);
606
DBUG_PRINT("info", ("write state info and base info"));
600
607
if (mi_state_info_write(file, &share.state, 2) ||
601
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));
604
619
/* Write key and keyseg definitions */
620
DBUG_PRINT("info", ("write key and keyseg definitions"));
605
621
for (i=0 ; i < share.base.keys - uniques; i++)
609
625
if (mi_keydef_write(file, &keydefs[i]))
615
631
/* Create extra keys for unique definitions */
616
632
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
617
memset(&tmp_keydef, 0, sizeof(tmp_keydef));
618
memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
633
bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
634
bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
619
635
for (i=0; i < uniques ; i++)
621
637
tmp_keydef.keysegs=1;
622
638
tmp_keydef.flag= HA_UNIQUE_CHECK;
623
tmp_keydef.block_length= (uint16_t)myisam_block_size;
639
tmp_keydef.block_length= (uint16)myisam_block_size;
624
640
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
625
641
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
626
642
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
683
DBUG_PRINT("info", ("write field definitions"));
666
684
for (i=0 ; i < share.base.fields ; i++)
667
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",
670
697
/* Enlarge files */
698
DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
671
699
if (ftruncate(file, (off_t) share.base.keystart))
685
713
pthread_mutex_unlock(&THR_LOCK_myisam);
686
714
if (my_close(file,MYF(0)))
688
free((char*) rec_per_key_part);
716
my_free((char*) rec_per_key_part,MYF(0));
692
720
pthread_mutex_unlock(&THR_LOCK_myisam);
693
721
save_errno=my_errno;
694
722
switch (errpos) {
696
my_close(dfile,MYF(0));
724
VOID(my_close(dfile,MYF(0)));
697
725
/* fall through */
727
/* QQ: T�nu should add a call to my_raid_delete() here */
699
728
if (! (flags & HA_DONT_TOUCH_DATA))
700
729
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,
701
730
MY_UNPACK_FILENAME | MY_APPEND_EXT),
703
732
/* fall through */
705
my_close(file,MYF(0));
734
VOID(my_close(file,MYF(0)));
706
735
if (! (flags & HA_DONT_TOUCH_DATA))
707
736
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,
708
737
MY_UNPACK_FILENAME | MY_APPEND_EXT),
711
free((char*) rec_per_key_part);
712
return(my_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 */
716
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
745
uint mi_get_pointer_length(ulonglong file_length, uint def)
718
assert(def >= 2 && def <= 7);
747
DBUG_ASSERT(def >= 2 && def <= 7);
719
748
if (file_length) /* If not default */
721
750
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS