~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* Create a MyISAM table */
17
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
18
#include "myisam_priv.h"
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
19
#include "drizzled/internal/my_bit.h"
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
20
#include "drizzled/internal/my_sys.h"
1 by brian
clean slate
21
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
22
#include "drizzled/util/test.h"
23
#include "drizzled/global_charset_info.h"
1271.5.3 by Tim Penhey
change the include files
24
#include "drizzled/error.h"
1 by brian
clean slate
25
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
26
#include <cassert>
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
27
#include <algorithm>
28
29
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
30
using namespace drizzled;
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
31
1 by brian
clean slate
32
/*
33
  Old options is used when recreating database, from myisamchk
34
*/
35
482 by Brian Aker
Remove uint.
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)
1 by brian
clean slate
40
{
482 by Brian Aker
Remove uint.
41
  register uint32_t i, j;
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
42
  int dfile= 0, file= 0;
1 by brian
clean slate
43
  int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
44
  myf create_flag;
482 by Brian Aker
Remove uint.
45
  uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
1 by brian
clean slate
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;
482 by Brian Aker
Remove uint.
49
  uint32_t aligned_key_start, block_length;
1 by brian
clean slate
50
  ulong reclength, real_reclength,min_pack_length;
51
  char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
52
  ulong pack_reclength;
151 by Brian Aker
Ulonglong to uint64_t
53
  uint64_t tot_length,max_rows, tmp;
1 by brian
clean slate
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;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
61
  internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
1 by brian
clean slate
62
  MI_CREATE_INFO tmp_create_info;
63
64
  if (!ci)
65
  {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
66
    memset(&tmp_create_info, 0, sizeof(tmp_create_info));
1 by brian
clean slate
67
    ci=&tmp_create_info;
68
  }
69
70
  if (keys + uniques > MI_MAX_KEY || columns == 0)
71
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
72
    return(errno=HA_WRONG_CREATE_OPTION);
1 by brian
clean slate
73
  }
74
  errpos= 0;
75
  options= 0;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
76
  memset(&share, 0, sizeof(share));
1 by brian
clean slate
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 |
1117.1.2 by Brian Aker
Remove CHECKSUM option in create table.
83
	 HA_OPTION_READ_ONLY_DATA |
1117.1.1 by Brian Aker
Remove SQL level reference for DELAY (just now done correctly by default in
84
	 HA_OPTION_TMP_TABLE );
1 by brian
clean slate
85
    else
86
      options=ci->old_options &
1117.1.2 by Brian Aker
Remove CHECKSUM option in create table.
87
	(HA_OPTION_TMP_TABLE );
1 by brian
clean slate
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=
656.1.25 by Monty Taylor
Removed my_malloc stuff from storage/
94
	(ulong*) malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long))))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
95
    return(errno);
656.1.25 by Monty Taylor
Removed my_malloc stuff from storage/
96
  memset(rec_per_key_part, 0, (keys + uniques)*MI_MAX_KEY_SEG*sizeof(long));
1 by brian
clean slate
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++;
163 by Brian Aker
Merge Monty's code.
114
	if (pack_reclength != INT32_MAX)
1 by brian
clean slate
115
	{
116
	  if (rec->length == 4+portable_sizeof_char_ptr)
163 by Brian Aker
Merge Monty's code.
117
	    pack_reclength= INT32_MAX;
1 by brian
clean slate
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
      {
163 by Brian Aker
Merge Monty's code.
125
	if (pack_reclength != INT32_MAX)
1 by brian
clean slate
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;
499.1.3 by Monty Taylor
Removed O_NOFOLLOW
177
    create_mode|= O_EXCL;
1 by brian
clean slate
178
  }
179
180
  packed=(packed+7)/8;
163 by Brian Aker
Merge Monty's code.
181
  if (pack_reclength != INT32_MAX)
1 by brian
clean slate
182
    pack_reclength+= reclength+packed +
960.2.2 by Monty Taylor
Moved MyISAM files to C++ so we can continue to consolidate code.
183
      test(test_all_bits(options,
1117.1.2 by Brian Aker
Remove CHECKSUM option in create table.
184
                         uint32_t(HA_PACK_RECORD)));
1 by brian
clean slate
185
  min_pack_length+=packed;
186
187
  if (!ci->data_file_length && ci->max_rows)
188
  {
163 by Brian Aker
Merge Monty's code.
189
    if (pack_reclength == INT32_MAX ||
151 by Brian Aker
Ulonglong to uint64_t
190
             (~(uint64_t) 0)/ci->max_rows < (uint64_t) pack_reclength)
191
      ci->data_file_length= ~(uint64_t) 0;
1 by brian
clean slate
192
    else
151 by Brian Aker
Ulonglong to uint64_t
193
      ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
1 by brian
clean slate
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))
790 by Brian Aker
More myisam plugin conversion.
201
    pointer=mi_get_pointer_length(ci->data_file_length, data_pointer_size);
1 by brian
clean slate
202
  else
790 by Brian Aker
More myisam plugin conversion.
203
    pointer=mi_get_pointer_length(ci->max_rows, data_pointer_size);
