1/*
2 Copyright (c) 2000, 2011, Oracle and/or its affiliates
3 Copyright (c) 2009, 2013, Monty Program Ab.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
18/* Create a MyISAM table */
19
20#include "ftdefs.h"
21#include "sp_defs.h"
22#include <my_bit.h>
23
24#ifdef __WIN__
25#include <fcntl.h>
26#endif
27#include <m_ctype.h>
28
29/*
30 Old options is used when recreating database, from myisamchk
31*/
32
33int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
34 uint columns, MI_COLUMNDEF *recinfo,
35 uint uniques, MI_UNIQUEDEF *uniquedefs,
36 MI_CREATE_INFO *ci,uint flags)
37{
38 register uint i,j;
39 File UNINIT_VAR(dfile),UNINIT_VAR(file);
40 int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
41 myf create_flag;
42 uint fields,length,max_key_length,packed,pack_bytes,pointer,real_length_diff,
43 key_length,info_length,key_segs,options,min_key_length_skip,
44 base_pos,long_varchar_count,varchar_length,
45 max_key_block_length,unique_key_parts,fulltext_keys,offset;
46 uint aligned_key_start, block_length, res;
47 uint internal_table= flags & HA_CREATE_INTERNAL_TABLE;
48 ulong reclength, real_reclength,min_pack_length;
49 char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr;
50 char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr= 0;
51 ulong pack_reclength;
52 ulonglong tot_length,max_rows, tmp;
53 enum en_fieldtype type;
54 MYISAM_SHARE share;
55 MI_KEYDEF *keydef,tmp_keydef;
56 MI_UNIQUEDEF *uniquedef;
57 HA_KEYSEG *keyseg,tmp_keyseg;
58 MI_COLUMNDEF *rec;
59 ulong *rec_per_key_part;
60 my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
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));
65
66 if (!ci)
67 {
68 bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
69 ci=&tmp_create_info;
70 }
71
72 if (keys + uniques > MI_MAX_KEY || columns == 0)
73 {
74 DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
75 }
76
77 errpos=0;
78 options=0;
79 bzero((uchar*) &share,sizeof(share));
80
81 if (flags & HA_DONT_TOUCH_DATA)
82 {
83 if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
84 options=ci->old_options &
85 (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
86 HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
87 HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
88 else
89 options=ci->old_options &
90 (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
91 }
92
93 if (ci->reloc_rows > ci->max_rows)
94 ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
95
96 if (!(rec_per_key_part=
97 (ulong*) my_malloc((keys + uniques)*HA_MAX_KEY_SEG*sizeof(long),
98 MYF(MY_WME | MY_ZEROFILL))))
99 DBUG_RETURN(my_errno);
100
101 /* Start by checking fields and field-types used */
102
103 reclength=varchar_length=long_varchar_count=packed=
104 min_pack_length=pack_reclength=0;
105 for (rec=recinfo, fields=0 ;
106 fields != columns ;
107 rec++,fields++)
108 {
109 reclength+=rec->length;
110 if (rec->null_bit)
111 options|= HA_OPTION_NULL_FIELDS;
112
113 if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL &&
114 type != FIELD_CHECK)
115 {
116 packed++;
117 if (type == FIELD_BLOB)
118 {
119 share.base.blobs++;
120 if (pack_reclength != INT_MAX32)
121 {
122 if (rec->length == 4+portable_sizeof_char_ptr)
123 pack_reclength= INT_MAX32;
124 else
125 pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */
126 }
127 }
128 else if (type == FIELD_SKIP_PRESPACE ||
129 type == FIELD_SKIP_ENDSPACE)
130 {
131 if (pack_reclength != INT_MAX32)
132 pack_reclength+= rec->length > 255 ? 2 : 1;
133 min_pack_length++;
134 }
135 else if (type == FIELD_VARCHAR)
136 {
137 varchar_length+= rec->length-1; /* Used for min_pack_length */
138 packed--;
139 pack_reclength++;
140 min_pack_length++;
141 /* We must test for 257 as length includes pack-length */
142 if (MY_TEST(rec->length >= 257))
143 {
144 long_varchar_count++;
145 pack_reclength+= 2; /* May be packed on 3 bytes */
146 }
147 options|= HA_OPTION_NULL_FIELDS; /* Use of mi_checksum() */
148 }
149 else if (type != FIELD_SKIP_ZERO)
150 {
151 min_pack_length+=rec->length;
152 packed--; /* Not a pack record type */
153 }
154 }
155 else /* FIELD_NORMAL */
156 min_pack_length+=rec->length;
157 }
158 if ((packed & 7) == 1)
159 { /* Bad packing, try to remove a zero-field */
160 while (rec != recinfo)
161 {
162 rec--;
163 if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
164 {
165 /*
166 NOTE1: here we change a field type FIELD_SKIP_ZERO ->
167 FIELD_NORMAL
168 */
169 rec->type=(int) FIELD_NORMAL;
170 packed--;
171 min_pack_length++;
172 break;
173 }
174 }
175 }
176
177 if (packed || (flags & HA_PACK_RECORD))
178 options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
179 /* We can't use checksum with static length rows */
180 if (!(options & HA_OPTION_PACK_RECORD))
181 options&= ~HA_OPTION_CHECKSUM;
182 if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
183 min_pack_length+= varchar_length;
184 if (flags & HA_CREATE_TMP_TABLE)
185 {
186 options|= HA_OPTION_TMP_TABLE;
187 create_mode|= O_NOFOLLOW;
188 }
189 if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
190 {
191 options|= HA_OPTION_CHECKSUM;
192 min_pack_length++;
193 }
194 /*
195 Don't set HA_OPTION_NULL_FIELDS if no checksums, as this flag makes
196 that file incompatible with MySQL. This is ok, as this flag is only
197 used if one specifics table level checksums.
198 */
199 if (!(options & HA_OPTION_CHECKSUM))
200 options&= ~HA_OPTION_NULL_FIELDS;
201 if (flags & HA_CREATE_DELAY_KEY_WRITE)
202 options|= HA_OPTION_DELAY_KEY_WRITE;
203 if (flags & HA_CREATE_RELIES_ON_SQL_LAYER)
204 options|= HA_OPTION_RELIES_ON_SQL_LAYER;
205
206 pack_bytes= (packed+7)/8;
207 if (pack_reclength != INT_MAX32)
208 pack_reclength+= reclength+packed +
209 MY_TEST(test_all_bits(options, HA_OPTION_CHECKSUM |
210 HA_OPTION_PACK_RECORD));
211 min_pack_length+= pack_bytes;
212
213 if (!ci->data_file_length && ci->max_rows)
214 {
215 if (pack_reclength == INT_MAX32 ||
216 (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
217 ci->data_file_length= ~(ulonglong) 0;
218 else
219 ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
220 }
221 else if (!ci->max_rows)
222 ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
223 ((options & HA_OPTION_PACK_RECORD) ?
224 3 : 0)));
225
226 if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
227 pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
228 else
229 pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
230 if (!(max_rows=(ulonglong) ci->max_rows))
231 max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
232
233
234 real_reclength=reclength;
235 if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)))
236 {
237 if (reclength <= pointer)
238 reclength=pointer+1; /* reserve place for delete link */
239 }
240 else
241 reclength+= long_varchar_count; /* We need space for varchar! */
242
243 max_key_length=0; tot_length=0 ; key_segs=0;
244 fulltext_keys=0;
245 max_key_block_length=0;
246 share.state.rec_per_key_part=rec_per_key_part;
247 share.state.key_root=key_root;
248 share.state.key_del=key_del;
249 if (uniques)
250 {
251 max_key_block_length= myisam_block_size;
252 max_key_length= MI_UNIQUE_HASH_LENGTH + pointer;
253 }
254
255 for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
256 {
257
258 share.state.key_root[i]= HA_OFFSET_ERROR;
259 min_key_length_skip=length=real_length_diff=0;
260 key_length=pointer;
261 if (keydef->flag & HA_SPATIAL)
262 {
263#ifdef HAVE_SPATIAL
264 /* BAR TODO to support 3D and more dimensions in the future */
265 uint sp_segs=SPDIMS*2;
266 keydef->flag=HA_SPATIAL;
267
268 if (flags & HA_DONT_TOUCH_DATA)
269 {
270 /*
271 called by myisamchk - i.e. table structure was taken from
272 MYI file and SPATIAL key *does have* additional sp_segs keysegs.
273 keydef->seg here points right at the GEOMETRY segment,
274 so we only need to decrease keydef->keysegs.
275 (see recreate_table() in mi_check.c)
276 */
277 keydef->keysegs= 1;
278 }
279
280 for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
281 j++, keyseg++)
282 {
283 if (keyseg->type != HA_KEYTYPE_BINARY &&
284 keyseg->type != HA_KEYTYPE_VARBINARY1 &&
285 keyseg->type != HA_KEYTYPE_VARBINARY2)
286 {
287 my_errno=HA_WRONG_CREATE_OPTION;
288 goto err_no_lock;
289 }
290 }
291 DBUG_ASSERT(keydef->keysegs == 1);
292 keydef->keysegs= sp_segs + 1;
293 key_length+=SPLEN*sp_segs;
294 length++; /* At least one length byte */
295 min_key_length_skip+=SPLEN*2*SPDIMS;
296#else
297 my_errno= HA_ERR_UNSUPPORTED;
298 goto err_no_lock;
299#endif /*HAVE_SPATIAL*/
300 }
301 else if (keydef->flag & HA_FULLTEXT)
302 {
303 keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
304 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
305
306 for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
307 j++, keyseg++)
308 {
309 if (keyseg->type != HA_KEYTYPE_TEXT &&
310 keyseg->type != HA_KEYTYPE_VARTEXT1 &&
311 keyseg->type != HA_KEYTYPE_VARTEXT2)
312 {
313 my_errno=HA_WRONG_CREATE_OPTION;
314 goto err_no_lock;
315 }
316 if (!(keyseg->flag & HA_BLOB_PART) &&
317 (keyseg->type == HA_KEYTYPE_VARTEXT1 ||
318 keyseg->type == HA_KEYTYPE_VARTEXT2))
319 {
320 /* Make a flag that this is a VARCHAR */
321 keyseg->flag|= HA_VAR_LENGTH_PART;
322 /* Store in bit_start number of bytes used to pack the length */
323 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)?
324 1 : 2);
325 }
326 }
327
328 fulltext_keys++;
329 key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
330 length++; /* At least one length byte */
331 min_key_length_skip+=HA_FT_MAXBYTELEN;
332 real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
333 }
334 else
335 {
336 /* Test if prefix compression */
337 if (keydef->flag & HA_PACK_KEY)
338 {
339 /* Can't use space_compression on number keys */
340 if ((keydef->seg[0].flag & HA_SPACE_PACK) &&
341 keydef->seg[0].type == (int) HA_KEYTYPE_NUM)
342 keydef->seg[0].flag&= ~HA_SPACE_PACK;
343
344 /* Only use HA_PACK_KEY when first segment is a variable length key */
345 if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
346 HA_VAR_LENGTH_PART)))
347 {
348 /* pack relative to previous key */
349 keydef->flag&= ~HA_PACK_KEY;
350 keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
351 }
352 else
353 {
354 keydef->seg[0].flag|=HA_PACK_KEY; /* for easyer intern test */
355 keydef->flag|=HA_VAR_LENGTH_KEY;
356 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
357 }
358 }
359 if (keydef->flag & HA_BINARY_PACK_KEY)
360 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
361
362 if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment)
363 share.base.auto_key=i+1;
364 for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++)
365 {
366 /* numbers are stored with high by first to make compression easier */
367 switch (keyseg->type) {
368 case HA_KEYTYPE_SHORT_INT:
369 case HA_KEYTYPE_LONG_INT:
370 case HA_KEYTYPE_FLOAT:
371 case HA_KEYTYPE_DOUBLE:
372 case HA_KEYTYPE_USHORT_INT:
373 case HA_KEYTYPE_ULONG_INT:
374 case HA_KEYTYPE_LONGLONG:
375 case HA_KEYTYPE_ULONGLONG:
376 case HA_KEYTYPE_INT24:
377 case HA_KEYTYPE_UINT24:
378 case HA_KEYTYPE_INT8:
379 keyseg->flag|= HA_SWAP_KEY;
380 break;
381 case HA_KEYTYPE_VARTEXT1:
382 case HA_KEYTYPE_VARTEXT2:
383 case HA_KEYTYPE_VARBINARY1:
384 case HA_KEYTYPE_VARBINARY2:
385 if (!(keyseg->flag & HA_BLOB_PART))
386 {
387 /* Make a flag that this is a VARCHAR */
388 keyseg->flag|= HA_VAR_LENGTH_PART;
389 /* Store in bit_start number of bytes used to pack the length */
390 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
391 keyseg->type == HA_KEYTYPE_VARBINARY1) ?
392 1 : 2);
393 }
394 break;
395 default:
396 break;
397 }
398 if (keyseg->flag & HA_SPACE_PACK)
399 {
400 DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
401 keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
402 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
403 length++; /* At least one length byte */
404 min_key_length_skip+=keyseg->length;
405 if (keyseg->length >= 255)
406 { /* prefix may be 3 bytes */
407 min_key_length_skip+=2;
408 length+=2;
409 }
410 }
411 if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
412 {
413 DBUG_ASSERT(!test_all_bits(keyseg->flag,
414 (HA_VAR_LENGTH_PART | HA_BLOB_PART)));
415 keydef->flag|=HA_VAR_LENGTH_KEY;
416 length++; /* At least one length byte */
417 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
418 min_key_length_skip+=keyseg->length;
419 if (keyseg->length >= 255)
420 { /* prefix may be 3 bytes */
421 min_key_length_skip+=2;
422 length+=2;
423 }
424 }
425 key_length+= keyseg->length;
426 if (keyseg->null_bit)
427 {
428 key_length++;
429 options|=HA_OPTION_PACK_KEYS;
430 keyseg->flag|=HA_NULL_PART;
431 keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY;
432 }
433 }
434 } /* if HA_FULLTEXT */
435 key_segs+=keydef->keysegs;
436 if (keydef->keysegs > HA_MAX_KEY_SEG)
437 {
438 my_errno=HA_WRONG_CREATE_OPTION;
439 goto err_no_lock;
440 }
441 /*
442 key_segs may be 0 in the case when we only want to be able to
443 add on row into the table. This can happen with some DISTINCT queries
444 in MySQL
445 */
446 if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME &&
447 key_segs)
448 share.state.rec_per_key_part[key_segs-1]=1L;
449 length+=key_length;
450 /* Get block length for key, if defined by user */
451 block_length= (keydef->block_length ?
452 my_round_up_to_next_power(keydef->block_length) :
453 myisam_block_size);
454 block_length= MY_MAX(block_length, MI_MIN_KEY_BLOCK_LENGTH);
455 block_length= MY_MIN(block_length, MI_MAX_KEY_BLOCK_LENGTH);
456
457 keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
458 pointer,MI_MAX_KEYPTR_SIZE,
459 block_length);
460 if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
461 length >= HA_MAX_KEY_BUFF)
462 {
463 my_errno=HA_WRONG_CREATE_OPTION;
464 goto err_no_lock;
465 }
466 set_if_bigger(max_key_block_length,keydef->block_length);
467 keydef->keylength= (uint16) key_length;
468 keydef->minlength= (uint16) (length-min_key_length_skip);
469 keydef->maxlength= (uint16) length;
470
471 if (length > max_key_length)
472 max_key_length= length;
473 tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/
474 (length*2)))*
475 (ulong) keydef->block_length;
476 }
477 for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
478 key_del[i]=HA_OFFSET_ERROR;
479
480 unique_key_parts=0;
481 for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++)
482 {
483 uniquedef->key=keys+i;
484 unique_key_parts+=uniquedef->keysegs;
485 share.state.key_root[keys+i]= HA_OFFSET_ERROR;
486 tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/
487 ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))*
488 (ulong) myisam_block_size;
489 }
490 keys+=uniques; /* Each unique has 1 key */
491 key_segs+=uniques; /* Each unique has 1 key seg */
492
493 base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
494 max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
495 MI_STATE_KEYBLOCK_SIZE+
496 key_segs*MI_STATE_KEYSEG_SIZE);
497 info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
498 keys * MI_KEYDEF_SIZE+
499 uniques * MI_UNIQUEDEF_SIZE +
500 (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
501 columns*MI_COLUMNDEF_SIZE);
502 DBUG_PRINT("info", ("info_length: %u", info_length));
503 /* There are only 16 bits for the total header length. */
504 if (info_length > 65535)
505 {
506 my_printf_error(HA_WRONG_CREATE_OPTION,
507 "MyISAM table '%s' has too many columns and/or "
508 "indexes and/or unique constraints.",
509 MYF(0), name + dirname_length(name));
510 my_errno= HA_WRONG_CREATE_OPTION;
511 goto err_no_lock;
512 }
513
514 bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
515 ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
516 HA_OPTION_COMPRESS_RECORD |
517 HA_OPTION_TEMP_COMPRESS_RECORD: 0);
518 mi_int2store(share.state.header.options,ci->old_options);
519 mi_int2store(share.state.header.header_length,info_length);
520 mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE);
521 mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
522 mi_int2store(share.state.header.base_pos,base_pos);
523 share.state.header.language= (ci->language ?
524 ci->language : default_charset_info->number);
525 share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
526
527 share.state.dellink = HA_OFFSET_ERROR;
528 share.state.process= (ulong) getpid();
529 share.state.unique= (ulong) 0;
530 share.state.update_count=(ulong) 0;
531 share.state.version= (ulong) time((time_t*) 0);
532 share.state.sortkey= (ushort) ~0;
533 share.state.auto_increment=ci->auto_increment;
534 share.options=options;
535 share.base.rec_reflength=pointer;
536 /* Get estimate for index file length (this may be wrong for FT keys) */
537 tmp= (tot_length + max_key_block_length * keys *
538 MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
539 /*
540 use maximum of key_file_length we calculated and key_file_length value we
541 got from MYI file header (see also myisampack.c:save_state)
542 */
543 share.base.key_reflength=
544 mi_get_pointer_length(MY_MAX(ci->key_file_length,tmp),3);
545 share.base.keys= share.state.header.keys= keys;
546 share.state.header.uniques= uniques;
547 share.state.header.fulltext_keys= fulltext_keys;
548 mi_int2store(share.state.header.key_parts,key_segs);
549 mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
550
551 mi_set_all_keys_active(share.state.key_map, keys);
552 aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
553 max_key_block_length :
554 myisam_block_size);
555
556 share.base.keystart= share.state.state.key_file_length=
557 MY_ALIGN(info_length, aligned_key_start);
558 share.base.max_key_block_length=max_key_block_length;
559 share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
560 share.base.records=ci->max_rows;
561 share.base.reloc= ci->reloc_rows;
562 share.base.reclength=real_reclength;
563 share.base.pack_reclength= reclength + MY_TEST(options & HA_OPTION_CHECKSUM);
564 share.base.max_pack_length=pack_reclength;
565 share.base.min_pack_length=min_pack_length;
566 share.base.pack_bits= pack_bytes;
567 share.base.fields=fields;
568 share.base.pack_fields=packed;
569
570 /* max_data_file_length and max_key_file_length are recalculated on open */
571 if (options & HA_OPTION_TMP_TABLE)
572 share.base.max_data_file_length=(my_off_t) ci->data_file_length;
573
574 share.base.min_block_length=
575 (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
576 ! share.base.blobs) ?
577 MY_MAX(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
578 MI_EXTEND_BLOCK_LENGTH;
579 if (! (flags & HA_DONT_TOUCH_DATA))
580 share.state.create_time= time((time_t*) 0);
581
582 if (!internal_table)
583 mysql_mutex_lock(&THR_LOCK_myisam);
584
585 /*
586 NOTE: For test_if_reopen() we need a real path name. Hence we need
587 MY_RETURN_REAL_PATH for every fn_format(filename, ...).
588 */
589 if (ci->index_file_name)
590 {
591 char *iext= strrchr(ci->index_file_name, '.');
592 int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
593 if (options & HA_OPTION_TMP_TABLE)
594 {
595 char *path;
596 /* chop off the table name, tempory tables use generated name */
597 if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
598 *path= '\0';
599 fn_format(kfilename, name, ci->index_file_name, MI_NAME_IEXT,
600 MY_REPLACE_DIR | MY_UNPACK_FILENAME |
601 MY_RETURN_REAL_PATH | MY_APPEND_EXT);
602 }
603 else
604 {
605 fn_format(kfilename, ci->index_file_name, "", MI_NAME_IEXT,
606 MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
607 (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
608 }
609 fn_format(klinkname, name, "", MI_NAME_IEXT,
610 MY_UNPACK_FILENAME|MY_APPEND_EXT);
611 klinkname_ptr= klinkname;
612 /*
613 Don't create the table if the link or file exists to ensure that one
614 doesn't accidently destroy another table.
615 */
616 create_flag=0;
617 }
618 else
619 {
620 char *iext= strrchr(name, '.');
621 int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
622 fn_format(kfilename, name, "", MI_NAME_IEXT,
623 MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
624 (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
625 klinkname_ptr= 0;
626 /* Replace the current file */
627 create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
628 }
629
630 /*
631 If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
632 but no entry is made in the table cache for them.
633 A TRUNCATE command checks for the table in the cache only and could
634 be fooled to believe, the table is not open.
635 Pull the emergency brake in this situation. (Bug #8306)
636
637 NOTE: The filename is compared against unique_file_name of every
638 open table. Hence we need a real path here.
639 */
640 if (!internal_table && test_if_reopen(kfilename))
641 {
642 my_printf_error(HA_ERR_TABLE_EXIST, "MyISAM table '%s' is in use "
643 "(most likely by a MERGE table). Try FLUSH TABLES.",
644 MYF(0), name + dirname_length(name));
645 my_errno= HA_ERR_TABLE_EXIST;
646 goto err;
647 }
648
649 if ((file= mysql_file_create_with_symlink(mi_key_file_kfile,
650 klinkname_ptr, kfilename, 0,
651 create_mode,
652 MYF(MY_WME | create_flag))) < 0)
653 goto err;
654 errpos=1;
655
656 if (!(flags & HA_DONT_TOUCH_DATA))
657 {
658 {
659 if (ci->data_file_name)
660 {
661 char *dext= strrchr(ci->data_file_name, '.');
662 int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
663
664 if (options & HA_OPTION_TMP_TABLE)
665 {
666 char *path;
667 /* chop off the table name, tempory tables use generated name */
668 if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
669 *path= '\0';
670 fn_format(dfilename, name, ci->data_file_name, MI_NAME_DEXT,
671 MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
672 }
673 else
674 {
675 fn_format(dfilename, ci->data_file_name, "", MI_NAME_DEXT,
676 MY_UNPACK_FILENAME |
677 (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
678 }
679
680 fn_format(dlinkname, name, "",MI_NAME_DEXT,
681 MY_UNPACK_FILENAME | MY_APPEND_EXT);
682 dlinkname_ptr= dlinkname;
683 create_flag=0;
684 }
685 else
686 {
687 fn_format(dfilename,name,"", MI_NAME_DEXT,
688 MY_UNPACK_FILENAME | MY_APPEND_EXT);
689 dlinkname_ptr= 0;
690 create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
691 }
692 if ((dfile=
693 mysql_file_create_with_symlink(mi_key_file_dfile,
694 dlinkname_ptr, dfilename, 0,
695 create_mode,
696 MYF(MY_WME | create_flag))) < 0)
697 goto err;
698 }
699 errpos=3;
700 }
701
702 DBUG_PRINT("info", ("write state info and base info"));
703 if (mi_state_info_write(file, &share.state, 2) ||
704 mi_base_info_write(file, &share.base))
705 goto err;
706#ifndef DBUG_OFF
707 if ((uint) mysql_file_tell(file, MYF(0)) != base_pos + MI_BASE_INFO_SIZE)
708 {
709 uint pos=(uint) mysql_file_tell(file, MYF(0));
710 DBUG_PRINT("warning",("base_length: %d != used_length: %d",
711 base_pos+ MI_BASE_INFO_SIZE, pos));
712 }
713#endif
714
715 /* Write key and keyseg definitions */
716 DBUG_PRINT("info", ("write key and keyseg definitions"));
717 for (i=0 ; i < share.base.keys - uniques; i++)
718 {
719 uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
720
721 if (mi_keydef_write(file, &keydefs[i]))
722 goto err;
723 for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
724 if (mi_keyseg_write(file, &keydefs[i].seg[j]))
725 goto err;
726#ifdef HAVE_SPATIAL
727 for (j=0 ; j < sp_segs ; j++)
728 {
729 HA_KEYSEG sseg;
730 sseg.type=SPTYPE;
731 sseg.language= 7; /* Binary */
732 sseg.null_bit=0;
733 sseg.bit_start=0;
734 sseg.bit_length= 0;
735 sseg.bit_pos= 0;
736 sseg.length=SPLEN;
737 sseg.null_pos=0;
738 sseg.start=j*SPLEN;
739 sseg.flag= HA_SWAP_KEY;
740 if (mi_keyseg_write(file, &sseg))
741 goto err;
742 }
743#endif
744 }
745 /* Create extra keys for unique definitions */
746 offset= real_reclength - uniques * MI_UNIQUE_HASH_LENGTH;
747 bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
748 bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
749 for (i=0; i < uniques ; i++)
750 {
751 tmp_keydef.keysegs=1;
752 tmp_keydef.flag= HA_UNIQUE_CHECK;
753 tmp_keydef.block_length= (uint16)myisam_block_size;
754 tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
755 tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
756 tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
757 tmp_keyseg.length= MI_UNIQUE_HASH_LENGTH;
758 tmp_keyseg.start= offset;
759 offset+= MI_UNIQUE_HASH_LENGTH;
760 if (mi_keydef_write(file,&tmp_keydef) ||
761 mi_keyseg_write(file,(&tmp_keyseg)))
762 goto err;
763 }
764
765 /* Save unique definition */
766 DBUG_PRINT("info", ("write unique definitions"));
767 for (i=0 ; i < share.state.header.uniques ; i++)
768 {
769 HA_KEYSEG *keyseg_end;
770 keyseg= uniquedefs[i].seg;
771 if (mi_uniquedef_write(file, &uniquedefs[i]))
772 goto err;
773 for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
774 keyseg < keyseg_end;
775 keyseg++)
776 {
777 switch (keyseg->type) {
778 case HA_KEYTYPE_VARTEXT1:
779 case HA_KEYTYPE_VARTEXT2:
780 case HA_KEYTYPE_VARBINARY1:
781 case HA_KEYTYPE_VARBINARY2:
782 if (!(keyseg->flag & HA_BLOB_PART))
783 {
784 keyseg->flag|= HA_VAR_LENGTH_PART;
785 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
786 keyseg->type == HA_KEYTYPE_VARBINARY1) ?
787 1 : 2);
788 }
789 break;
790 default:
791 break;
792 }
793 if (mi_keyseg_write(file, keyseg))
794 goto err;
795 }
796 }
797 DBUG_PRINT("info", ("write field definitions"));
798 for (i=0 ; i < share.base.fields ; i++)
799 if (mi_recinfo_write(file, &recinfo[i]))
800 goto err;
801
802#ifndef DBUG_OFF
803 if ((uint) mysql_file_tell(file, MYF(0)) != info_length)
804 {
805 uint pos= (uint) mysql_file_tell(file, MYF(0));
806 DBUG_PRINT("warning",("info_length: %d != used_length: %d",
807 info_length, pos));
808 }
809#endif
810
811 /* Enlarge files */
812 DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
813 if (mysql_file_chsize(file, (ulong) share.base.keystart, 0, MYF(0)))
814 goto err;
815
816 if (! (flags & HA_DONT_TOUCH_DATA))
817 {
818#ifdef USE_RELOC
819 if (mysql_file_chsize(dfile, share.base.min_pack_length*ci->reloc_rows,
820 0, MYF(0)))
821 goto err;
822#endif
823 errpos=2;
824 if (mysql_file_close(dfile, MYF(0)))
825 goto err;
826 }
827 errpos=0;
828 if (!internal_table)
829 mysql_mutex_unlock(&THR_LOCK_myisam);
830 res= 0;
831 if (mysql_file_close(file, MYF(0)))
832 res= my_errno;
833 my_free(rec_per_key_part);
834 DBUG_RETURN(res);
835
836err:
837 if (!internal_table)
838 mysql_mutex_unlock(&THR_LOCK_myisam);
839
840err_no_lock:
841 save_errno=my_errno;
842 switch (errpos) {
843 case 3:
844 (void) mysql_file_close(dfile, MYF(0));
845 /* fall through */
846 case 2:
847 if (! (flags & HA_DONT_TOUCH_DATA))
848 {
849 mysql_file_delete(mi_key_file_dfile, dfilename, MYF(0));
850 if (dlinkname_ptr)
851 mysql_file_delete(mi_key_file_dfile, dlinkname_ptr, MYF(0));
852 }
853 /* fall through */
854 case 1:
855 (void) mysql_file_close(file, MYF(0));
856 if (! (flags & HA_DONT_TOUCH_DATA))
857 {
858 mysql_file_delete(mi_key_file_kfile, kfilename, MYF(0));
859 if (klinkname_ptr)
860 mysql_file_delete(mi_key_file_kfile, klinkname_ptr, MYF(0));
861 }
862 }
863 my_free(rec_per_key_part);
864 DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */
865}
866
867
868uint mi_get_pointer_length(ulonglong file_length, uint def)
869{
870 DBUG_ASSERT(def >= 2 && def <= 7);
871 if (file_length) /* If not default */
872 {
873#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
874 if (file_length >= 1ULL << 56)
875 def=8;
876 else
877#endif
878 if (file_length >= 1ULL << 48)
879 def=7;
880 else if (file_length >= 1ULL << 40)
881 def=6;
882 else if (file_length >= 1ULL << 32)
883 def=5;
884 else if (file_length >= 1ULL << 24)
885 def=4;
886 else if (file_length >= 1ULL << 16)
887 def=3;
888 else
889 def=2;
890 }
891 return def;
892}
893