~ubuntu-branches/ubuntu/hardy/mysql-dfsg-5.0/hardy-updates

« back to all changes in this revision

Viewing changes to libmysqld/ha_myisam.cc

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-04-02 16:10:53 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070402161053-zkil9hjq9k5p1uzv
Tags: 5.0.37-0ubuntu1
* New upstream bugfix release.
  - Fixes replication failure with auto-increment and on duplicate key
    update, a regression introduced into 5.0.24. (LP: #95821)
* debian/control: Set Ubuntu maintainer.
* debian/rules: Change comments from 'Debian etch' to 'Ubuntu 7.04'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000,2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
 
1
/* Copyright (C) 2000-2006 MySQL AB
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; either version 2 of the License, or
6
 
   (at your option) any later version.
 
5
   the Free Software Foundation; version 2 of the License.
7
6
 
8
7
   This program is distributed in the hope that it will be useful,
9
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
121
120
  return;
122
121
}
123
122
 
 
123
 
 
124
/*
 
125
  Convert TABLE object to MyISAM key and column definition
 
126
 
 
127
  SYNOPSIS
 
128
    table2myisam()
 
129
      table_arg   in     TABLE object.
 
130
      keydef_out  out    MyISAM key definition.
 
131
      recinfo_out out    MyISAM column definition.
 
132
      records_out out    Number of fields.
 
133
 
 
134
  DESCRIPTION
 
135
    This function will allocate and initialize MyISAM key and column
 
136
    definition for further use in mi_create or for a check for underlying
 
137
    table conformance in merge engine.
 
138
 
 
139
  RETURN VALUE
 
140
    0  OK
 
141
    !0 error code
 
142
*/
 
143
 
 
144
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
 
145
                 MI_COLUMNDEF **recinfo_out, uint *records_out)
 
