~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to plugin/myisam/mi_create.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
        case HA_KEYTYPE_UINT24:
 
269
          keyseg->flag|= HA_SWAP_KEY;
 
270
          break;
 
271
        case HA_KEYTYPE_VARTEXT1:
 
272
        case HA_KEYTYPE_VARTEXT2:
 
273
        case HA_KEYTYPE_VARBINARY1:
 
274
        case HA_KEYTYPE_VARBINARY2:
 
275
          if (!(keyseg->flag & HA_BLOB_PART))
 
276
          {
 
277
            /* Make a flag that this is a VARCHAR */
 
278
            keyseg->flag|= HA_VAR_LENGTH_PART;
 
279
            /* Store in bit_start number of bytes used to pack the length */
 
280
            keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
 
281
                                 keyseg->type == HA_KEYTYPE_VARBINARY1) ?
 
282
                                1 : 2);
 
283
          }
 
284
          break;
 
285
        default:
 
286
          break;
 
287
        }
 
288
        if (keyseg->flag & HA_SPACE_PACK)
 
289
        {
 
290
          assert(!(keyseg->flag & HA_VAR_LENGTH_PART));
 
291
          keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
 
292
          options|=HA_OPTION_PACK_KEYS;         /* Using packed keys */
 
293
          length++;                             /* At least one length byte */
 
294
          min_key_length_skip+=keyseg->length;
 
295
          if (keyseg->length >= 255)
 
296
          {                                     /* prefix may be 3 bytes */
 
297
            min_key_length_skip+=2;
 
298
            length+=2;
 
299
          }
 
300
        }
 
301
        if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
302
        {
 
303
          assert(!test_all_bits(keyseg->flag,
 
304
                                    (HA_VAR_LENGTH_PART | HA_BLOB_PART)));
 
305
          keydef->flag|=HA_VAR_LENGTH_KEY;
 
306
          length++;                             /* At least one length byte */
 
307
          options|=HA_OPTION_PACK_KEYS;         /* Using packed keys */
 
308
          min_key_length_skip+=keyseg->length;
 
309
          if (keyseg->length >= 255)
 
310
          {                                     /* prefix may be 3 bytes */
 
311
            min_key_length_skip+=2;
 
312
            length+=2;
 
313
          }
 
314
        }
 
315
        key_length+= keyseg->length;
 
316
        if (keyseg->null_bit)
 
317
        {
 
318
          key_length++;
 
319
          options|=HA_OPTION_PACK_KEYS;
 
320
          keyseg->flag|=HA_NULL_PART;
 
321
          keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY;
 
322
        }
 
323
      }
 
324
    } /* if HA_FULLTEXT */
 
325
    key_segs+=keydef->keysegs;
 
326
    if (keydef->keysegs > MI_MAX_KEY_SEG)
 
327
    {
 
328
      errno=HA_WRONG_CREATE_OPTION;
 
329
      goto err;
 
330
    }
 
331
    /*
 
332
      key_segs may be 0 in the case when we only want to be able to
 
333
      add on row into the table. This can happen with some DISTINCT queries
 
334
      in MySQL
 
335
    */
 
336
    if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME &&
 
337
        key_segs)
 
338
      share.state.rec_per_key_part[key_segs-1]=1L;
 
339
    length+=key_length;
 
340
    /* Get block length for key, if defined by user */
 
341
    block_length= (keydef->block_length ?
 
342
                   my_round_up_to_next_power(keydef->block_length) :
 
343
                   myisam_block_size);
 
344
    block_length= max(block_length, (uint32_t)MI_MIN_KEY_BLOCK_LENGTH);
 
345
    block_length= min(block_length, (uint32_t)MI_MAX_KEY_BLOCK_LENGTH);
 
346
 
 
347
    keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
 
348
                                                 pointer,MI_MAX_KEYPTR_SIZE,
 
349
                                                 block_length);
 
350
    if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
 
