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