151 by Brian Aker
Ulonglong to uint64_t
204
  if (!(max_rows=(uint64_t) ci->max_rows))
205
    max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
1 by brian
clean slate
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
	{
51.1.94 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
290
          assert(!(keyseg->flag & HA_VAR_LENGTH_PART));
1 by brian
clean slate
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
	{
51.1.94 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
303
          assert(!test_all_bits(keyseg->flag,
1 by brian
clean slate
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
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
328
      errno=HA_WRONG_CREATE_OPTION;
1 by brian
clean slate
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 */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
341
    block_length= (keydef->block_length ?
1 by brian
clean slate
342
                   my_round_up_to_next_power(keydef->block_length) :
343
                   myisam_block_size);
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
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);
1 by brian
clean slate
346
206 by Brian Aker
Removed final uint dead types.
347
    keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
1 by brian
clean slate
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
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
353
      errno=HA_WRONG_CREATE_OPTION;
1 by brian
clean slate
354
      goto err;
355
    }
937.2.6 by Stewart Smith
make set_if_bigger typesafe for C and C++. Fix up everywhere.
356
    set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
206 by Brian Aker
Removed final uint dead types.
357
    keydef->keylength= (uint16_t) key_length;
358
    keydef->minlength= (uint16_t) (length-min_key_length_skip);
359
    keydef->maxlength= (uint16_t) length;
1 by brian
clean slate
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.",
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
398
                    MYF(0), name + internal::dirname_length(name));
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
399
    errno= HA_WRONG_CREATE_OPTION;
1 by brian
clean slate
400
    goto err;
401
  }
402
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
403
  memmove(share.state.header.file_version,myisam_file_magic,4);
1 by brian
clean slate
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);
365.2.9 by Monty Taylor
Got rid of all instances of ~0
421
  share.state.sortkey=  UINT16_MAX;
1 by brian
clean slate
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=
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
433
    mi_get_pointer_length(max(ci->key_file_length,tmp),3);
1 by brian
clean slate
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;
1117.1.2 by Brian Aker
Remove CHECKSUM option in create table.
452
  share.base.pack_reclength=reclength;
1 by brian
clean slate
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)
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
461
    share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
1 by brian
clean slate
462
463
  share.base.min_block_length=
464
    (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
465
     ! share.base.blobs) ?
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
466
    max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
1 by brian
clean slate
467
    MI_EXTEND_BLOCK_LENGTH;
468
  if (! (flags & HA_DONT_TOUCH_DATA))
469
    share.state.create_time= (long) time((time_t*) 0);
470
1703.1.3 by Brian Aker
Replace pthread mutex with boost based one for myisam.
471
  THR_LOCK_myisam.lock();
1 by brian
clean slate
472
473
  /*
474
    NOTE: For test_if_reopen() we need a real path name. Hence we need
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
475
    MY_RETURN_REAL_PATH for every internal::fn_format(filename, ...).
1 by brian
clean slate
476
  */
477
  if (ci->index_file_name)
478
  {
960.3.1 by Monty Taylor
Fixed linkage issues on solaris.
479
    char *iext= strrchr((char *)ci->index_file_name, '.');
1 by brian
clean slate
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 */
960.3.1 by Monty Taylor
Fixed linkage issues on solaris.
485
      if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
1 by brian
clean slate
486
        *path= '\0';
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
487
      internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
1 by brian
clean slate
488
                MY_REPLACE_DIR | MY_UNPACK_FILENAME |
489
                MY_RETURN_REAL_PATH | MY_APPEND_EXT);
490
    }
491
    else
492
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
493
      internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
1 by brian
clean slate
494
                MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
495
                (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
496
    }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