146
{
 
147
  uint i, j, recpos, minpos, fieldpos, temp_length, length;
 
148
  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
 
149
  KEY *pos;
 
150
  MI_KEYDEF *keydef;
 
151
  MI_COLUMNDEF *recinfo, *recinfo_pos;
 
152
  HA_KEYSEG *keyseg;
 
153
  TABLE_SHARE *share= table_arg->s;
 
154
  uint options= share->db_options_in_use;
 
155
  DBUG_ENTER("table2myisam");
 
156
  if (!(my_multi_malloc(MYF(MY_WME),
 
157
          recinfo_out, (share->fields * 2 + 2) * sizeof(MI_COLUMNDEF),
 
158
          keydef_out, share->keys * sizeof(MI_KEYDEF),
 
159
          &keyseg,
 
160
          (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
 
161
          NullS)))
 
162
    DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
 
163
  keydef= *keydef_out;
 
164
  recinfo= *recinfo_out;
 
165
  pos= table_arg->key_info;
 
166
  for (i= 0; i < share->keys; i++, pos++)
 
167
  {
 
168
    keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
 
169
    keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
 
170
      (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
 
171
      pos->algorithm;
 
172
    keydef[i].seg= keyseg;
 
173
    keydef[i].keysegs= pos->key_parts;
 
174
    for (j= 0; j < pos->key_parts; j++)
 
175
    {
 
176
      Field *field= pos->key_part[j].field;
 
177
      type= field->key_type();
 
178
      keydef[i].seg[j].flag= pos->key_part[j].key_part_flag;
 
179
 
 
180
      if (options & HA_OPTION_PACK_KEYS ||
 
181
          (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
 
182
                         HA_SPACE_PACK_USED)))
 
183
      {
 
184
        if (pos->key_part[j].length > 8 &&
 
185
            (type == HA_KEYTYPE_TEXT ||
 
186
             type == HA_KEYTYPE_NUM ||
 
187
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
 
188
        {
 
189
          /* No blobs here */
 
190
          if (j == 0)
 
191
            keydef[i].flag|= HA_PACK_KEY;
 
192
          if (!(field->flags & ZEROFILL_FLAG) &&
 
193
              (field->type() == MYSQL_TYPE_STRING ||
 
194
               field->type() == MYSQL_TYPE_VAR_STRING ||
 
195
               ((int) (pos->key_part[j].length - field->decimals())) >= 4))
 
196
            keydef[i].seg[j].flag|= HA_SPACE_PACK;
 
197
        }
 
198
        else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
 
199
          keydef[i].flag|= HA_BINARY_PACK_KEY;
 
200
      }
 
201
      keydef[i].seg[j].type= (int) type;
 
202
      keydef[i].seg[j].start= pos->key_part[j].offset;
 
203
      keydef[i].seg[j].length= pos->key_part[j].length;
 
204
      keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
 
205
        keydef[i].seg[j].bit_length= 0;
 
206
      keydef[i].seg[j].bit_pos= 0;
 
207
      keydef[i].seg[j].language= field->charset()->number;
 
208
 
 
209
      if (field->null_ptr)
 
210
      {
 
211
        keydef[i].seg[j].null_bit= field->null_bit;
 
212
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
 
213
                                           (uchar*) table_arg->record[0]);
 
214
      }
 
215
      else
 
216
      {
 
217
        keydef[i].seg[j].null_bit= 0;
 
218
        keydef[i].seg[j].null_pos= 0;
 
219
      }
 
220
      if (field->type() == FIELD_TYPE_BLOB ||
 
221
          field->type() == FIELD_TYPE_GEOMETRY)
 
222
      {
 
223
        keydef[i].seg[j].flag|= HA_BLOB_PART;
 
224
        /* save number of bytes used to pack length */
 
225
        keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
 
226
                                            share->blob_ptr_size);
 
227
      }
 
228
      else if (field->type() == FIELD_TYPE_BIT)
 
229
      {
 
230
        keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
 
231
        keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
 
232
        keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
 
233
                                          (uchar*) table_arg->record[0]);
 
234
      }
 
235
    }
 
236
    keyseg+= pos->key_parts;
 
237
  }
 
238
  if (table_arg->found_next_number_field)
 
239
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
 
240
  recpos= 0;
 
241
  recinfo_pos= recinfo;
 
242
  while (recpos < (uint) share->reclength)
 
243
  {
 
244
    Field **field, *found= 0;
 
245
    minpos= share->reclength;
 
246
    length= 0;
 
247
 
 
248
    for (field= table_arg->field; *field; field++)
 
249
    {
 
250
      if ((fieldpos= (*field)->offset()) >= recpos &&
 
251
          fieldpos <= minpos)
 
252
      {
 
253
        /* skip null fields */
 
254
        if (!(temp_length= (*field)->pack_length_in_rec()))
 
255
          continue; /* Skip null-fields */
 
256
        if (! found || fieldpos < minpos ||
 
257
            (fieldpos == minpos && temp_length < length))
 
258
        {
 
259
          minpos= fieldpos;
 
260
          found= *field;
 
261
          length= temp_length;
 
262
        }
 
263
      }
 
264
    }
 
265
    DBUG_PRINT("loop", ("found: 0x%lx  recpos: %d  minpos: %d  length: %d",
 
266
                        (long) found, recpos, minpos, length));
 
267
    if (recpos != minpos)
 
268
    { // Reserved space (Null bits?)
 
269
      bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
 
270
      recinfo_pos->type= (int) FIELD_NORMAL;
 
271
      recinfo_pos++->length= (uint16) (minpos - recpos);
 
272
    }
 
273
    if (!found)
 
274
      break;
 
275
 
 
276
    if (found->flags & BLOB_FLAG)
 
277
      recinfo_pos->type= (int) FIELD_BLOB;
 
278
    else if (found->type() == MYSQL_TYPE_VARCHAR)
 
279
      recinfo_pos->type= FIELD_VARCHAR;
 
280
    else if (!(options & HA_OPTION_PACK_RECORD))
 
281
      recinfo_pos->type= (int) FIELD_NORMAL;
 
282
    else if (found->zero_pack())
 
283
      recinfo_pos->type= (int) FIELD_SKIP_ZERO;
 
284
    else
 
285
      recinfo_pos->type= (int) ((length <= 3 ||
 
286
                                 (found->flags & ZEROFILL_FLAG)) ?
 
287
                                  FIELD_NORMAL :
 
288
                                  found->type() == MYSQL_TYPE_STRING ||
 
289
                                  found->type() == MYSQL_TYPE_VAR_STRING ?
 
290
                                  FIELD_SKIP_ENDSPACE :
 
291
                                  FIELD_SKIP_PRESPACE);
 
292
    if (found->null_ptr)
 
293
    {
 
294
      recinfo_pos->null_bit= found->null_bit;
 
295
      recinfo_pos->null_pos= (uint) (found->null_ptr -
 
296
                                     (uchar*) table_arg->record[0]);
 
297
    }
 
298
    else
 
299
    {
 
300
      recinfo_pos->null_bit= 0;
 
301
      recinfo_pos->null_pos= 0;
 
302
    }
 
303
    (recinfo_pos++)->length= (uint16) length;
 
304
    recpos= minpos + length;
 
305
    DBUG_PRINT("loop", ("length: %d  type: %d",
 
306
                        recinfo_pos[-1].length,recinfo_pos[-1].type));
 
307
  }
 
308
  *records_out= (uint) (recinfo_pos - recinfo);
 
309
  DBUG_RETURN(0);
 
310
}
 
