~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/mi_create.cc

  • Committer: Brian Aker
  • Date: 2009-05-30 22:30:05 UTC
  • mto: This revision was merged to the branch mainline in revision 1045.
  • Revision ID: brian@gaz-20090530223005-hmylm6iywddfentm
A lot of little cleanups (most based off lcov)

Show diffs side-by-side

added added

removed removed

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