~vadim-tk/percona-server/percona-galera-5.1.57

« back to all changes in this revision

Viewing changes to storage/myisam/mi_create.c

  • Committer: root
  • Date: 2011-07-10 16:09:24 UTC
  • Revision ID: root@r815.office.percona.com-20110710160924-fyffqsbaclgu6vui
Initial port

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