311
 
 
312
 
 
313
/*
 
314
  Check for underlying table conformance
 
315
 
 
316
  SYNOPSIS
 
317
    check_definition()
 
318
      t1_keyinfo       in    First table key definition
 
319
      t1_recinfo       in    First table record definition
 
320
      t1_keys          in    Number of keys in first table
 
321
      t1_recs          in    Number of records in first table
 
322
      t2_keyinfo       in    Second table key definition
 
323
      t2_recinfo       in    Second table record definition
 
324
      t2_keys          in    Number of keys in second table
 
325
      t2_recs          in    Number of records in second table
 
326
      strict           in    Strict check switch
 
327
 
 
328
  DESCRIPTION
 
329
    This function compares two MyISAM definitions. By intention it was done
 
330
    to compare merge table definition against underlying table definition.
 
331
    It may also be used to compare dot-frm and MYI definitions of MyISAM
 
332
    table as well to compare different MyISAM table definitions.
 
333
 
 
334
    For merge table it is not required that number of keys in merge table
 
335
    must exactly match number of keys in underlying table. When calling this
 
336
    function for underlying table conformance check, 'strict' flag must be
 
337
    set to false, and converted merge definition must be passed as t1_*.
 
338
 
 
339
    Otherwise 'strict' flag must be set to 1 and it is not required to pass
 
340
    converted dot-frm definition as t1_*.
 
341
 
 
342
  RETURN VALUE
 
343
    0 - Equal definitions.
 
344
    1 - Different definitions.
 
345
*/
 
346
 
 
347
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
 
348
                     uint t1_keys, uint t1_recs,
 
349
                     MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
 
350
                     uint t2_keys, uint t2_recs, bool strict)
 
351
{
 
352
  uint i, j;
 
353
  DBUG_ENTER("check_definition");
 
354
  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
 
355
  {
 
356
    DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
 
357
                         t1_keys, t2_keys));
 
358
    DBUG_RETURN(1);
 
359
  }
 
360
  if (t1_recs != t2_recs)
 
361
  {
 
362
    DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
 
363
                         t1_recs, t2_recs));
 
364
    DBUG_RETURN(1);
 
365
  }
 
366
  for (i= 0; i < t1_keys; i++)
 
367
  {
 
368
    HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
 
369
    HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
 
370
    if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
 
371
        t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
 
372
    {
 
373
      DBUG_PRINT("error", ("Key %d has different definition", i));
 
374
      DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
 
375
                           t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
 
376
      DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
 
377
                           t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
 
378
      DBUG_RETURN(1);
 
379
    }
 
380
    for (j=  t1_keyinfo[i].keysegs; j--;)
 
381
    {
 
382
      if (t1_keysegs[j].type != t2_keysegs[j].type ||
 
383
          t1_keysegs[j].language != t2_keysegs[j].language ||
 
384
          t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
 
385
          t1_keysegs[j].length != t2_keysegs[j].length)
 
386
      {
 
387
        DBUG_PRINT("error", ("Key segment %d (key %d) has different "
 
388
                             "definition", j, i));
 
389
        DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
 
390
                             "t1_length=%d",
 
391
                             t1_keysegs[j].type, t1_keysegs[j].language,
 
392
                             t1_keysegs[j].null_bit, t1_keysegs[j].length));
 
393
        DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
 
394
                             "t2_length=%d",
 
395
                             t2_keysegs[j].type, t2_keysegs[j].language,
 
396
                             t2_keysegs[j].null_bit, t2_keysegs[j].length));
 
