1
/* Copyright (C) 2000-2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
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;
33
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)
41
register uint32_t i, j;
42
int dfile= 0, file= 0;
43
int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
45
uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
46
key_length,info_length,key_segs,options,min_key_length_skip,
47
base_pos,long_varchar_count,varchar_length,
48
max_key_block_length,unique_key_parts,fulltext_keys,offset;
49
uint32_t aligned_key_start, block_length;
50
ulong reclength, real_reclength,min_pack_length;
51
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
53
uint64_t tot_length,max_rows, tmp;
54
enum en_fieldtype type;
56
MI_KEYDEF *keydef,tmp_keydef;
57
MI_UNIQUEDEF *uniquedef;
58
HA_KEYSEG *keyseg,tmp_keyseg;
60
ulong *rec_per_key_part;
61
internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
62
MI_CREATE_INFO tmp_create_info;
66
memset(&tmp_create_info, 0, sizeof(tmp_create_info));
70
if (keys + uniques > MI_MAX_KEY || columns == 0)
72
return(errno=HA_WRONG_CREATE_OPTION);
76
memset(&share, 0, sizeof(share));
78
if (flags & HA_DONT_TOUCH_DATA)
80
if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
81
options=ci->old_options &
82
(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
83
HA_OPTION_READ_ONLY_DATA |
84
HA_OPTION_TMP_TABLE );
86
options=ci->old_options &
87
(HA_OPTION_TMP_TABLE );
90
if (ci->reloc_rows > ci->max_rows)
91
ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
93
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));
98
/* Start by checking fields and field-types used */
100
reclength=varchar_length=long_varchar_count=packed=
101
min_pack_length=pack_reclength=0;
102
for (rec=recinfo, fields=0 ;
106
reclength+=rec->length;
107
if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL &&
111
if (type == FIELD_BLOB)
114
if (pack_reclength != INT32_MAX)
116
if (rec->length == 4+portable_sizeof_char_ptr)
117
pack_reclength= INT32_MAX;
119
pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */
122
else if (type == FIELD_SKIP_PRESPACE ||
123
type == FIELD_SKIP_ENDSPACE)
125
if (pack_reclength != INT32_MAX)
126
pack_reclength+= rec->length > 255 ? 2 : 1;
129
else if (type == FIELD_VARCHAR)
131
varchar_length+= rec->length-1; /* Used for min_pack_length */
135
/* We must test for 257 as length includes pack-length */
136
if (test(rec->length >= 257))
138
long_varchar_count++;
139
pack_reclength+= 2; /* May be packed on 3 bytes */
142
else if (type != FIELD_SKIP_ZERO)
144
min_pack_length+=rec->length;
145
packed--; /* Not a pack record type */
148
else /* FIELD_NORMAL */
149
min_pack_length+=rec->length;
151
if ((packed & 7) == 1)
152
{ /* Bad packing, try to remove a zero-field */
153
while (rec != recinfo)
156
if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
159
NOTE1: here we change a field type FIELD_SKIP_ZERO ->
162
rec->type=(int) FIELD_NORMAL;
170
if (packed || (flags & HA_PACK_RECORD))
171
options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
172
if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
173
min_pack_length+= varchar_length;
174
if (flags & HA_CREATE_TMP_TABLE)
176
options|= HA_OPTION_TMP_TABLE;
177
create_mode|= O_EXCL;
181
if (pack_reclength != INT32_MAX)
182
pack_reclength+= reclength+packed +
183
test(test_all_bits(options,
184
uint32_t(HA_PACK_RECORD)));
185
min_pack_length+=packed;
187
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;
193
ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
195
else if (!ci->max_rows)
196
ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
197
((options & HA_OPTION_PACK_RECORD) ?
200
if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
201
pointer=mi_get_pointer_length(ci->data_file_length, 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);
208
real_reclength=reclength;
209
if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)))
211
if (reclength <= pointer)
212
reclength=pointer+1; /* reserve place for delete link */
215
reclength+= long_varchar_count; /* We need space for varchar! */
217
max_key_length=0; tot_length=0 ; key_segs=0;
219
max_key_block_length=0;
220
share.state.rec_per_key_part=rec_per_key_part;
221
share.state.key_root=key_root;
222
share.state.key_del=key_del;
225
max_key_block_length= myisam_block_size;
226
max_key_length= MI_UNIQUE_HASH_LENGTH + pointer;
229
for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
232
share.state.key_root[i]= HA_OFFSET_ERROR;
233
min_key_length_skip=length=real_length_diff=0;
236
/* Test if prefix compression */
237
if (keydef->flag & HA_PACK_KEY)
239
/* Only use HA_PACK_KEY when first segment is a variable length key */
240
if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
241
HA_VAR_LENGTH_PART)))
243
/* pack relative to previous key */
244
keydef->flag&= ~HA_PACK_KEY;
245
keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
249
keydef->seg[0].flag|=HA_PACK_KEY; /* for easyer intern test */
250
keydef->flag|=HA_VAR_LENGTH_KEY;
251
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
254
if (keydef->flag & HA_BINARY_PACK_KEY)
255
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
257
if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment)
258
share.base.auto_key=i+1;
259
for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++)
261
/* numbers are stored with high by first to make compression easier */
262
switch (keyseg->type) {
263
case HA_KEYTYPE_LONG_INT:
264
case HA_KEYTYPE_DOUBLE:
265
case HA_KEYTYPE_ULONG_INT:
266
case HA_KEYTYPE_LONGLONG:
267
case HA_KEYTYPE_ULONGLONG:
268
case HA_KEYTYPE_UINT24:
269
keyseg->flag|= HA_SWAP_KEY;
271
case HA_KEYTYPE_VARTEXT1:
272
case HA_KEYTYPE_VARTEXT2:
273
case HA_KEYTYPE_VARBINARY1:
274
case HA_KEYTYPE_VARBINARY2:
275
if (!(keyseg->flag & HA_BLOB_PART))
277
/* Make a flag that this is a VARCHAR */
278
keyseg->flag|= HA_VAR_LENGTH_PART;
279
/* Store in bit_start number of bytes used to pack the length */
280
keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
281
keyseg->type == HA_KEYTYPE_VARBINARY1) ?
288
if (keyseg->flag & HA_SPACE_PACK)
290
assert(!(keyseg->flag & HA_VAR_LENGTH_PART));
291
keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
292
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
293
length++; /* At least one length byte */
294
min_key_length_skip+=keyseg->length;
295
if (keyseg->length >= 255)
296
{ /* prefix may be 3 bytes */
297
min_key_length_skip+=2;
301
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
303
assert(!test_all_bits(keyseg->flag,
304
(HA_VAR_LENGTH_PART | HA_BLOB_PART)));
305
keydef->flag|=HA_VAR_LENGTH_KEY;
306
length++; /* At least one length byte */
307
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
308
min_key_length_skip+=keyseg->length;
309
if (keyseg->length >= 255)
310
{ /* prefix may be 3 bytes */
311
min_key_length_skip+=2;
315
key_length+= keyseg->length;
316
if (keyseg->null_bit)
319
options|=HA_OPTION_PACK_KEYS;
320
keyseg->flag|=HA_NULL_PART;
321
keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY;
324
} /* if HA_FULLTEXT */
325
key_segs+=keydef->keysegs;
326
if (keydef->keysegs > MI_MAX_KEY_SEG)
328
errno=HA_WRONG_CREATE_OPTION;
332
key_segs may be 0 in the case when we only want to be able to
333
add on row into the table. This can happen with some DISTINCT queries
336
if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME &&
338
share.state.rec_per_key_part[key_segs-1]=1L;
340
/* Get block length for key, if defined by user */
341
block_length= (keydef->block_length ?
342
my_round_up_to_next_power(keydef->block_length) :
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);
347
keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
348
pointer,MI_MAX_KEYPTR_SIZE,
350
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
351
length >= MI_MAX_KEY_BUFF)
353
errno=HA_WRONG_CREATE_OPTION;
356
set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
357
keydef->keylength= (uint16_t) key_length;
358
keydef->minlength= (uint16_t) (length-min_key_length_skip);
359
keydef->maxlength= (uint16_t) length;
361
if (length > max_key_length)
362
max_key_length= length;
363
tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/
365
(ulong) keydef->block_length;
367
for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
368
key_del[i]=HA_OFFSET_ERROR;
371
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
372
for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++)
374
uniquedef->key=keys+i;
375
unique_key_parts+=uniquedef->keysegs;
376
share.state.key_root[keys+i]= HA_OFFSET_ERROR;
377
tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/
378
((MI_UNIQUE_HASH_LENGTH + pointer)*2)))*
379
(ulong) myisam_block_size;
381
keys+=uniques; /* Each unique has 1 key */
382
key_segs+=uniques; /* Each unique has 1 key seg */
384
base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
385
max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
386
MI_STATE_KEYBLOCK_SIZE+
387
key_segs*MI_STATE_KEYSEG_SIZE);
388
info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
389
keys * MI_KEYDEF_SIZE+
390
uniques * MI_UNIQUEDEF_SIZE +
391
(key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
392
columns*MI_COLUMNDEF_SIZE);
393
/* There are only 16 bits for the total header length. */
394
if (info_length > 65535)
396
my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
397
"indexes and/or unique constraints.",
398
MYF(0), name + internal::dirname_length(name));
399
errno= HA_WRONG_CREATE_OPTION;
403
memmove(share.state.header.file_version,myisam_file_magic,4);
404
ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
405
HA_OPTION_COMPRESS_RECORD |
406
HA_OPTION_TEMP_COMPRESS_RECORD: 0);
407
mi_int2store(share.state.header.options,ci->old_options);
408
mi_int2store(share.state.header.header_length,info_length);
409
mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE);
410
mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
411
mi_int2store(share.state.header.base_pos,base_pos);
412
share.state.header.language= (ci->language ?
413
ci->language : default_charset_info->number);
414
share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
416
share.state.dellink = HA_OFFSET_ERROR;
417
share.state.process= (ulong) getpid();
418
share.state.unique= (ulong) 0;
419
share.state.update_count=(ulong) 0;
420
share.state.version= (ulong) time((time_t*) 0);
421
share.state.sortkey= UINT16_MAX;
422
share.state.auto_increment=ci->auto_increment;
423
share.options=options;
424
share.base.rec_reflength=pointer;
425
/* Get estimate for index file length (this may be wrong for FT keys) */
426
tmp= (tot_length + max_key_block_length * keys *
427
MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
429
use maximum of key_file_length we calculated and key_file_length value we
430
got from MYI file header (see also myisampack.c:save_state)
432
share.base.key_reflength=
433
mi_get_pointer_length(max(ci->key_file_length,tmp),3);
434
share.base.keys= share.state.header.keys= keys;
435
share.state.header.uniques= uniques;
436
share.state.header.fulltext_keys= fulltext_keys;
437
mi_int2store(share.state.header.key_parts,key_segs);
438
mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
440
mi_set_all_keys_active(share.state.key_map, keys);
441
aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
442
max_key_block_length :
445
share.base.keystart= share.state.state.key_file_length=
446
MY_ALIGN(info_length, aligned_key_start);
447
share.base.max_key_block_length=max_key_block_length;
448
share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
449
share.base.records=ci->max_rows;
450
share.base.reloc= ci->reloc_rows;
451
share.base.reclength=real_reclength;
452
share.base.pack_reclength=reclength;
453
share.base.max_pack_length=pack_reclength;
454
share.base.min_pack_length=min_pack_length;
455
share.base.pack_bits=packed;
456
share.base.fields=fields;
457
share.base.pack_fields=packed;
459
/* max_data_file_length and max_key_file_length are recalculated on open */
460
if (options & HA_OPTION_TMP_TABLE)
461
share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
463
share.base.min_block_length=
464
(share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
465
! share.base.blobs) ?
466
max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
467
MI_EXTEND_BLOCK_LENGTH;
468
if (! (flags & HA_DONT_TOUCH_DATA))
469
share.state.create_time= (long) time((time_t*) 0);
471
pthread_mutex_lock(&THR_LOCK_myisam);
474
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, ...).
477
if (ci->index_file_name)
479
char *iext= strrchr((char *)ci->index_file_name, '.');
480
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
481
if (options & HA_OPTION_TMP_TABLE)
484
/* chop off the table name, tempory tables use generated name */
485
if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
487
internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
488
MY_REPLACE_DIR | MY_UNPACK_FILENAME |
489
MY_RETURN_REAL_PATH | MY_APPEND_EXT);
493
internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
494
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
495
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
497
internal::fn_format(linkname, name, "", MI_NAME_IEXT,
498
MY_UNPACK_FILENAME|MY_APPEND_EXT);
499
linkname_ptr=linkname;
501
Don't create the table if the link or file exists to ensure that one
502
doesn't accidently destroy another table.
508
char *iext= strrchr((char *)name, '.');
509
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
510
internal::fn_format(filename, name, "", MI_NAME_IEXT,
511
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
512
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
514
/* Replace the current file */
515
create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
519
If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
520
but no entry is made in the table cache for them.
521
A TRUNCATE command checks for the table in the cache only and could
522
be fooled to believe, the table is not open.
523
Pull the emergency brake in this situation. (Bug #8306)
525
NOTE: The filename is compared against unique_file_name of every
526
open table. Hence we need a real path here.
528
if (test_if_reopen(filename))
530
my_printf_error(0, "MyISAM table '%s' is in use "
531
"(most likely by a MERGE table). Try FLUSH TABLES.",
532
MYF(0), name + internal::dirname_length(name));
533
errno= HA_ERR_TABLE_EXIST;
537
if ((file= internal::my_create_with_symlink(linkname_ptr,
541
MYF(MY_WME | create_flag))) < 0)
545
if (!(flags & HA_DONT_TOUCH_DATA))
548
if (ci->data_file_name)
550
char *dext= strrchr((char *)ci->data_file_name, '.');
551
int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
553
if (options & HA_OPTION_TMP_TABLE)
556
/* chop off the table name, tempory tables use generated name */
557
if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
559
internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
560
MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
564
internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
566
(have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
569
internal::fn_format(linkname, name, "",MI_NAME_DEXT,
570
MY_UNPACK_FILENAME | MY_APPEND_EXT);
571
linkname_ptr=linkname;
576
internal::fn_format(filename,name,"", MI_NAME_DEXT,
577
MY_UNPACK_FILENAME | MY_APPEND_EXT);
579
create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
581
if ((dfile= internal::my_create_with_symlink(linkname_ptr,
582
filename, 0, create_mode,
583
MYF(MY_WME | create_flag))) < 0)
589
if (mi_state_info_write(file, &share.state, 2) ||
590
mi_base_info_write(file, &share.base))
593
/* Write key and keyseg definitions */
594
for (i=0 ; i < share.base.keys - uniques; i++)
598
if (mi_keydef_write(file, &keydefs[i]))
600
for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
601
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
604
/* Create extra keys for unique definitions */
605
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
606
memset(&tmp_keydef, 0, sizeof(tmp_keydef));
607
memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
608
for (i=0; i < uniques ; i++)
610
tmp_keydef.keysegs=1;
611
tmp_keydef.flag= HA_UNIQUE_CHECK;
612
tmp_keydef.block_length= (uint16_t)myisam_block_size;
613
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
614
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
615
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
616
tmp_keyseg.length= MI_UNIQUE_HASH_LENGTH;
617
tmp_keyseg.start= offset;
618
offset+= MI_UNIQUE_HASH_LENGTH;
619
if (mi_keydef_write(file,&tmp_keydef) ||
620
mi_keyseg_write(file,(&tmp_keyseg)))
624
/* Save unique definition */
625
for (i=0 ; i < share.state.header.uniques ; i++)
627
HA_KEYSEG *keyseg_end;
628
keyseg= uniquedefs[i].seg;
629
if (mi_uniquedef_write(file, &uniquedefs[i]))
631
for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
635
switch (keyseg->type) {
636
case HA_KEYTYPE_VARTEXT1:
637
case HA_KEYTYPE_VARTEXT2:
638
case HA_KEYTYPE_VARBINARY1:
639
case HA_KEYTYPE_VARBINARY2:
640
if (!(keyseg->flag & HA_BLOB_PART))
642
keyseg->flag|= HA_VAR_LENGTH_PART;
643
keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
644
keyseg->type == HA_KEYTYPE_VARBINARY1) ?
651
if (mi_keyseg_write(file, keyseg))
655
for (i=0 ; i < share.base.fields ; i++)
656
if (mi_recinfo_write(file, &recinfo[i]))
660
if (ftruncate(file, (off_t) share.base.keystart))
663
if (! (flags & HA_DONT_TOUCH_DATA))
666
if (ftruncate(dfile,share.base.min_pack_length*ci->reloc_rows,))
670
if (internal::my_close(dfile,MYF(0)))
674
pthread_mutex_unlock(&THR_LOCK_myisam);
675
if (internal::my_close(file,MYF(0)))
677
free((char*) rec_per_key_part);
681
pthread_mutex_unlock(&THR_LOCK_myisam);
685
internal::my_close(dfile,MYF(0));
688
if (! (flags & HA_DONT_TOUCH_DATA))
689
internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
690
MY_UNPACK_FILENAME | MY_APPEND_EXT),
694
internal::my_close(file,MYF(0));
695
if (! (flags & HA_DONT_TOUCH_DATA))
696
internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
697
MY_UNPACK_FILENAME | MY_APPEND_EXT),
700
free((char*) rec_per_key_part);
701
return(errno=save_errno); /* return the fatal errno */
705
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
707
assert(def >= 2 && def <= 7);
708
if (file_length) /* If not default */
710
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
711
if (file_length >= 1ULL << 56)
715
if (file_length >= 1ULL << 48)
717
else if (file_length >= 1ULL << 40)
719
else if (file_length >= 1ULL << 32)
721
else if (file_length >= 1ULL << 24)
723
else if (file_length >= 1ULL << 16)