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