397
 
 
398
        DBUG_RETURN(1);
 
399
      }
 
400
    }
 
401
  }
 
402
  for (i= 0; i < t1_recs; i++)
 
403
  {
 
404
    MI_COLUMNDEF *t1_rec= &t1_recinfo[i];
 
405
    MI_COLUMNDEF *t2_rec= &t2_recinfo[i];
 
406
    if (t1_rec->type != t2_rec->type ||
 
407
        t1_rec->length != t2_rec->length ||
 
408
        t1_rec->null_bit != t2_rec->null_bit)
 
409
    {
 
410
      DBUG_PRINT("error", ("Field %d has different definition", i));
 
411
      DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
 
412
                           t1_rec->type, t1_rec->length, t1_rec->null_bit));
 
413
      DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
 
414
                           t2_rec->type, t2_rec->length, t2_rec->null_bit));
 
415
      DBUG_RETURN(1);
 
416
    }
 
417
  }
 
418
  DBUG_RETURN(0);
 
419
}
 
420
 
 
421
 
124
422
extern "C" {
125
423
 
126
424
volatile int *killed_ptr(MI_CHECK *param)
340
638
  MYISAM_SHARE* share = file->s;
341
639
  const char *old_proc_info=thd->proc_info;
342
640
 
343
 
  thd->proc_info="Checking table";
 
641
  thd_proc_info(thd, "Checking table");
344
642
  myisamchk_init(&param);
345
643
  param.thd = thd;
346
644
  param.op_name =   "check";
414
712
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
415
713
  }
416
714
 
417
 
  thd->proc_info=old_proc_info;
 
715
  thd_proc_info(thd, old_proc_info);
418
716
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
419
717
}
420
718
 
680
978
        char buf[40];
681
979
        /* TODO: respect myisam_repair_threads variable */
682
980
        my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
683
 
        thd->proc_info=buf;
 
981
        thd_proc_info(thd, buf);
684
982
        error = mi_repair_parallel(&param, file, fixed_name,
685
983
            param.testflag & T_QUICK);
686
 
        thd->proc_info="Repair done"; // to reset proc_info, as
 
984
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
687
985
                                      // it was pointing to local buffer
688
986
      }
689
987
      else
690
988
      {
691
 
        thd->proc_info="Repair by sorting";
 
989
        thd_proc_info(thd, "Repair by sorting");
692
990
        error = mi_repair_by_sort(&param, file, fixed_name,
693
991
            param.testflag & T_QUICK);
694
992
      }
695
993
    }
696
994
    else
697
995
    {
698
 
      thd->proc_info="Repair with keycache";
 
996
      thd_proc_info(thd, "Repair with keycache");
699
997
      param.testflag &= ~T_REP_BY_SORT;
700
998
      error=  mi_repair(&param, file, fixed_name,
701
999
                        param.testflag & T_QUICK);
709
1007
        (share->state.changed & STATE_NOT_SORTED_PAGES))
710
1008
    {
711
1009
      optimize_done=1;
712
 
      thd->proc_info="Sorting index";
 
1010
      thd_proc_info(thd, "Sorting index");
713
1011
      error=mi_sort_index(&param,file,fixed_name);
714
1012
    }
715
1013
    if (!statistics_done && (local_testflag & T_STATISTICS))
717
1015
      if (share->state.changed & STATE_NOT_ANALYZED)
718
1016
      {
719
1017
        optimize_done=1;
720
 
        thd->proc_info="Analyzing";
 
1018
        thd_proc_info(thd, "Analyzing");
721
1019
        error = chk_key(&param, file);
722
1020
      }
723
1021
      else
724
1022
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
725
1023
    }
726
1024
  }
727
 
  thd->proc_info="Saving state";
 
1025
  thd_proc_info(thd, "Saving state");
728
1026
  if (!error)