351
        length >= MI_MAX_KEY_BUFF)
 
352
    {
 
353
      errno=HA_WRONG_CREATE_OPTION;
 
354
      goto err;
 
355
    }
 
356
    set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
 
357
    keydef->keylength= (uint16_t) key_length;
 
358
    keydef->minlength= (uint16_t) (length-min_key_length_skip);
 
359
    keydef->maxlength= (uint16_t) length;
 
360
 
 
361
    if (length > max_key_length)
 
362
      max_key_length= length;
 
363
    tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/
 
364
                                    (length*2)))*
 
365
      (ulong) keydef->block_length;
 
366
  }
 
367
  for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
 
368
    key_del[i]=HA_OFFSET_ERROR;
 
369
 
 
370
  unique_key_parts=0;
 
371
  offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
 
372
  for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++)
 
373
  {
 
374
    uniquedef->key=keys+i;
 
375
    unique_key_parts+=uniquedef->keysegs;
 
376
    share.state.key_root[keys+i]= HA_OFFSET_ERROR;
 
377
    tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/
 
378
                         ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))*
 
379
                         (ulong) myisam_block_size;
 
380
  }
 
381
  keys+=uniques;                                /* Each unique has 1 key */
 
382
  key_segs+=uniques;                            /* Each unique has 1 key seg */
 
383
 
 
384
  base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
 
385
            max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
 
386
            MI_STATE_KEYBLOCK_SIZE+
 
387
            key_segs*MI_STATE_KEYSEG_SIZE);
 
388
  info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
 
389
                               keys * MI_KEYDEF_SIZE+
 
390
                               uniques * MI_UNIQUEDEF_SIZE +
 
391
                               (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
 
392
                               columns*MI_COLUMNDEF_SIZE);
 
393
  /* There are only 16 bits for the total header length. */
 
394
  if (info_length > 65535)
 
395
  {
 
396
    my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
 
397
                    "indexes and/or unique constraints.",
 
398
                    MYF(0), name + internal::dirname_length(name));
 
399
    errno= HA_WRONG_CREATE_OPTION;
 
400
    goto err;
 
401
  }
 
402
 
 
403
  memmove(share.state.header.file_version,myisam_file_magic,4);
 
404
  ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
 
405
                        HA_OPTION_COMPRESS_RECORD |
 
406
                        HA_OPTION_TEMP_COMPRESS_RECORD: 0);
 
407
  mi_int2store(share.state.header.options,ci->old_options);
 
408
  mi_int2store(share.state.header.header_length,info_length);
 
409
  mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE);
 
410
  mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
 
411
  mi_int2store(share.state.header.base_pos,base_pos);
 
412
  share.state.header.language= (ci->language ?
 
413
                                ci->language : default_charset_info->number);
 
414
  share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
 
415
 
 
416
  share.state.dellink = HA_OFFSET_ERROR;
 
417
  share.state.process=  (ulong) getpid();
 
418
  share.state.unique=   (ulong) 0;
 
419
  share.state.update_count=(ulong) 0;
 
420
  share.state.version=  (ulong) time((time_t*) 0);
 
421
  share.state.sortkey=  UINT16_MAX;
 
422
  share.state.auto_increment=ci->auto_increment;
 
423
  share.options=options;
 
424
  share.base.rec_reflength=pointer;
 
425
  /* Get estimate for index file length (this may be wrong for FT keys) */
 
426
  tmp= (tot_length + max_key_block_length * keys *
 
427
        MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
 
428
  /*
 
429
    use maximum of key_file_length we calculated and key_file_length value we
 
430
    got from MYI file header (see also myisampack.c:save_state)
 
431
  */
 
432
  share.base.key_reflength=
 
433
    mi_get_pointer_length(max(ci->key_file_length,tmp),3);
 
434
  share.base.keys= share.state.header.keys= keys;
 
435
  share.state.header.uniques= uniques;
 
436
  share.state.header.fulltext_keys= fulltext_keys;
 
437
  mi_int2store(share.state.header.key_parts,key_segs);
 
438
  mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
 
439
 
 
440
  mi_set_all_keys_active(share.state.key_map, keys);
 
441
  aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
 
442
                                               max_key_block_length :
 
443
                                               myisam_block_size);
 