497
    internal::fn_format(linkname, name, "", MI_NAME_IEXT,
1 by brian
clean slate
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
  {
960.3.1 by Monty Taylor
Fixed linkage issues on solaris.
508
    char *iext= strrchr((char *)name, '.');
1 by brian
clean slate
509
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
510
    internal::fn_format(filename, name, "", MI_NAME_IEXT,
1 by brian
clean slate
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.",
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
532
                    MYF(0), name + internal::dirname_length(name));
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
533
    errno= HA_ERR_TABLE_EXIST;
1 by brian
clean slate
534
    goto err;
535
  }
536
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
537
  if ((file= internal::my_create_with_symlink(linkname_ptr,
538
                                              filename,
539
                                              0,
540
                                              create_mode,
541
				              MYF(MY_WME | create_flag))) < 0)
1 by brian
clean slate
542
    goto err;
543
  errpos=1;
544
545
  if (!(flags & HA_DONT_TOUCH_DATA))
546
  {
547
    {
548
      if (ci->data_file_name)
549
      {
960.3.1 by Monty Taylor
Fixed linkage issues on solaris.
550
        char *dext= strrchr((char *)ci->data_file_name, '.');
1 by brian
clean slate
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 */
960.3.1 by Monty Taylor
Fixed linkage issues on solaris.
557
          if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
1 by brian
clean slate
558
            *path= '\0';
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
559
          internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
1 by brian
clean slate
560
                    MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
561
        }
562
        else
563
        {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
564
          internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
1 by brian
clean slate
565
                    MY_UNPACK_FILENAME |
566
                    (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
567
        }
568
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
569
	internal::fn_format(linkname, name, "",MI_NAME_DEXT,
1 by brian
clean slate
570
	          MY_UNPACK_FILENAME | MY_APPEND_EXT);
571
	linkname_ptr=linkname;
572
	create_flag=0;
573
      }
574
      else
575
      {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
576
	internal::fn_format(filename,name,"", MI_NAME_DEXT,
1 by brian
clean slate
577
	          MY_UNPACK_FILENAME | MY_APPEND_EXT);
578
	linkname_ptr=0;
579
        create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
580
      }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
581
      if ((dfile= internal::my_create_with_symlink(linkname_ptr,
582
                                                   filename, 0, create_mode,
583
                                                   MYF(MY_WME | create_flag))) < 0)
1 by brian
clean slate
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
  {
482 by Brian Aker
Remove uint.
596
    uint32_t sp_segs= 0;
1 by brian
clean slate
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;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
606
  memset(&tmp_keydef, 0, sizeof(tmp_keydef));
607
  memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
1 by brian
clean slate
608
  for (i=0; i < uniques ; i++)
609
  {
610
    tmp_keydef.keysegs=1;
611
    tmp_keydef.flag=		HA_UNIQUE_CHECK;
206 by Brian Aker
Removed final uint dead types.
612
    tmp_keydef.block_length=	(uint16_t)myisam_block_size;
1 by brian
clean slate
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 */
30 by Brian Aker
Large file and ftruncate() support
660
  if (ftruncate(file, (off_t) share.base.keystart))
1 by brian
clean slate
661
    goto err;
662
663
  if (! (flags & HA_DONT_TOUCH_DATA))
664
  {
665
#ifdef USE_RELOC
30 by Brian Aker
Large file and ftruncate() support
666
    if (ftruncate(dfile,share.base.min_pack_length*ci->reloc_rows,))
1 by brian
clean slate
667
      goto err;
668
#endif
669
    errpos=2;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
670
    if (internal::my_close(dfile,MYF(0)))
1 by brian
clean slate
671
      goto err;
672
  }
673
  errpos=0;
1703.1.3 by Brian Aker
Replace pthread mutex with boost based one for myisam.
674
  THR_LOCK_myisam.unlock();
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
675
  if (internal::my_close(file,MYF(0)))
1 by brian
clean slate
676
    goto err;
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
677
  free((char*) rec_per_key_part);
51.1.94 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
678
  return(0);
1 by brian
clean slate
679
680
err:
1703.1.3 by Brian Aker
Replace pthread mutex with boost based one for myisam.
681
  THR_LOCK_myisam.unlock();
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
682
  save_errno=errno;
1 by brian
clean slate
683
  switch (errpos) {
684
  case 3:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
685
    internal::my_close(dfile,MYF(0));
1 by brian
clean slate
686
    /* fall through */
687
  case 2:
688
  if (! (flags & HA_DONT_TOUCH_DATA))
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
689
    internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
1 by brian
clean slate
690
                                     MY_UNPACK_FILENAME | MY_APPEND_EXT),
691
			   MYF(0));
692
    /* fall through */
693
  case 1:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
694
    internal::my_close(file,MYF(0));
1 by brian
clean slate
695
    if (! (flags & HA_DONT_TOUCH_DATA))
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
696
      internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
1 by brian
clean slate
697
                                       MY_UNPACK_FILENAME | MY_APPEND_EXT),
698
			     MYF(0));
699
  }
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
700
  free((char*) rec_per_key_part);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
701
  return(errno=save_errno);		/* return the fatal errno */
1 by brian
clean slate
702
}
703
704
482 by Brian Aker
Remove uint.
705
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
1 by brian
clean slate
706
{
51.1.94 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
707
  assert(def >= 2 && def <= 7);
1 by brian
clean slate
708
  if (file_length)				/* If not default */
709
  {
710
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
80.1.1 by Brian Aker
LL() cleanup
711
    if (file_length >= 1ULL << 56)
1 by brian
clean slate
712
      def=8;
713
    else
714
#endif
80.1.1 by Brian Aker
LL() cleanup
715
    if (file_length >= 1ULL << 48)
1 by brian
clean slate
716
      def=7;
80.1.1 by Brian Aker
LL() cleanup
717
    else if (file_length >= 1ULL << 40)
1 by brian
clean slate
718
      def=6;
80.1.1 by Brian Aker
LL() cleanup
719
    else if (file_length >= 1ULL << 32)
1 by brian
clean slate
720
      def=5;
80.1.1 by Brian Aker
LL() cleanup
721
    else if (file_length >= 1ULL << 24)
1 by brian
clean slate
722
      def=4;
80.1.1 by Brian Aker
LL() cleanup
723
    else if (file_length >= 1ULL << 16)
1 by brian
clean slate
724
      def=3;
725
    else
726
      def=2;
727
  }
728
  return def;
729
}