729
1027
  {
730
1028
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
762
1060
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
763
1061
    update_state_info(&param, file, 0);
764
1062
  }
765
 
  thd->proc_info=old_proc_info;
 
1063
  thd_proc_info(thd, old_proc_info);
766
1064
  if (!thd->locked_tables)
767
1065
    mi_lock_database(file,F_UNLCK);
768
1066
  DBUG_RETURN(error ? HA_ADMIN_FAILED :
987
1285
    THD *thd=current_thd;
988
1286
    MI_CHECK param;
989
1287
    const char *save_proc_info=thd->proc_info;
990
 
    thd->proc_info="Creating index";
 
1288
    thd_proc_info(thd, "Creating index");
991
1289
    myisamchk_init(&param);
992
1290
    param.op_name= "recreating_index";
993
1291
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
1012
1310
        thd->clear_error();
1013
1311
    }
1014
1312
    info(HA_STATUS_CONST);
1015
 
    thd->proc_info=save_proc_info;
 
1313
    thd_proc_info(thd, save_proc_info);
1016
1314
  }
1017
1315
  else
1018
1316
  {
1430
1728
                      HA_CREATE_INFO *info)
1431
1729
{
1432
1730
  int error;
1433
 
  uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags= 0;
1434
 
  bool found_real_auto_increment=0;
1435
 
  enum ha_base_keytype type;
 
1731
  uint create_flags= 0, records;
1436
1732
  char buff[FN_REFLEN];
1437
 
  KEY *pos;
1438
1733
  MI_KEYDEF *keydef;
1439
 
  MI_COLUMNDEF *recinfo,*recinfo_pos;
1440
 
  HA_KEYSEG *keyseg;
 
1734
  MI_COLUMNDEF *recinfo;
 
1735
  MI_CREATE_INFO create_info;
1441
1736
  TABLE_SHARE *share= table->s;
1442
1737
  uint options= share->db_options_in_use;
1443
1738
  DBUG_ENTER("ha_myisam::create");
1444
 
 
1445
 
  type=HA_KEYTYPE_BINARY;                               // Keep compiler happy
1446
 
  if (!(my_multi_malloc(MYF(MY_WME),
1447
 
                        &recinfo,(share->fields*2+2)*
1448
 
                        sizeof(MI_COLUMNDEF),
1449
 
                        &keydef, share->keys*sizeof(MI_KEYDEF),
1450
 
                        &keyseg,
1451
 
                        ((share->key_parts + share->keys) *
1452
 
                         sizeof(HA_KEYSEG)),
1453
 
                        NullS)))
1454
 
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1455
 
 
1456
 
  pos=table_arg->key_info;
1457
 
  for (i=0; i < share->keys ; i++, pos++)
1458
 
  {
1459
 
    keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
1460
 
    keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ? 
1461
 
      (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
1462
 
      pos->algorithm;
1463
 
    keydef[i].seg=keyseg;
1464
 
    keydef[i].keysegs=pos->key_parts;
1465
 
    for (j=0 ; j < pos->key_parts ; j++)
1466
 
    {
1467
 
      Field *field=pos->key_part[j].field;
1468
 
      type=field->key_type();
1469
 
      keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
1470
 
 
1471
 
      if (options & HA_OPTION_PACK_KEYS ||
1472
 
          (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
1473
 
                         HA_SPACE_PACK_USED)))
1474
 
      {
1475
 
        if (pos->key_part[j].length > 8 &&
1476
 
            (type == HA_KEYTYPE_TEXT ||
1477
 
             type == HA_KEYTYPE_NUM ||
1478
 
             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
1479
 
        {
1480
 
          /* No blobs here */
1481
 
          if (j == 0)
1482
 
            keydef[i].flag|=HA_PACK_KEY;
1483
 
          if (!(field->flags & ZEROFILL_FLAG) &&
1484
 
              (field->type() == MYSQL_TYPE_STRING ||
1485
 
               field->type() == MYSQL_TYPE_VAR_STRING ||
1486
 
               ((int) (pos->key_part[j].length - field->decimals()))
1487
 
               >= 4))
1488
 
            keydef[i].seg[j].flag|=HA_SPACE_PACK;
1489
 
        }
1490
 
        else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
1491
 
          keydef[i].flag|= HA_BINARY_PACK_KEY;
1492
 
      }
1493
 
      keydef[i].seg[j].type=   (int) type;
1494
 
      keydef[i].seg[j].start=  pos->key_part[j].offset;
1495
 
      keydef[i].seg[j].length= pos->key_part[j].length;
1496
 
      keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
1497
 
        keydef[i].seg[j].bit_length= 0;
1498
 
      keydef[i].seg[j].bit_pos= 0;
1499
 
      keydef[i].seg[j].language= field->charset()->number;
1500
 
 
1501
 
      if (field->null_ptr)
1502
 
      {
1503
 
        keydef[i].seg[j].null_bit=field->null_bit;
1504
 
        keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
1505
 
                                           (uchar*) table_arg->record[0]);
1506
 
      }
1507
 
      else
1508
 
      {
1509
 
        keydef[i].seg[j].null_bit=0;
1510
 
        keydef[i].seg[j].null_pos=0;
1511
 
      }
1512
 
      if (field->type() == FIELD_TYPE_BLOB ||
1513
 
          field->type() == FIELD_TYPE_GEOMETRY)
1514
 
      {
1515
 
        keydef[i].seg[j].flag|=HA_BLOB_PART;
1516
 
        /* save number of bytes used to pack length */
1517
 
        keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
1518
 
                                            share->blob_ptr_size);
1519
 
      }
1520
 
      else if (field->type() == FIELD_TYPE_BIT)
1521
 
      {
1522
 
        keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
1523
 
        keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
1524
 
        keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
1525
 
                                          (uchar*) table_arg->record[0]);
1526
 
      }
1527
 
    }
1528
 
    keyseg+=pos->key_parts;
1529
 
  }