444
 
 
445
  share.base.keystart= share.state.state.key_file_length=
 
446
    MY_ALIGN(info_length, aligned_key_start);
 
447
  share.base.max_key_block_length=max_key_block_length;
 
448
  share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
 
449
  share.base.records=ci->max_rows;
 
450
  share.base.reloc=  ci->reloc_rows;
 
451
  share.base.reclength=real_reclength;
 
452
  share.base.pack_reclength=reclength;
 
453
  share.base.max_pack_length=pack_reclength;
 
454
  share.base.min_pack_length=min_pack_length;
 
455
  share.base.pack_bits=packed;
 
456
  share.base.fields=fields;
 
457
  share.base.pack_fields=packed;
 
458
 
 
459
  /* max_data_file_length and max_key_file_length are recalculated on open */
 
460
  if (options & HA_OPTION_TMP_TABLE)
 
461
    share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
 
462
 
 
463
  share.base.min_block_length=
 
464
    (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
 
465
     ! share.base.blobs) ?
 
466
    max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
 
467
    MI_EXTEND_BLOCK_LENGTH;
 
468
  if (! (flags & HA_DONT_TOUCH_DATA))
 
469
    share.state.create_time= (long) time((time_t*) 0);
 
470
 
 
471
  pthread_mutex_lock(&THR_LOCK_myisam);
 
472
 
 
473
  /*
 
474
    NOTE: For test_if_reopen() we need a real path name. Hence we need
 
475
    MY_RETURN_REAL_PATH for every internal::fn_format(filename, ...).
 
476
  */
 
477
  if (ci->index_file_name)
 
478
  {
 
479
    char *iext= strrchr((char *)ci->index_file_name, '.');
 
480
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
 
481
    if (options & HA_OPTION_TMP_TABLE)
 
482
    {
 
483
      char *path;
 
484
      /* chop off the table name, tempory tables use generated name */
 
485
      if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
 
486
        *path= '\0';
 
487
      internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
 
488
                MY_REPLACE_DIR | MY_UNPACK_FILENAME |
 
489
                MY_RETURN_REAL_PATH | MY_APPEND_EXT);
 
490
    }
 
491
    else
 
