12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
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;
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;
66
memset(&tmp_create_info, 0, sizeof(tmp_create_info));
61
bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
67
62
ci=&tmp_create_info;
70
65
if (keys + uniques > MI_MAX_KEY || columns == 0)
72
return(errno=HA_WRONG_CREATE_OPTION);
67
return(my_errno=HA_WRONG_CREATE_OPTION);
76
memset(&share, 0, sizeof(share));
71
bzero((uchar*) &share,sizeof(share));
78
73
if (flags & HA_DONT_TOUCH_DATA)
80
75
if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
81
76
options=ci->old_options &
82
77
(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
83
HA_OPTION_READ_ONLY_DATA |
84
HA_OPTION_TMP_TABLE );
78
HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
79
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
86
81
options=ci->old_options &
87
(HA_OPTION_TMP_TABLE );
82
(HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
90
85
if (ci->reloc_rows > ci->max_rows)
91
86
ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
93
88
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));
89
(ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long),
90
MYF(MY_WME | MY_ZEROFILL))))
98
93
/* Start by checking fields and field-types used */
170
165
if (packed || (flags & HA_PACK_RECORD))
171
166
options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
167
/* We can't use checksum with static length rows */
168
if (!(options & HA_OPTION_PACK_RECORD))
169
options&= ~HA_OPTION_CHECKSUM;
172
170
if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
173
171
min_pack_length+= varchar_length;
174
172
if (flags & HA_CREATE_TMP_TABLE)
176
174
options|= HA_OPTION_TMP_TABLE;
177
create_mode|= O_EXCL;
175
create_mode|= O_EXCL | O_NOFOLLOW;
177
if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
179
options|= HA_OPTION_CHECKSUM;
182
if (flags & HA_CREATE_DELAY_KEY_WRITE)
183
options|= HA_OPTION_DELAY_KEY_WRITE;
184
if (flags & HA_CREATE_RELIES_ON_SQL_LAYER)
185
options|= HA_OPTION_RELIES_ON_SQL_LAYER;
180
187
packed=(packed+7)/8;
181
188
if (pack_reclength != INT32_MAX)
182
189
pack_reclength+= reclength+packed +
183
test(test_all_bits(options,
184
uint32_t(HA_PACK_RECORD)));
190
test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
185
191
min_pack_length+=packed;
187
193
if (!ci->data_file_length && ci->max_rows)
200
206
if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
201
pointer=mi_get_pointer_length(ci->data_file_length, data_pointer_size);
207
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);
209
pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
204
210
if (!(max_rows=(uint64_t) ci->max_rows))
205
211
max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
236
242
/* Test if prefix compression */
237
243
if (keydef->flag & HA_PACK_KEY)
245
/* Can't use space_compression on number keys */
246
if ((keydef->seg[0].flag & HA_SPACE_PACK) &&
247
keydef->seg[0].type == (int) HA_KEYTYPE_NUM)
248
keydef->seg[0].flag&= ~HA_SPACE_PACK;
239
250
/* Only use HA_PACK_KEY when first segment is a variable length key */
240
251
if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
241
252
HA_VAR_LENGTH_PART)))
261
272
/* numbers are stored with high by first to make compression easier */
262
273
switch (keyseg->type) {
274
case HA_KEYTYPE_SHORT_INT:
263
275
case HA_KEYTYPE_LONG_INT:
276
case HA_KEYTYPE_FLOAT:
264
277
case HA_KEYTYPE_DOUBLE:
278
case HA_KEYTYPE_USHORT_INT:
265
279
case HA_KEYTYPE_ULONG_INT:
266
280
case HA_KEYTYPE_LONGLONG:
267
281
case HA_KEYTYPE_ULONGLONG:
282
case HA_KEYTYPE_INT24:
283
case HA_KEYTYPE_UINT24:
284
case HA_KEYTYPE_INT8:
268
285
keyseg->flag|= HA_SWAP_KEY;
270
287
case HA_KEYTYPE_VARTEXT1:
337
354
share.state.rec_per_key_part[key_segs-1]=1L;
338
355
length+=key_length;
339
356
/* Get block length for key, if defined by user */
340
block_length= (keydef->block_length ?
357
block_length= (keydef->block_length ?
341
358
my_round_up_to_next_power(keydef->block_length) :
342
359
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);
360
block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
361
block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
346
keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
363
keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
347
364
pointer,MI_MAX_KEYPTR_SIZE,
349
366
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
350
367
length >= MI_MAX_KEY_BUFF)
352
errno=HA_WRONG_CREATE_OPTION;
369
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;
372
set_if_bigger(max_key_block_length,keydef->block_length);
373
keydef->keylength= (uint16) key_length;
374
keydef->minlength= (uint16) (length-min_key_length_skip);
375
keydef->maxlength= (uint16) length;
360
377
if (length > max_key_length)
361
378
max_key_length= length;
392
409
/* There are only 16 bits for the total header length. */
393
410
if (info_length > 65535)
395
my_printf_error(EE_OK, "MyISAM table '%s' has too many columns and/or "
412
my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
396
413
"indexes and/or unique constraints.",
397
MYF(0), name + internal::dirname_length(name));
398
errno= HA_WRONG_CREATE_OPTION;
414
MYF(0), name + dirname_length(name));
415
my_errno= HA_WRONG_CREATE_OPTION;
402
memmove(share.state.header.file_version,myisam_file_magic,4);
419
bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
403
420
ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
404
421
HA_OPTION_COMPRESS_RECORD |
405
422
HA_OPTION_TEMP_COMPRESS_RECORD: 0);
448
465
share.base.records=ci->max_rows;
449
466
share.base.reloc= ci->reloc_rows;
450
467
share.base.reclength=real_reclength;
451
share.base.pack_reclength=reclength;
468
share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);
452
469
share.base.max_pack_length=pack_reclength;
453
470
share.base.min_pack_length=min_pack_length;
454
471
share.base.pack_bits=packed;
458
475
/* max_data_file_length and max_key_file_length are recalculated on open */
459
476
if (options & HA_OPTION_TMP_TABLE)
460
share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
477
share.base.max_data_file_length=(my_off_t) ci->data_file_length;
462
479
share.base.min_block_length=
463
480
(share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
464
481
! share.base.blobs) ?
465
max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
482
max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
466
483
MI_EXTEND_BLOCK_LENGTH;
467
484
if (! (flags & HA_DONT_TOUCH_DATA))
468
485
share.state.create_time= (long) time((time_t*) 0);
470
THR_LOCK_myisam.lock();
487
pthread_mutex_lock(&THR_LOCK_myisam);
473
490
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, ...).
491
MY_RETURN_REAL_PATH for every fn_format(filename, ...).
476
493
if (ci->index_file_name)
478
char *iext= strrchr((char *)ci->index_file_name, '.');
495
char *iext= strrchr(ci->index_file_name, '.');
479
496
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
480
497
if (options & HA_OPTION_TMP_TABLE)
483
500
/* chop off the table name, tempory tables use generated name */
484
if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
501
if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
486
internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
503
fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
487
504
MY_REPLACE_DIR | MY_UNPACK_FILENAME |
488
505
MY_RETURN_REAL_PATH | MY_APPEND_EXT);
492
internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
509
fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
493
510
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
494
511
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
496
internal::fn_format(linkname, name, "", MI_NAME_IEXT,
513
fn_format(linkname, name, "", MI_NAME_IEXT,
497
514
MY_UNPACK_FILENAME|MY_APPEND_EXT);
498
515
linkname_ptr=linkname;
507
char *iext= strrchr((char *)name, '.');
524
char *iext= strrchr(name, '.');
508
525
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
509
internal::fn_format(filename, name, "", MI_NAME_IEXT,
526
fn_format(filename, name, "", MI_NAME_IEXT,
510
527
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
511
528
(have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
527
544
if (test_if_reopen(filename))
529
my_printf_error(EE_OK, "MyISAM table '%s' is in use "
546
my_printf_error(0, "MyISAM table '%s' is in use "
530
547
"(most likely by a MERGE table). Try FLUSH TABLES.",
531
MYF(0), name + internal::dirname_length(name));
532
errno= HA_ERR_TABLE_EXIST;
548
MYF(0), name + dirname_length(name));
549
my_errno= HA_ERR_TABLE_EXIST;
536
if ((file= internal::my_create_with_symlink(linkname_ptr,
540
MYF(MY_WME | create_flag))) < 0)
553
if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
554
MYF(MY_WME | create_flag))) < 0)
547
561
if (ci->data_file_name)
549
char *dext= strrchr((char *)ci->data_file_name, '.');
563
char *dext= strrchr(ci->data_file_name, '.');
550
564
int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
552
566
if (options & HA_OPTION_TMP_TABLE)
555
569
/* chop off the table name, tempory tables use generated name */
556
if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
570
if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
558
internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
572
fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
559
573
MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
563
internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
577
fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
564
578
MY_UNPACK_FILENAME |
565
579
(have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
568
internal::fn_format(linkname, name, "",MI_NAME_DEXT,
582
fn_format(linkname, name, "",MI_NAME_DEXT,
569
583
MY_UNPACK_FILENAME | MY_APPEND_EXT);
570
584
linkname_ptr=linkname;
575
internal::fn_format(filename,name,"", MI_NAME_DEXT,
589
fn_format(filename,name,"", MI_NAME_DEXT,
576
590
MY_UNPACK_FILENAME | MY_APPEND_EXT);
578
592
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)
595
my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
596
MYF(MY_WME | create_flag))) < 0)
603
617
/* Create extra keys for unique definitions */
604
618
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
605
memset(&tmp_keydef, 0, sizeof(tmp_keydef));
606
memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
619
bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
620
bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
607
621
for (i=0; i < uniques ; i++)
609
623
tmp_keydef.keysegs=1;
610
624
tmp_keydef.flag= HA_UNIQUE_CHECK;
611
tmp_keydef.block_length= (uint16_t)myisam_block_size;
625
tmp_keydef.block_length= (uint16)myisam_block_size;
612
626
tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
613
627
tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
614
628
tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
669
if (internal::my_close(dfile,MYF(0)))
683
if (my_close(dfile,MYF(0)))
673
THR_LOCK_myisam.unlock();
674
if (internal::my_close(file,MYF(0)))
687
pthread_mutex_unlock(&THR_LOCK_myisam);
688
if (my_close(file,MYF(0)))
676
free((char*) rec_per_key_part);
690
my_free((char*) rec_per_key_part,MYF(0));
680
THR_LOCK_myisam.unlock();
694
pthread_mutex_unlock(&THR_LOCK_myisam);
682
696
switch (errpos) {
684
internal::my_close(dfile,MYF(0));
698
VOID(my_close(dfile,MYF(0)));
685
699
/* fall through */
701
/* QQ: T�nu should add a call to my_raid_delete() here */
687
702
if (! (flags & HA_DONT_TOUCH_DATA))
688
internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
703
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,
689
704
MY_UNPACK_FILENAME | MY_APPEND_EXT),
691
706
/* fall through */
693
internal::my_close(file,MYF(0));
708
VOID(my_close(file,MYF(0)));
694
709
if (! (flags & HA_DONT_TOUCH_DATA))
695
internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
710
my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,
696
711
MY_UNPACK_FILENAME | MY_APPEND_EXT),
699
free((char*) rec_per_key_part);
700
return(errno=save_errno); /* return the fatal errno */
714
my_free((char*) rec_per_key_part, MYF(0));
715
return(my_errno=save_errno); /* return the fatal errno */
704
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
719
uint mi_get_pointer_length(uint64_t file_length, uint def)
706
721
assert(def >= 2 && def <= 7);
707
722
if (file_length) /* If not default */