1530
 
 
1531
 
  if (table_arg->found_next_number_field)
1532
 
  {
1533
 
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
1534
 
    found_real_auto_increment= share->next_number_key_offset == 0;
1535
 
  }
1536
 
 
1537
 
  recpos=0; recinfo_pos=recinfo;
1538
 
  while (recpos < (uint) share->reclength)
1539
 
  {
1540
 
    Field **field,*found=0;
1541
 
    minpos= share->reclength;
1542
 
    length=0;
1543
 
 
1544
 
    for (field=table_arg->field ; *field ; field++)
1545
 
    {
1546
 
      if ((fieldpos=(*field)->offset()) >= recpos &&
1547
 
          fieldpos <= minpos)
1548
 
      {
1549
 
        /* skip null fields */
1550
 
        if (!(temp_length= (*field)->pack_length_in_rec()))
1551
 
          continue;                             /* Skip null-fields */
1552
 
        if (! found || fieldpos < minpos ||
1553
 
            (fieldpos == minpos && temp_length < length))
1554
 
        {
1555
 
          minpos=fieldpos; found= *field; length=temp_length;
1556
 
        }
1557
 
      }
1558
 
    }
1559
 
    DBUG_PRINT("loop",("found: 0x%lx  recpos: %d  minpos: %d  length: %d",
1560
 
                       (long) found, recpos, minpos, length));
1561
 
    if (recpos != minpos)
1562
 
    {                                           // Reserved space (Null bits?)
1563
 
      bzero((char*) recinfo_pos,sizeof(*recinfo_pos));
1564
 
      recinfo_pos->type=(int) FIELD_NORMAL;
1565
 
      recinfo_pos++->length= (uint16) (minpos-recpos);
1566
 
    }
1567
 
    if (! found)
1568
 
      break;
1569
 
 
1570
 
    if (found->flags & BLOB_FLAG)
1571
 
      recinfo_pos->type= (int) FIELD_BLOB;
1572
 
    else if (found->type() == MYSQL_TYPE_VARCHAR)
1573
 
      recinfo_pos->type= FIELD_VARCHAR;
1574
 
    else if (!(options & HA_OPTION_PACK_RECORD))
1575
 
      recinfo_pos->type= (int) FIELD_NORMAL;
1576
 
    else if (found->zero_pack())
1577
 
      recinfo_pos->type= (int) FIELD_SKIP_ZERO;
1578
 
    else
1579
 
      recinfo_pos->type= (int) ((length <= 3 ||
1580
 
                                 (found->flags & ZEROFILL_FLAG)) ?
1581
 
                                FIELD_NORMAL :
1582
 
                                found->type() == MYSQL_TYPE_STRING ||
1583
 
                                found->type() == MYSQL_TYPE_VAR_STRING ?
1584
 
                                FIELD_SKIP_ENDSPACE :
1585
 
                                FIELD_SKIP_PRESPACE);
1586
 
    if (found->null_ptr)
1587
 
    {
1588
 
      recinfo_pos->null_bit=found->null_bit;
1589
 
      recinfo_pos->null_pos= (uint) (found->null_ptr-
1590
 
                                     (uchar*) table_arg->record[0]);
1591
 
    }
1592
 
    else
1593
 
    {
1594
 
      recinfo_pos->null_bit=0;
1595
 
      recinfo_pos->null_pos=0;
1596
 
    }
1597
 
    (recinfo_pos++)->length= (uint16) length;
1598
 
    recpos=minpos+length;
1599
 
    DBUG_PRINT("loop",("length: %d  type: %d",
1600
 
                       recinfo_pos[-1].length,recinfo_pos[-1].type));
1601
 
 
1602
 
  }