492
    {
 
493
      internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
 
494
                MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
 
495
                (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
 
496
    }
 
497
    internal::fn_format(linkname, name, "", MI_NAME_IEXT,
 
498
              MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
499
    linkname_ptr=linkname;
 
500
    /*
 
501
      Don't create the table if the link or file exists to ensure that one
 
502
      doesn't accidently destroy another table.
 
503
    */
 
504
    create_flag=0;
 
505
  }
 
506
  else
 
507
  {
 
508
    char *iext= strrchr((char *)name, '.');
 
509
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
 
510
    internal::fn_format(filename, name, "", MI_NAME_IEXT,
 
511
              MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
 
512
              (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
 
513
    linkname_ptr=0;
 
514
    /* Replace the current file */
 
515
    create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
 
516
  }
 
517
 
 
518
  /*
 
519
    If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
 
520
    but no entry is made in the table cache for them.
 
521
    A TRUNCATE command checks for the table in the cache only and could
 
522
    be fooled to believe, the table is not open.
 
523
    Pull the emergency brake in this situation. (Bug #8306)
 
524
 
 
525
    NOTE: The filename is compared against unique_file_name of every
 
526
    open table. Hence we need a real path here.
 
527
  */
 
528
  if (test_if_reopen(filename))
 
529
  {
 
530
    my_printf_error(0, "MyISAM table '%s' is in use "
 
531
                    "(most likely by a MERGE table). Try FLUSH TABLES.",
 
532
                    MYF(0), name + internal::dirname_length(name));
 
533
    errno= HA_ERR_TABLE_EXIST;
 
534
    goto err;
 
535
  }
 
536
 
 
537
  if ((file= internal::my_create_with_symlink(linkname_ptr,
 
538
                                              filename,
 
539
                                              0,
 
540
                                              create_mode,
 
541
                                              MYF(MY_WME | create_flag))) < 0)
 
542
    goto err;
 
543
  errpos=1;
 
544
 
 
545
  if (!(flags & HA_DONT_TOUCH_DATA))
 
546
  {
 
547
    {
 
548
      if (ci->data_file_name)
 
549
      {
 
550
        char *dext= strrchr((char *)ci->data_file_name, '.');
 
551
        int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
 
552
 
 
553
        if (options & HA_OPTION_TMP_TABLE)
 
554
        {
 
555
          char *path;
 
556
          /* chop off the table name, tempory tables use generated name */
 
557
          if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
 
558
            *path= '\0';
 
559
          internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
 
560
                    MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
 
561
        }
 
562
        else
 
563
        {
 
564
          internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
 
565
                    MY_UNPACK_FILENAME |
 
566
                    (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
 
567
        }
 
568
 
 
569
        internal::fn_format(linkname, name, "",MI_NAME_DEXT,
 
570
                  MY_UNPACK_FILENAME | MY_APPEND_EXT);
 
571
        linkname_ptr=linkname;
 
572
        create_flag=0;
 
573
      }
 
574
      else
 
575
      {
 
576
        internal::fn_format(filename,name,"", MI_NAME_DEXT,
 
577
                  MY_UNPACK_FILENAME | MY_APPEND_EXT);
 
578
        linkname_ptr=0;
 
579
        create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
 
580
      }
 
581
      if ((dfile= internal::my_create_with_symlink(linkname_ptr,
 
582
                                                   filename, 0, create_mode,
 
583
                                                   MYF(MY_WME | create_flag))) < 0)
 
584
        goto err;
 
585
    }
 
586
    errpos=3;
 
587
  }
 
588
 
 
589
  if (mi_state_info_write(file, &share.state, 2) ||
 
590
      mi_base_info_write(file, &share.base))
 
591
    goto err;
 
592
 
 
593
  /* Write key and keyseg definitions */
 
594
  for (i=0 ; i < share.base.keys - uniques; i++)
 
595
  {
 
596
    uint32_t sp_segs= 0;
 
597
 
 
598
    if (mi_keydef_write(file, &keydefs[i]))
 
599
      goto err;
 
600
    for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
 
601
      if (mi_keyseg_write(file, &keydefs[i].seg[j]))
 
602
       goto err;
 
603
  }
 
604
  /* Create extra keys for unique definitions */
 
605
  offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
 
606
  memset(&tmp_keydef, 0, sizeof(tmp_keydef));
 
607
  memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
 
608
  for (i=0; i < uniques ; i++)
 
609
  {
 
610
    tmp_keydef.keysegs=1;
 
611
    tmp_keydef.flag=            HA_UNIQUE_CHECK;
 
612
    tmp_keydef.block_length=    (uint16_t)myisam_block_size;
 
613
    tmp_keydef.keylength=       MI_UNIQUE_HASH_LENGTH + pointer;
 
614
    tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
 
615
    tmp_keyseg.type=            MI_UNIQUE_HASH_TYPE;
 
616
    tmp_keyseg.length=          MI_UNIQUE_HASH_LENGTH;
 
617
    tmp_keyseg.start=           offset;
 
618
    offset+=                    MI_UNIQUE_HASH_LENGTH;
 
619
    if (mi_keydef_write(file,&tmp_keydef) ||
 
620
        mi_keyseg_write(file,(&tmp_keyseg)))
 
621
      goto err;
 
622
  }
 
623
 
 
624
  /* Save unique definition */
 
625
  for (i=0 ; i < share.state.header.uniques ; i++)
 
626
  {
 
627
    HA_KEYSEG *keyseg_end;
 
628
    keyseg= uniquedefs[i].seg;
 
629
    if (mi_uniquedef_write(file, &uniquedefs[i]))
 
630
      goto err;
 
631
    for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
 
632
         keyseg < keyseg_end;
 
633
         keyseg++)
 
634
    {
 
635
      switch (keyseg->type) {
 
636
      case HA_KEYTYPE_VARTEXT1:
 
637
      case HA_KEYTYPE_VARTEXT2:
 
638
      case HA_KEYTYPE_VARBINARY1:
 
639
      case HA_KEYTYPE_VARBINARY2:
 
640
        if (!(keyseg->flag & HA_BLOB_PART))
 
641
        {
 
642
          keyseg->flag|= HA_VAR_LENGTH_PART;
 
643
          keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
 
644
                               keyseg->type == HA_KEYTYPE_VARBINARY1) ?
 
645
                              1 : 2);
 
646
        }
 
647
        break;
 
648
      default:
 
649
        break;
 
650
      }
 
651
      if (mi_keyseg_write(file, keyseg))
 
652
        goto err;
 
653
    }
 
654
  }
 
655
  for (i=0 ; i < share.base.fields ; i++)
 
656
    if (mi_recinfo_write(file, &recinfo[i]))
 
657
      goto err;
 
658
 
 
659
        /* Enlarge files */
 
660
  if (ftruncate(file, (off_t) share.base.keystart))
 
661
    goto err;
 
662
 
 
663
  if (! (flags & HA_DONT_TOUCH_DATA))
 
664
  {
 
665
#ifdef USE_RELOC
 
666
    if (ftruncate(dfile,share.base.min_pack_length*ci->reloc_rows,))
 
667
      goto err;
 
668
#endif
 
669
    errpos=2;
 
670
    if (internal::my_close(dfile,MYF(0)))
 
671
      goto err;
 
672
  }
 
673
  errpos=0;
 
674
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
675
  if (internal::my_close(file,MYF(0)))
 
676
    goto err;
 
677
  free((char*) rec_per_key_part);
 
678
  return(0);
 
679
 
 
680
err:
 
681
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
682
  save_errno=errno;
 
683
  switch (errpos) {
 
684
  case 3:
 
685
    internal::my_close(dfile,MYF(0));
 
686
    /* fall through */
 
687
  case 2:
 
688
  if (! (flags & HA_DONT_TOUCH_DATA))
 
689
    internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
 
690
                                     MY_UNPACK_FILENAME | MY_APPEND_EXT),
 
691
                           MYF(0));
 
