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