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