1603
 
  MI_CREATE_INFO create_info;
1604
 
  bzero((char*) &create_info,sizeof(create_info));
 
1739
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
 
1740
    DBUG_RETURN(error); /* purecov: inspected */
 
1741
  bzero((char*) &create_info, sizeof(create_info));
1605
1742
  create_info.max_rows= share->max_rows;
1606
1743
  create_info.reloc_rows= share->min_rows;
1607
 
  create_info.with_auto_increment=found_real_auto_increment;
1608
 
  create_info.auto_increment=(info->auto_increment_value ?
1609
 
                              info->auto_increment_value -1 :
1610
 
                              (ulonglong) 0);
 
1744
  create_info.with_auto_increment= share->next_number_key_offset == 0;
 
1745
  create_info.auto_increment= (info->auto_increment_value ?
 
1746
                               info->auto_increment_value -1 :
 
1747
                               (ulonglong) 0);
1611
1748
  create_info.data_file_length= ((ulonglong) share->max_rows *
1612
 
                                 share->avg_row_length);
1613
 
  create_info.raid_type=info->raid_type;
 
1749
                                 share->avg_row_length);
 
1750
  create_info.raid_type= info->raid_type;
1614
1751
  create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
1615
 
                            RAID_DEFAULT_CHUNKS);
 
1752
                            RAID_DEFAULT_CHUNKS);
1616
1753
  create_info.raid_chunksize= (info->raid_chunksize ? info->raid_chunksize :
1617
1754
                               RAID_DEFAULT_CHUNKSIZE);
1618
 
  create_info.data_file_name=  info->data_file_name;
 
1755
  create_info.data_file_name= info->data_file_name;
1619
1756
  create_info.index_file_name= info->index_file_name;
1620
1757
 
1621
1758
  if (info->options & HA_LEX_CREATE_TMP_TABLE)
1628
1765
    create_flags|= HA_CREATE_DELAY_KEY_WRITE;
1629
1766
 
1630
1767
  /* TODO: Check that the following fn_format is really needed */
1631
 
  error=mi_create(fn_format(buff,name,"","",2+4),
1632
 
                  share->keys,keydef,
1633
 
                  (uint) (recinfo_pos-recinfo), recinfo,
1634
 
                  0, (MI_UNIQUEDEF*) 0,
1635
 
                  &create_info, create_flags);
1636
 
 
1637
 
  my_free((gptr) recinfo,MYF(0));
 
1768
  error= mi_create(fn_format(buff, name, "", "",
 
1769
                             MY_UNPACK_FILENAME|MY_REPLACE_EXT),
 
1770
                   share->keys, keydef,
 
1771
                   records, recinfo,
 
1772
                   0, (MI_UNIQUEDEF*) 0,
 
1773
                   &create_info, create_flags);
 
1774
  my_free((gptr) recinfo, MYF(0));
1638
1775
  DBUG_RETURN(error);
1639
1776
}
1640
1777