16
16
/* Create a MyISAM table */
18
#include "myisamdef.h"
19
#include <mysys/my_tree.h>
20
#include <mysys/queues.h>
21
#include <mysys/my_bit.h>
23
#include <drizzled/util/test.h>
22
#if defined(MSDOS) || defined(__WIN__)
26
#include <process.h> /* Prototype for getpid */
26
32
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)
35
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
36
uint columns, MI_COLUMNDEF *recinfo,
37
uint uniques, MI_UNIQUEDEF *uniquedefs,
38
MI_CREATE_INFO *ci,uint flags)
34
register uint32_t i, j;
35
File dfile= 0, file= 0;
36
42
int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
38
uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
44
uint fields,length,max_key_length,packed,pointer,real_length_diff,
39
45
key_length,info_length,key_segs,options,min_key_length_skip,
40
46
base_pos,long_varchar_count,varchar_length,
41
47
max_key_block_length,unique_key_parts,fulltext_keys,offset;
42
uint32_t aligned_key_start, block_length;
48
uint aligned_key_start, block_length;
43
49
ulong reclength, real_reclength,min_pack_length;
44
50
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
45
51
ulong pack_reclength;
46
uint64_t tot_length,max_rows, tmp;
52
ulonglong tot_length,max_rows, tmp;
47
53
enum en_fieldtype type;
48
54
MYISAM_SHARE share;
49
55
MI_KEYDEF *keydef,tmp_keydef;
53
59
ulong *rec_per_key_part;
54
60
my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
55
61
MI_CREATE_INFO tmp_create_info;
62
DBUG_ENTER("mi_create");
63
DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u",
64
keys, columns, uniques, flags));
59
memset(&tmp_create_info, 0, sizeof(tmp_create_info));
68
bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
60
69
ci=&tmp_create_info;
63
72
if (keys + uniques > MI_MAX_KEY || columns == 0)
65
return(my_errno=HA_WRONG_CREATE_OPTION);
74
DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
69
memset(&share, 0, sizeof(share));
78
bzero((uchar*) &share,sizeof(share));
71
80
if (flags & HA_DONT_TOUCH_DATA)
183
192
options|= HA_OPTION_RELIES_ON_SQL_LAYER;
185
194
packed=(packed+7)/8;
186
if (pack_reclength != INT32_MAX)
195
if (pack_reclength != INT_MAX32)
187
196
pack_reclength+= reclength+packed +
188
197
test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
189
198
min_pack_length+=packed;
191
200
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;
202
if (pack_reclength == INT_MAX32 ||
203
(~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
204
ci->data_file_length= ~(ulonglong) 0;
197
ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
206
ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
199
208
else if (!ci->max_rows)
200
209
ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
205
214
pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
207
216
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);
217
if (!(max_rows=(ulonglong) ci->max_rows))
218
max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
212
221
real_reclength=reclength;
236
245
share.state.key_root[i]= HA_OFFSET_ERROR;
237
246
min_key_length_skip=length=real_length_diff=0;
238
247
key_length=pointer;
248
if (keydef->flag & HA_SPATIAL)
251
/* BAR TODO to support 3D and more dimensions in the future */
252
uint sp_segs=SPDIMS*2;
253
keydef->flag=HA_SPATIAL;
255
if (flags & HA_DONT_TOUCH_DATA)
258
called by myisamchk - i.e. table structure was taken from
259
MYI file and SPATIAL key *does have* additional sp_segs keysegs.
260
keydef->seg here points right at the GEOMETRY segment,
261
so we only need to decrease keydef->keysegs.
262
(see recreate_table() in mi_check.c)
264
keydef->keysegs-=sp_segs-1;
267
for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
270
if (keyseg->type != HA_KEYTYPE_BINARY &&
271
keyseg->type != HA_KEYTYPE_VARBINARY1 &&
272
keyseg->type != HA_KEYTYPE_VARBINARY2)
274
my_errno=HA_WRONG_CREATE_OPTION;
278
keydef->keysegs+=sp_segs;
279
key_length+=SPLEN*sp_segs;
280
length++; /* At least one length byte */
281
min_key_length_skip+=SPLEN*2*SPDIMS;
283
my_errno= HA_ERR_UNSUPPORTED;
285
#endif /*HAVE_SPATIAL*/
287
else if (keydef->flag & HA_FULLTEXT)
289
keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
290
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
292
for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
295
if (keyseg->type != HA_KEYTYPE_TEXT &&
296
keyseg->type != HA_KEYTYPE_VARTEXT1 &&
297
keyseg->type != HA_KEYTYPE_VARTEXT2)
299
my_errno=HA_WRONG_CREATE_OPTION;
302
if (!(keyseg->flag & HA_BLOB_PART) &&
303
(keyseg->type == HA_KEYTYPE_VARTEXT1 ||
304
keyseg->type == HA_KEYTYPE_VARTEXT2))
306
/* Make a flag that this is a VARCHAR */
307
keyseg->flag|= HA_VAR_LENGTH_PART;
308
/* Store in bit_start number of bytes used to pack the length */
309
keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)?
315
key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
316
length++; /* At least one length byte */
317
min_key_length_skip+=HA_FT_MAXBYTELEN;
318
real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
240
322
/* Test if prefix compression */
241
323
if (keydef->flag & HA_PACK_KEY)
355
437
block_length= (keydef->block_length ?
356
438
my_round_up_to_next_power(keydef->block_length) :
357
439
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);
440
block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
441
block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
361
keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
443
keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
362
444
pointer,MI_MAX_KEYPTR_SIZE,
364
446
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
370
452
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;
453
keydef->keylength= (uint16) key_length;
454
keydef->minlength= (uint16) (length-min_key_length_skip);
455
keydef->maxlength= (uint16) length;
375
457
if (length > max_key_length)
376
458
max_key_length= length;
444
527
got from MYI file header (see also myisampack.c:save_state)
446
529
share.base.key_reflength=
447
mi_get_pointer_length(cmax(ci->key_file_length,tmp),3);
530
mi_get_pointer_length(max(ci->key_file_length,tmp),3);
448
531
share.base.keys= share.state.header.keys= keys;
449
532
share.state.header.uniques= uniques;
450
533
share.state.header.fulltext_keys= fulltext_keys;
469
552
share.base.pack_bits=packed;
470
553
share.base.fields=fields;
471
554
share.base.pack_fields=packed;
556
share.base.raid_type=ci->raid_type;
557
share.base.raid_chunks=ci->raid_chunks;
558
share.base.raid_chunksize=ci->raid_chunksize;
473
561
/* max_data_file_length and max_key_file_length are recalculated on open */
474
562
if (options & HA_OPTION_TMP_TABLE)
477
565
share.base.min_block_length=
478
566
(share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
479
567
! share.base.blobs) ?
480
cmax(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
568
max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
481
569
MI_EXTEND_BLOCK_LENGTH;
482
570
if (! (flags & HA_DONT_TOUCH_DATA))
483
571
share.state.create_time= (long) time((time_t*) 0);
556
644
if (!(flags & HA_DONT_TOUCH_DATA))
647
if (share.base.raid_type)
649
(void) fn_format(filename, name, "", MI_NAME_DEXT,
650
MY_UNPACK_FILENAME | MY_APPEND_EXT);
651
if ((dfile=my_raid_create(filename, 0, create_mode,
652
share.base.raid_type,
653
share.base.raid_chunks,
654
share.base.raid_chunksize,
655
MYF(MY_WME | MY_RAID))) < 0)
559
661
if (ci->data_file_name)
702
DBUG_PRINT("info", ("write state info and base info"));
600
703
if (mi_state_info_write(file, &share.state, 2) ||
601
704
mi_base_info_write(file, &share.base))
707
if ((uint) my_tell(file,MYF(0)) != base_pos+ MI_BASE_INFO_SIZE)
709
uint pos=(uint) my_tell(file,MYF(0));
710
DBUG_PRINT("warning",("base_length: %d != used_length: %d",
711
base_pos+ MI_BASE_INFO_SIZE, pos));
604
715
/* Write key and keyseg definitions */
716
DBUG_PRINT("info", ("write key and keyseg definitions"));
605
717
for (i=0 ; i < share.base.keys - uniques; i++)
719
uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
609
721
if (mi_keydef_write(file, &keydefs[i]))
611
723
for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
612
724
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
727
for (j=0 ; j < sp_segs ; j++)
731
sseg.language= 7; /* Binary */
740
sseg.flag= HA_SWAP_KEY;
741
if (mi_keyseg_write(file, &sseg))
615
746
/* Create extra keys for unique definitions */
616
747
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
617
memset(&tmp_keydef, 0, sizeof(tmp_keydef));
618
memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
748
bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
749
bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
619
750
for (i=0; i < uniques ; i++)
621
752
tmp_keydef.keysegs=1;
622
753
tmp_keydef.flag= HA_UNIQUE_CHECK;
623
tmp_keydef.block_length= (uint16_t)myisam_block_size;
754
tmp_keydef.block_length= (uint16)myisam_block_size;
624
755
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
625
756
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
626
757
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
798
DBUG_PRINT("info", ("write field definitions"));
666
799
for (i=0 ; i < share.base.fields ; i++)
667
800
if (mi_recinfo_write(file, &recinfo[i]))
804
if ((uint) my_tell(file,MYF(0)) != info_length)
806
uint pos= (uint) my_tell(file,MYF(0));
807
DBUG_PRINT("warning",("info_length: %d != used_length: %d",
670
812
/* Enlarge files */
813
DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
671
814
if (ftruncate(file, (off_t) share.base.keystart))
685
828
pthread_mutex_unlock(&THR_LOCK_myisam);
686
829
if (my_close(file,MYF(0)))
688
free((char*) rec_per_key_part);
831
my_free((char*) rec_per_key_part,MYF(0));
692
835
pthread_mutex_unlock(&THR_LOCK_myisam);
693
836
save_errno=my_errno;
694
837
switch (errpos) {
696
my_close(dfile,MYF(0));
839
VOID(my_close(dfile,MYF(0)));
697
840
/* fall through */
842
/* QQ: T�nu should add a call to my_raid_delete() here */
699
843
if (! (flags & HA_DONT_TOUCH_DATA))
700
844
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,
701
845
MY_UNPACK_FILENAME | MY_APPEND_EXT),
703
847
/* fall through */
705
my_close(file,MYF(0));
849
VOID(my_close(file,MYF(0)));
706
850
if (! (flags & HA_DONT_TOUCH_DATA))
707
851
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,
708
852
MY_UNPACK_FILENAME | MY_APPEND_EXT),
711
free((char*) rec_per_key_part);
712
return(my_errno=save_errno); /* return the fatal errno */
855
my_free((char*) rec_per_key_part, MYF(0));
856
DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */
716
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
860
uint mi_get_pointer_length(ulonglong file_length, uint def)
718
assert(def >= 2 && def <= 7);
862
DBUG_ASSERT(def >= 2 && def <= 7);
719
863
if (file_length) /* If not default */
721
865
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
722
if (file_length >= 1ULL << 56)
866
if (file_length >= ULL(1) << 56)
726
if (file_length >= 1ULL << 48)
870
if (file_length >= ULL(1) << 48)
728
else if (file_length >= 1ULL << 40)
872
else if (file_length >= ULL(1) << 40)
730
else if (file_length >= 1ULL << 32)
874
else if (file_length >= ULL(1) << 32)
732
else if (file_length >= 1ULL << 24)
876
else if (file_length >= ULL(1) << 24)
734
else if (file_length >= 1ULL << 16)
878
else if (file_length >= ULL(1) << 16)