125
Convert TABLE object to MyISAM key and column definition
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.
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.
144
int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
145
MI_COLUMNDEF **recinfo_out, uint *records_out)
147
uint i, j, recpos, minpos, fieldpos, temp_length, length;
148
enum ha_base_keytype type= HA_KEYTYPE_BINARY;
151
MI_COLUMNDEF *recinfo, *recinfo_pos;
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),
160
(share->key_parts + share->keys) * sizeof(HA_KEYSEG),
162
DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
164
recinfo= *recinfo_out;
165
pos= table_arg->key_info;
166
for (i= 0; i < share->keys; i++, pos++)
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) :
172
keydef[i].seg= keyseg;
173
keydef[i].keysegs= pos->key_parts;
174
for (j= 0; j < pos->key_parts; j++)
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;
180
if (options & HA_OPTION_PACK_KEYS ||
181
(pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
182
HA_SPACE_PACK_USED)))
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())))
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;
198
else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
199
keydef[i].flag|= HA_BINARY_PACK_KEY;
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;
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]);
217
keydef[i].seg[j].null_bit= 0;
218
keydef[i].seg[j].null_pos= 0;
220
if (field->type() == FIELD_TYPE_BLOB ||
221
field->type() == FIELD_TYPE_GEOMETRY)
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);
228
else if (field->type() == FIELD_TYPE_BIT)
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]);
236
keyseg+= pos->key_parts;
238
if (table_arg->found_next_number_field)
239
keydef[share->next_number_index].flag|= HA_AUTO_KEY;
241
recinfo_pos= recinfo;
242
while (recpos < (uint) share->reclength)
244
Field **field, *found= 0;
245
minpos= share->reclength;
248
for (field= table_arg->field; *field; field++)
250
if ((fieldpos= (*field)->offset()) >= recpos &&
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))
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);
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;
285
recinfo_pos->type= (int) ((length <= 3 ||
286
(found->flags & ZEROFILL_FLAG)) ?
288
found->type() == MYSQL_TYPE_STRING ||
289
found->type() == MYSQL_TYPE_VAR_STRING ?
290
FIELD_SKIP_ENDSPACE :
291
FIELD_SKIP_PRESPACE);
294
recinfo_pos->null_bit= found->null_bit;
295
recinfo_pos->null_pos= (uint) (found->null_ptr -
296
(uchar*) table_arg->record[0]);
300
recinfo_pos->null_bit= 0;
301
recinfo_pos->null_pos= 0;
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));
308
*records_out= (uint) (recinfo_pos - recinfo);
314
Check for underlying table conformance
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
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.
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_*.
339
Otherwise 'strict' flag must be set to 1 and it is not required to pass
340
converted dot-frm definition as t1_*.
343
0 - Equal definitions.
344
1 - Different definitions.
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)
353
DBUG_ENTER("check_definition");
354
if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
356
DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
360
if (t1_recs != t2_recs)
362
DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
366
for (i= 0; i < t1_keys; i++)
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)
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));
380
for (j= t1_keyinfo[i].keysegs; j--;)
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)
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, "
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, "
395
t2_keysegs[j].type, t2_keysegs[j].language,
396
t2_keysegs[j].null_bit, t2_keysegs[j].length));
402
for (i= 0; i < t1_recs; i++)
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)
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));
126
424
volatile int *killed_ptr(MI_CHECK *param)
1430
1728
HA_CREATE_INFO *info)
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];
1438
1733
MI_KEYDEF *keydef;
1439
MI_COLUMNDEF *recinfo,*recinfo_pos;
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");
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),
1451
((share->key_parts + share->keys) *
1454
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1456
pos=table_arg->key_info;
1457
for (i=0; i < share->keys ; i++, pos++)
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) :
1463
keydef[i].seg=keyseg;
1464
keydef[i].keysegs=pos->key_parts;
1465
for (j=0 ; j < pos->key_parts ; j++)
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;
1471
if (options & HA_OPTION_PACK_KEYS ||
1472
(pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
1473
HA_SPACE_PACK_USED)))
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())))
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()))
1488
keydef[i].seg[j].flag|=HA_SPACE_PACK;
1490
else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
1491
keydef[i].flag|= HA_BINARY_PACK_KEY;
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;
1501
if (field->null_ptr)
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]);
1509
keydef[i].seg[j].null_bit=0;
1510
keydef[i].seg[j].null_pos=0;
1512
if (field->type() == FIELD_TYPE_BLOB ||
1513
field->type() == FIELD_TYPE_GEOMETRY)
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);
1520
else if (field->type() == FIELD_TYPE_BIT)
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]);
1528
keyseg+=pos->key_parts;
1531
if (table_arg->found_next_number_field)
1533
keydef[share->next_number_index].flag|= HA_AUTO_KEY;
1534
found_real_auto_increment= share->next_number_key_offset == 0;
1537
recpos=0; recinfo_pos=recinfo;
1538
while (recpos < (uint) share->reclength)
1540
Field **field,*found=0;
1541
minpos= share->reclength;
1544
for (field=table_arg->field ; *field ; field++)
1546
if ((fieldpos=(*field)->offset()) >= recpos &&
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))
1555
minpos=fieldpos; found= *field; length=temp_length;
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);
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;
1579
recinfo_pos->type= (int) ((length <= 3 ||
1580
(found->flags & ZEROFILL_FLAG)) ?
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)
1588
recinfo_pos->null_bit=found->null_bit;
1589
recinfo_pos->null_pos= (uint) (found->null_ptr-
1590
(uchar*) table_arg->record[0]);
1594
recinfo_pos->null_bit=0;
1595
recinfo_pos->null_pos=0;
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));
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 :
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 :
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;
1621
1758
if (info->options & HA_LEX_CREATE_TMP_TABLE)