00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "myisam_priv.h"
00019 #include <drizzled/internal/my_bit.h>
00020 #include <drizzled/internal/my_sys.h>
00021
00022 #include <drizzled/util/test.h>
00023 #include <drizzled/charset.h>
00024 #include <drizzled/error.h>
00025
00026 #include <cassert>
00027 #include <algorithm>
00028
00029 using namespace std;
00030 using namespace drizzled;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 static inline uint32_t my_round_up_to_next_power(uint32_t v)
00052 {
00053 v--;
00054 v|= v >> 1;
00055 v|= v >> 2;
00056 v|= v >> 4;
00057 v|= v >> 8;
00058 v|= v >> 16;
00059 return v+1;
00060 }
00061
00062
00063
00064
00065
00066 int mi_create(const char *name,uint32_t keys,MI_KEYDEF *keydefs,
00067 uint32_t columns, MI_COLUMNDEF *recinfo,
00068 uint32_t uniques, MI_UNIQUEDEF *uniquedefs,
00069 MI_CREATE_INFO *ci,uint32_t flags)
00070 {
00071 register uint32_t i, j;
00072 int dfile= 0, file= 0;
00073 int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
00074 myf create_flag;
00075 uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
00076 key_length,info_length,key_segs,options,min_key_length_skip,
00077 base_pos,long_varchar_count,varchar_length,
00078 max_key_block_length,unique_key_parts,fulltext_keys,offset;
00079 uint32_t aligned_key_start, block_length;
00080 ulong reclength, real_reclength,min_pack_length;
00081 char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
00082 ulong pack_reclength;
00083 uint64_t tot_length,max_rows, tmp;
00084 enum en_fieldtype type;
00085 MYISAM_SHARE share;
00086 MI_KEYDEF *keydef,tmp_keydef;
00087 MI_UNIQUEDEF *uniquedef;
00088 HA_KEYSEG *keyseg,tmp_keyseg;
00089 MI_COLUMNDEF *rec;
00090 ulong *rec_per_key_part;
00091 internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
00092 MI_CREATE_INFO tmp_create_info;
00093
00094 if (!ci)
00095 {
00096 memset(&tmp_create_info, 0, sizeof(tmp_create_info));
00097 ci=&tmp_create_info;
00098 }
00099
00100 if (keys + uniques > MI_MAX_KEY || columns == 0)
00101 {
00102 return(errno=HA_WRONG_CREATE_OPTION);
00103 }
00104 errpos= 0;
00105 options= 0;
00106 memset(&share, 0, sizeof(share));
00107
00108 if (flags & HA_DONT_TOUCH_DATA)
00109 {
00110 if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
00111 options=ci->old_options &
00112 (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
00113 HA_OPTION_READ_ONLY_DATA |
00114 HA_OPTION_TMP_TABLE );
00115 else
00116 options=ci->old_options &
00117 (HA_OPTION_TMP_TABLE );
00118 }
00119
00120 if (ci->reloc_rows > ci->max_rows)
00121 ci->reloc_rows=ci->max_rows;
00122
00123 if (!(rec_per_key_part=
00124 (ulong*) malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long))))
00125 return(errno);
00126 memset(rec_per_key_part, 0, (keys + uniques)*MI_MAX_KEY_SEG*sizeof(long));
00127
00128
00129
00130 reclength=varchar_length=long_varchar_count=packed=
00131 min_pack_length=pack_reclength=0;
00132 for (rec=recinfo, fields=0 ;
00133 fields != columns ;
00134 rec++,fields++)
00135 {
00136 reclength+=rec->length;
00137 if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL &&
00138 type != FIELD_CHECK)
00139 {
00140 packed++;
00141 if (type == FIELD_BLOB)
00142 {
00143 share.base.blobs++;
00144 if (pack_reclength != INT32_MAX)
00145 {
00146 if (rec->length == 4+portable_sizeof_char_ptr)
00147 pack_reclength= INT32_MAX;
00148 else
00149 pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8));
00150 }
00151 }
00152 else if (type == FIELD_SKIP_PRESPACE ||
00153 type == FIELD_SKIP_ENDSPACE)
00154 {
00155 if (pack_reclength != INT32_MAX)
00156 pack_reclength+= rec->length > 255 ? 2 : 1;
00157 min_pack_length++;
00158 }
00159 else if (type == FIELD_VARCHAR)
00160 {
00161 varchar_length+= rec->length-1;
00162 packed--;
00163 pack_reclength++;
00164 min_pack_length++;
00165
00166 if (test(rec->length >= 257))
00167 {
00168 long_varchar_count++;
00169 pack_reclength+= 2;
00170 }
00171 }
00172 else if (type != FIELD_SKIP_ZERO)
00173 {
00174 min_pack_length+=rec->length;
00175 packed--;
00176 }
00177 }
00178 else
00179 min_pack_length+=rec->length;
00180 }
00181 if ((packed & 7) == 1)
00182 {
00183 while (rec != recinfo)
00184 {
00185 rec--;
00186 if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
00187 {
00188
00189
00190
00191
00192 rec->type=(int) FIELD_NORMAL;
00193 packed--;
00194 min_pack_length++;
00195 break;
00196 }
00197 }
00198 }
00199
00200 if (packed || (flags & HA_PACK_RECORD))
00201 options|=HA_OPTION_PACK_RECORD;
00202 if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
00203 min_pack_length+= varchar_length;
00204 if (flags & HA_CREATE_TMP_TABLE)
00205 {
00206 options|= HA_OPTION_TMP_TABLE;
00207 create_mode|= O_EXCL;
00208 }
00209
00210 packed=(packed+7)/8;
00211 if (pack_reclength != INT32_MAX)
00212 pack_reclength+= reclength+packed +
00213 test(test_all_bits(options,
00214 uint32_t(HA_PACK_RECORD)));
00215 min_pack_length+=packed;
00216
00217 if (!ci->data_file_length && ci->max_rows)
00218 {
00219 if (pack_reclength == INT32_MAX ||
00220 (~(uint64_t) 0)/ci->max_rows < (uint64_t) pack_reclength)
00221 ci->data_file_length= ~(uint64_t) 0;
00222 else
00223 ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
00224 }
00225 else if (!ci->max_rows)
00226 ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
00227 ((options & HA_OPTION_PACK_RECORD) ?
00228 3 : 0)));
00229
00230 if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
00231 pointer=mi_get_pointer_length(ci->data_file_length, data_pointer_size);
00232 else
00233 pointer=mi_get_pointer_length(ci->max_rows, data_pointer_size);
00234 if (!(max_rows=(uint64_t) ci->max_rows))
00235 max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
00236
00237
00238 real_reclength=reclength;
00239 if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)))
00240 {
00241 if (reclength <= pointer)
00242 reclength=pointer+1;
00243 }
00244 else
00245 reclength+= long_varchar_count;
00246
00247 max_key_length=0; tot_length=0 ; key_segs=0;
00248 fulltext_keys=0;
00249 max_key_block_length=0;
00250 share.state.rec_per_key_part=rec_per_key_part;
00251 share.state.key_root=key_root;
00252 share.state.key_del=key_del;
00253 if (uniques)
00254 {
00255 max_key_block_length= myisam_block_size;
00256 max_key_length= MI_UNIQUE_HASH_LENGTH + pointer;
00257 }
00258
00259 for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
00260 {
00261
00262 share.state.key_root[i]= HA_OFFSET_ERROR;
00263 min_key_length_skip=length=real_length_diff=0;
00264 key_length=pointer;
00265 {
00266
00267 if (keydef->flag & HA_PACK_KEY)
00268 {
00269
00270 if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
00271 HA_VAR_LENGTH_PART)))
00272 {
00273
00274 keydef->flag&= ~HA_PACK_KEY;
00275 keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
00276 }
00277 else
00278 {
00279 keydef->seg[0].flag|=HA_PACK_KEY;
00280 keydef->flag|=HA_VAR_LENGTH_KEY;
00281 options|=HA_OPTION_PACK_KEYS;
00282 }
00283 }
00284 if (keydef->flag & HA_BINARY_PACK_KEY)
00285 options|=HA_OPTION_PACK_KEYS;
00286
00287 if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment)
00288 share.base.auto_key=i+1;
00289 for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++)
00290 {
00291
00292 switch (keyseg->type) {
00293 case HA_KEYTYPE_LONG_INT:
00294 case HA_KEYTYPE_DOUBLE:
00295 case HA_KEYTYPE_ULONG_INT:
00296 case HA_KEYTYPE_LONGLONG:
00297 case HA_KEYTYPE_ULONGLONG:
00298 keyseg->flag|= HA_SWAP_KEY;
00299 break;
00300 case HA_KEYTYPE_VARTEXT1:
00301 case HA_KEYTYPE_VARTEXT2:
00302 case HA_KEYTYPE_VARBINARY1:
00303 case HA_KEYTYPE_VARBINARY2:
00304 if (!(keyseg->flag & HA_BLOB_PART))
00305 {
00306
00307 keyseg->flag|= HA_VAR_LENGTH_PART;
00308
00309 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
00310 keyseg->type == HA_KEYTYPE_VARBINARY1) ?
00311 1 : 2);
00312 }
00313 break;
00314 default:
00315 break;
00316 }
00317 if (keyseg->flag & HA_SPACE_PACK)
00318 {
00319 assert(!(keyseg->flag & HA_VAR_LENGTH_PART));
00320 keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
00321 options|=HA_OPTION_PACK_KEYS;
00322 length++;
00323 min_key_length_skip+=keyseg->length;
00324 if (keyseg->length >= 255)
00325 {
00326 min_key_length_skip+=2;
00327 length+=2;
00328 }
00329 }
00330 if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
00331 {
00332 assert(!test_all_bits(keyseg->flag,
00333 (HA_VAR_LENGTH_PART | HA_BLOB_PART)));
00334 keydef->flag|=HA_VAR_LENGTH_KEY;
00335 length++;
00336 options|=HA_OPTION_PACK_KEYS;
00337 min_key_length_skip+=keyseg->length;
00338 if (keyseg->length >= 255)
00339 {
00340 min_key_length_skip+=2;
00341 length+=2;
00342 }
00343 }
00344 key_length+= keyseg->length;
00345 if (keyseg->null_bit)
00346 {
00347 key_length++;
00348 options|=HA_OPTION_PACK_KEYS;
00349 keyseg->flag|=HA_NULL_PART;
00350 keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY;
00351 }
00352 }
00353 }
00354 key_segs+=keydef->keysegs;
00355 if (keydef->keysegs > MI_MAX_KEY_SEG)
00356 {
00357 errno=HA_WRONG_CREATE_OPTION;
00358 goto err;
00359 }
00360
00361
00362
00363
00364
00365 if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME &&
00366 key_segs)
00367 share.state.rec_per_key_part[key_segs-1]=1L;
00368 length+=key_length;
00369
00370 block_length= (keydef->block_length ?
00371 my_round_up_to_next_power(keydef->block_length) :
00372 myisam_block_size);
00373 block_length= max(block_length, (uint32_t)MI_MIN_KEY_BLOCK_LENGTH);
00374 block_length= min(block_length, (uint32_t)MI_MAX_KEY_BLOCK_LENGTH);
00375
00376 keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
00377 pointer,MI_MAX_KEYPTR_SIZE,
00378 block_length);
00379 if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
00380 length >= MI_MAX_KEY_BUFF)
00381 {
00382 errno=HA_WRONG_CREATE_OPTION;
00383 goto err;
00384 }
00385 set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
00386 keydef->keylength= (uint16_t) key_length;
00387 keydef->minlength= (uint16_t) (length-min_key_length_skip);
00388 keydef->maxlength= (uint16_t) length;
00389
00390 if (length > max_key_length)
00391 max_key_length= length;
00392 tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/
00393 (length*2)))*
00394 (ulong) keydef->block_length;
00395 }
00396 for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
00397 key_del[i]=HA_OFFSET_ERROR;
00398
00399 unique_key_parts=0;
00400 offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
00401 for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++)
00402 {
00403 uniquedef->key=keys+i;
00404 unique_key_parts+=uniquedef->keysegs;
00405 share.state.key_root[keys+i]= HA_OFFSET_ERROR;
00406 tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/
00407 ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))*
00408 (ulong) myisam_block_size;
00409 }
00410 keys+=uniques;
00411 key_segs+=uniques;
00412
00413 base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
00414 max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
00415 MI_STATE_KEYBLOCK_SIZE+
00416 key_segs*MI_STATE_KEYSEG_SIZE);
00417 info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
00418 keys * MI_KEYDEF_SIZE+
00419 uniques * MI_UNIQUEDEF_SIZE +
00420 (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
00421 columns*MI_COLUMNDEF_SIZE);
00422
00423 if (info_length > 65535)
00424 {
00425 my_printf_error(EE_OK, "MyISAM table '%s' has too many columns and/or "
00426 "indexes and/or unique constraints.",
00427 MYF(0), name + internal::dirname_length(name));
00428 errno= HA_WRONG_CREATE_OPTION;
00429 goto err;
00430 }
00431
00432 memmove(share.state.header.file_version,myisam_file_magic,4);
00433 ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
00434 HA_OPTION_COMPRESS_RECORD |
00435 HA_OPTION_TEMP_COMPRESS_RECORD: 0);
00436 mi_int2store(share.state.header.options,ci->old_options);
00437 mi_int2store(share.state.header.header_length,info_length);
00438 mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE);
00439 mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
00440 mi_int2store(share.state.header.base_pos,base_pos);
00441 share.state.header.language= (ci->language ?
00442 ci->language : default_charset_info->number);
00443 share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
00444
00445 share.state.dellink = HA_OFFSET_ERROR;
00446 share.state.process= (ulong) getpid();
00447 share.state.unique= (ulong) 0;
00448 share.state.update_count=(ulong) 0;
00449 share.state.version= (ulong) time((time_t*) 0);
00450 share.state.sortkey= UINT16_MAX;
00451 share.state.auto_increment=ci->auto_increment;
00452 share.options=options;
00453 share.base.rec_reflength=pointer;
00454
00455 tmp= (tot_length + max_key_block_length * keys *
00456 MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
00457
00458
00459
00460
00461 share.base.key_reflength=
00462 mi_get_pointer_length(max(ci->key_file_length,tmp),3);
00463 share.base.keys= share.state.header.keys= keys;
00464 share.state.header.uniques= uniques;
00465 share.state.header.fulltext_keys= fulltext_keys;
00466 mi_int2store(share.state.header.key_parts,key_segs);
00467 mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
00468
00469 mi_set_all_keys_active(share.state.key_map, keys);
00470 aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
00471 max_key_block_length :
00472 myisam_block_size);
00473
00474 share.base.keystart= share.state.state.key_file_length=
00475 MY_ALIGN(info_length, aligned_key_start);
00476 share.base.max_key_block_length=max_key_block_length;
00477 share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
00478 share.base.records=ci->max_rows;
00479 share.base.reloc= ci->reloc_rows;
00480 share.base.reclength=real_reclength;
00481 share.base.pack_reclength=reclength;
00482 share.base.max_pack_length=pack_reclength;
00483 share.base.min_pack_length=min_pack_length;
00484 share.base.pack_bits=packed;
00485 share.base.fields=fields;
00486 share.base.pack_fields=packed;
00487
00488
00489 if (options & HA_OPTION_TMP_TABLE)
00490 share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
00491
00492 share.base.min_block_length=
00493 (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
00494 ! share.base.blobs) ?
00495 max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
00496 MI_EXTEND_BLOCK_LENGTH;
00497 if (! (flags & HA_DONT_TOUCH_DATA))
00498 share.state.create_time= (long) time((time_t*) 0);
00499
00500 THR_LOCK_myisam.lock();
00501
00502
00503
00504
00505
00506 if (ci->index_file_name)
00507 {
00508 char *iext= strrchr((char *)ci->index_file_name, '.');
00509 int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
00510 if (options & HA_OPTION_TMP_TABLE)
00511 {
00512 char *path;
00513
00514 if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
00515 *path= '\0';
00516 internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
00517 MY_REPLACE_DIR | MY_UNPACK_FILENAME |
00518 MY_RETURN_REAL_PATH | MY_APPEND_EXT);
00519 }
00520 else
00521 {
00522 internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
00523 MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
00524 (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
00525 }
00526 internal::fn_format(linkname, name, "", MI_NAME_IEXT,
00527 MY_UNPACK_FILENAME|MY_APPEND_EXT);
00528 linkname_ptr=linkname;
00529
00530
00531
00532
00533 create_flag=0;
00534 }
00535 else
00536 {
00537 char *iext= strrchr((char *)name, '.');
00538 int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
00539 internal::fn_format(filename, name, "", MI_NAME_IEXT,
00540 MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
00541 (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
00542 linkname_ptr=0;
00543
00544 create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 if (test_if_reopen(filename))
00558 {
00559 my_printf_error(EE_OK, "MyISAM table '%s' is in use "
00560 "(most likely by a MERGE table). Try FLUSH TABLES.",
00561 MYF(0), name + internal::dirname_length(name));
00562 errno= HA_ERR_TABLE_EXIST;
00563 goto err;
00564 }
00565
00566 if ((file= internal::my_create_with_symlink(linkname_ptr,
00567 filename,
00568 0,
00569 create_mode,
00570 MYF(MY_WME | create_flag))) < 0)
00571 goto err;
00572 errpos=1;
00573
00574 if (!(flags & HA_DONT_TOUCH_DATA))
00575 {
00576 {
00577 if (ci->data_file_name)
00578 {
00579 char *dext= strrchr((char *)ci->data_file_name, '.');
00580 int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
00581
00582 if (options & HA_OPTION_TMP_TABLE)
00583 {
00584 char *path;
00585
00586 if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
00587 *path= '\0';
00588 internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
00589 MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
00590 }
00591 else
00592 {
00593 internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
00594 MY_UNPACK_FILENAME |
00595 (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
00596 }
00597
00598 internal::fn_format(linkname, name, "",MI_NAME_DEXT,
00599 MY_UNPACK_FILENAME | MY_APPEND_EXT);
00600 linkname_ptr=linkname;
00601 create_flag=0;
00602 }
00603 else
00604 {
00605 internal::fn_format(filename,name,"", MI_NAME_DEXT,
00606 MY_UNPACK_FILENAME | MY_APPEND_EXT);
00607 linkname_ptr=0;
00608 create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
00609 }
00610 if ((dfile= internal::my_create_with_symlink(linkname_ptr,
00611 filename, 0, create_mode,
00612 MYF(MY_WME | create_flag))) < 0)
00613 goto err;
00614 }
00615 errpos=3;
00616 }
00617
00618 if (mi_state_info_write(file, &share.state, 2) ||
00619 mi_base_info_write(file, &share.base))
00620 goto err;
00621
00622
00623 for (i=0 ; i < share.base.keys - uniques; i++)
00624 {
00625 uint32_t sp_segs= 0;
00626
00627 if (mi_keydef_write(file, &keydefs[i]))
00628 goto err;
00629 for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
00630 if (mi_keyseg_write(file, &keydefs[i].seg[j]))
00631 goto err;
00632 }
00633
00634 offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
00635 memset(&tmp_keydef, 0, sizeof(tmp_keydef));
00636 memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
00637 for (i=0; i < uniques ; i++)
00638 {
00639 tmp_keydef.keysegs=1;
00640 tmp_keydef.flag= HA_UNIQUE_CHECK;
00641 tmp_keydef.block_length= (uint16_t)myisam_block_size;
00642 tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
00643 tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
00644 tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
00645 tmp_keyseg.length= MI_UNIQUE_HASH_LENGTH;
00646 tmp_keyseg.start= offset;
00647 offset+= MI_UNIQUE_HASH_LENGTH;
00648 if (mi_keydef_write(file,&tmp_keydef) ||
00649 mi_keyseg_write(file,(&tmp_keyseg)))
00650 goto err;
00651 }
00652
00653
00654 for (i=0 ; i < share.state.header.uniques ; i++)
00655 {
00656 HA_KEYSEG *keyseg_end;
00657 keyseg= uniquedefs[i].seg;
00658 if (mi_uniquedef_write(file, &uniquedefs[i]))
00659 goto err;
00660 for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
00661 keyseg < keyseg_end;
00662 keyseg++)
00663 {
00664 switch (keyseg->type) {
00665 case HA_KEYTYPE_VARTEXT1:
00666 case HA_KEYTYPE_VARTEXT2:
00667 case HA_KEYTYPE_VARBINARY1:
00668 case HA_KEYTYPE_VARBINARY2:
00669 if (!(keyseg->flag & HA_BLOB_PART))
00670 {
00671 keyseg->flag|= HA_VAR_LENGTH_PART;
00672 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
00673 keyseg->type == HA_KEYTYPE_VARBINARY1) ?
00674 1 : 2);
00675 }
00676 break;
00677 default:
00678 break;
00679 }
00680 if (mi_keyseg_write(file, keyseg))
00681 goto err;
00682 }
00683 }
00684 for (i=0 ; i < share.base.fields ; i++)
00685 if (mi_recinfo_write(file, &recinfo[i]))
00686 goto err;
00687
00688
00689 if (ftruncate(file, (off_t) share.base.keystart))
00690 goto err;
00691
00692 if (! (flags & HA_DONT_TOUCH_DATA))
00693 {
00694 #ifdef USE_RELOC
00695 if (ftruncate(dfile,share.base.min_pack_length*ci->reloc_rows,))
00696 goto err;
00697 #endif
00698 errpos=2;
00699 if (internal::my_close(dfile,MYF(0)))
00700 goto err;
00701 }
00702 errpos=0;
00703 THR_LOCK_myisam.unlock();
00704 if (internal::my_close(file,MYF(0)))
00705 goto err;
00706 free((char*) rec_per_key_part);
00707 return(0);
00708
00709 err:
00710 THR_LOCK_myisam.unlock();
00711 save_errno=errno;
00712 switch (errpos) {
00713 case 3:
00714 internal::my_close(dfile,MYF(0));
00715
00716 case 2:
00717 if (! (flags & HA_DONT_TOUCH_DATA))
00718 internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
00719 MY_UNPACK_FILENAME | MY_APPEND_EXT),
00720 MYF(0));
00721
00722 case 1:
00723 internal::my_close(file,MYF(0));
00724 if (! (flags & HA_DONT_TOUCH_DATA))
00725 internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
00726 MY_UNPACK_FILENAME | MY_APPEND_EXT),
00727 MYF(0));
00728 }
00729 free((char*) rec_per_key_part);
00730 return(errno=save_errno);
00731 }
00732
00733
00734 uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
00735 {
00736 assert(def >= 2 && def <= 7);
00737 if (file_length)
00738 {
00739 #ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
00740 if (file_length >= 1ULL << 56)
00741 def=8;
00742 else
00743 #endif
00744 if (file_length >= 1ULL << 48)
00745 def=7;
00746 else if (file_length >= 1ULL << 40)
00747 def=6;
00748 else if (file_length >= 1ULL << 32)
00749 def=5;
00750 else if (file_length >= 1ULL << 24)
00751 def=4;
00752 else if (file_length >= 1ULL << 16)
00753 def=3;
00754 else
00755 def=2;
00756 }
00757 return def;
00758 }