692
    /* fall through */
 
693
  case 1:
 
694
    internal::my_close(file,MYF(0));
 
695
    if (! (flags & HA_DONT_TOUCH_DATA))
 
696
      internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
 
697
                                       MY_UNPACK_FILENAME | MY_APPEND_EXT),
 
698
                             MYF(0));
 
699
  }
 
700
  free((char*) rec_per_key_part);
 
701
  return(errno=save_errno);             /* return the fatal errno */
 
702
}
 
703
 
 
704
 
 
705
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
 
706
{
 
707
  assert(def >= 2 && def <= 7);
 
708
  if (file_length)                              /* If not default */
 
709
  {
 
710
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
 
711
    if (file_length >= 1ULL << 56)
 
712
      def=8;
 
713
    else
 
714
#endif
 
715
    if (file_length >= 1ULL << 48)
 
716
      def=7;
 
717
    else if (file_length >= 1ULL << 40)
 
718
      def=6;
 
719
    else if (file_length >= 1ULL << 32)
 
720
      def=5;
 
721
    else if (file_length >= 1ULL << 24)
 
722
      def=4;
 
723
    else if (file_length >= 1ULL << 16)
 
724
      def=3;
 
725
    else
 
726
      def=2;
 
727
  }
 
728
  return def;
 
729
}