~drizzle-trunk/drizzle/development

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