270
Read table definition from a binary / text based .frm file
275
share Fill this with table definition
276
db_flags Bit mask of the following flags: OPEN_VIEW
279
This function is called when the table definition is not cached in
281
The data is returned in 'share', which is alloced by
282
alloc_table_share().. The code assumes that share is initialized.
286
1 Error (see open_table_error)
287
2 Error (see open_table_error)
288
3 Wrong data in .frm file
289
4 Error (see open_table_error)
290
5 Error (see open_table_error: charset unavailable)
291
6 Unknown .frm version
294
int open_table_def(THD *thd, TABLE_SHARE *share, uint32_t db_flags __attribute__((unused)))
288
enum_field_types proto_field_type_to_drizzle_type(uint32_t proto_field_type)
296
int error, table_type;
299
unsigned char head[64], *disk_buff;
300
char path[FN_REFLEN];
301
MEM_ROOT **root_ptr, *old_root;
307
strxmov(path, share->normalized_path.str, reg_ext, NULL);
308
if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
311
We don't try to open 5.0 unencoded name, if
312
- non-encoded name contains '@' signs,
313
because '@' can be misinterpreted.
314
It is not clear if '@' is escape character in 5.1,
315
or a normal character in 5.0.
317
- non-encoded db or table name contain "#mysql50#" prefix.
318
This kind of tables must have been opened only by the
321
if (strchr(share->table_name.str, '@') ||
322
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
323
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
324
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
325
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
328
/* Try unencoded 5.0 name */
330
strxnmov(path, sizeof(path)-1,
331
mysql_data_home, "/", share->db.str, "/",
332
share->table_name.str, reg_ext, NULL);
333
length= unpack_filename(path, path) - reg_ext_length;
335
The following is a safety test and should never fail
336
as the old file name should never be longer than the new one.
338
assert(length <= share->normalized_path.length);
340
If the old and the new names have the same length,
341
then table name does not have tricky characters,
342
so no need to check the old file name.
344
if (length == share->normalized_path.length ||
345
((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0))
348
/* Unencoded 5.0 table name found */
349
path[length]= '\0'; // Remove .frm extension
350
my_stpcpy(share->normalized_path.str, path);
351
share->normalized_path.length= length;
355
if (my_read(file, head, 64, MYF(MY_NABP)))
358
if (head[0] == (unsigned char) 254 && head[1] == 1)
360
if (head[2] == FRM_VER || head[2] == FRM_VER+1 ||
361
(head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
367
error= 6; // Unkown .frm version
374
/* No handling of text based files yet */
377
root_ptr= (MEM_ROOT **)pthread_getspecific(THR_MALLOC);
379
*root_ptr= &share->mem_root;
380
error= open_binary_frm(thd, share, head, file);
290
enum_field_types field_type;
292
switch(proto_field_type)
294
case drizzle::Table::Field::TINYINT:
295
field_type= DRIZZLE_TYPE_TINY;
297
case drizzle::Table::Field::INTEGER:
298
field_type= DRIZZLE_TYPE_LONG;
300
case drizzle::Table::Field::DOUBLE:
301
field_type= DRIZZLE_TYPE_DOUBLE;
303
case drizzle::Table::Field::TIMESTAMP:
304
field_type= DRIZZLE_TYPE_TIMESTAMP;
306
case drizzle::Table::Field::BIGINT:
307
field_type= DRIZZLE_TYPE_LONGLONG;
309
case drizzle::Table::Field::DATETIME:
310
field_type= DRIZZLE_TYPE_DATETIME;
312
case drizzle::Table::Field::DATE:
313
field_type= DRIZZLE_TYPE_DATE;
315
case drizzle::Table::Field::VARCHAR:
316
field_type= DRIZZLE_TYPE_VARCHAR;
318
case drizzle::Table::Field::DECIMAL:
319
field_type= DRIZZLE_TYPE_NEWDECIMAL;
321
case drizzle::Table::Field::ENUM:
322
field_type= DRIZZLE_TYPE_ENUM;
324
case drizzle::Table::Field::BLOB:
325
field_type= DRIZZLE_TYPE_BLOB;
327
case drizzle::Table::Field::VIRTUAL:
328
field_type= DRIZZLE_TYPE_VIRTUAL;
331
field_type= DRIZZLE_TYPE_TINY; /* Set value to kill GCC warning */
387
share->table_category= get_table_category(& share->db, & share->table_name);
390
thd->status_var.opened_shares++;
393
my_close(file, MYF(MY_WME));
396
if (error && !error_given)
399
open_table_error(share, error, (share->open_errno= my_errno), 0);
407
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
410
static int open_binary_frm(THD *thd, TABLE_SHARE *share, unsigned char *head,
413
int error, errarg= 0;
414
uint32_t new_frm_ver, field_pack_length, new_field_pack_flag;
415
uint32_t interval_count, interval_parts, read_length, int_length;
416
uint32_t db_create_options, keys, key_parts, n_length;
417
uint32_t key_info_length, com_length, null_bit_pos=0;
418
uint32_t extra_rec_buf_length;
421
unsigned char forminfo[288];
422
char *keynames, *names, *comment_pos;
423
unsigned char *record;
424
unsigned char *disk_buff, *strpos, *null_flags=NULL, *null_pos=NULL;
425
ulong pos, record_offset, *rec_per_key, rec_buff_length;
426
handler *handler_file= 0;
428
KEY_PART_INFO *key_part;
429
Field **field_ptr, *reg_field;
430
const char **interval_array;
431
enum legacy_db_type legacy_db_type;
432
my_bitmap_map *bitmaps;
433
unsigned char *buff= 0;
434
unsigned char *field_extra_info= 0;
436
new_field_pack_flag= head[27];
437
new_frm_ver= (head[2] - FRM_VER);
438
field_pack_length= new_frm_ver < 2 ? 11 : 17;
442
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
443
goto err; /* purecov: inspected */
444
my_seek(file,pos,MY_SEEK_SET,MYF(0));
445
if (my_read(file,forminfo,288,MYF(MY_NABP)))
448
share->frm_version= head[2];
450
Check if .frm file created by MySQL 5.0. In this case we want to
451
display CHAR fields as CHAR and not as VARCHAR.
452
We do it this way as we want to keep the old frm version to enable
453
MySQL 4.1 to read these files.
455
if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5)
456
share->frm_version= FRM_VER_TRUE_VARCHAR;
458
legacy_db_type= DB_TYPE_FIRST_DYNAMIC;
459
assert(share->db_plugin == NULL);
461
if the storage engine is dynamic, no point in resolving it by its
462
dynamically allocated legacy_db_type. We will resolve it later by name.
464
if (legacy_db_type > DB_TYPE_UNKNOWN &&
465
legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
466
share->db_plugin= ha_lock_engine(NULL,
467
ha_checktype(thd, legacy_db_type, 0, 0));
468
share->db_create_options= db_create_options= uint2korr(head+30);
338
Item * default_value_item(enum_field_types field_type,
339
const CHARSET_INFO *charset,
340
bool default_null, const string *default_value,
341
const string *default_bin_value)
343
Item *default_item= NULL;
348
return new Item_null();
353
case DRIZZLE_TYPE_TINY:
354
case DRIZZLE_TYPE_LONG:
355
case DRIZZLE_TYPE_LONGLONG:
356
default_item= new Item_int(default_value->c_str(),
357
(int64_t) my_strtoll10(default_value->c_str(),
360
default_value->length());
362
case DRIZZLE_TYPE_DOUBLE:
363
default_item= new Item_float(default_value->c_str(),
364
default_value->length());
366
case DRIZZLE_TYPE_NULL:
368
case DRIZZLE_TYPE_TIMESTAMP:
369
case DRIZZLE_TYPE_DATETIME:
370
case DRIZZLE_TYPE_DATE:
371
if(default_value->compare("NOW()")==0)
373
case DRIZZLE_TYPE_ENUM:
374
default_item= new Item_string(default_value->c_str(),
375
default_value->length(),
376
system_charset_info);
378
case DRIZZLE_TYPE_VARCHAR:
379
case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
380
if(charset==&my_charset_bin)
382
default_item= new Item_string(default_bin_value->c_str(),
383
default_bin_value->length(),
388
default_item= new Item_string(default_value->c_str(),
389
default_value->length(),
390
system_charset_info);
393
case DRIZZLE_TYPE_VIRTUAL:
395
case DRIZZLE_TYPE_NEWDECIMAL:
396
default_item= new Item_decimal(default_value->c_str(),
397
default_value->length(),
398
system_charset_info);
405
int parse_table_proto(Session *session, drizzle::Table &table, TABLE_SHARE *share)
408
handler *handler_file= NULL;
411
LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
412
strlen(table.engine().name().c_str()) };
413
share->db_plugin= ha_resolve_by_name(session, &engine_name);
416
share->mysql_version= DRIZZLE_VERSION_ID; // TODO: remove
418
drizzle::Table::TableOptions table_options;
420
if(table.has_options())
421
table_options= table.options();
423
uint32_t db_create_options= HA_OPTION_LONG_BLOB_PTR;
425
if(table_options.has_pack_keys())
427
if(table_options.pack_keys())
428
db_create_options|= HA_OPTION_PACK_KEYS;
430
db_create_options|= HA_OPTION_NO_PACK_KEYS;
433
if(table_options.pack_record())
434
db_create_options|= HA_OPTION_PACK_RECORD;
436
if(table_options.has_checksum())
438
if(table_options.checksum())
439
db_create_options|= HA_OPTION_CHECKSUM;
441
db_create_options|= HA_OPTION_NO_CHECKSUM;
444
if(table_options.has_delay_key_write())
446
if(table_options.delay_key_write())
447
db_create_options|= HA_OPTION_DELAY_KEY_WRITE;
449
db_create_options|= HA_OPTION_NO_DELAY_KEY_WRITE;
452
/* db_create_options was stored as 2 bytes in FRM
453
Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
455
share->db_create_options= (db_create_options & 0x0000FFFF);
469
456
share->db_options_in_use= share->db_create_options;
470
share->mysql_version= uint4korr(head+51);
471
share->null_field_first= 0;
472
if (!head[32]) // New frm file in 3.23
474
share->avg_row_length= uint4korr(head+34);
475
share->transactional= (ha_choice) (head[39] & 3);
476
share->page_checksum= (ha_choice) ((head[39] >> 2) & 3);
477
share->row_type= (row_type) head[40];
478
share->block_size= uint4korr(head+43);
479
share->table_charset= get_charset((uint) head[38],MYF(0));
480
share->null_field_first= 1;
459
share->avg_row_length= table_options.has_avg_row_length() ?
460
table_options.avg_row_length() : 0;
462
share->page_checksum= table_options.has_page_checksum() ?
463
(table_options.page_checksum()?HA_CHOICE_YES:HA_CHOICE_NO)
466
share->row_type= table_options.has_row_type() ?
467
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
469
share->block_size= table_options.has_block_size() ?
470
table_options.block_size() : 0;
472
share->table_charset= get_charset(table_options.has_collation_id()?
473
table_options.collation_id() : 0);
482
475
if (!share->table_charset)
484
477
/* unknown charset in head[38] or pre-3.23 frm */
485
478
if (use_mb(default_charset_info))
487
480
/* Warn that we may be changing the size of character columns */
488
sql_print_warning(_("'%s' had no or invalid character set, "
489
"and default character set is multi-byte, "
490
"so character column sizes may have changed"),
481
errmsg_printf(ERRMSG_LVL_WARN,
482
_("'%s' had no or invalid character set, "
483
"and default character set is multi-byte, "
484
"so character column sizes may have changed"),
493
487
share->table_charset= default_charset_info;
495
490
share->db_record_offset= 1;
496
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
497
share->blob_ptr_size= portable_sizeof_char_ptr;
498
/* Set temporarily a good value for db_low_byte_first */
492
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
499
494
share->db_low_byte_first= true;
501
share->max_rows= uint4korr(head+18);
502
share->min_rows= uint4korr(head+22);
504
/* Read keyinformation */
505
key_info_length= (uint) uint2korr(head+28);
506
my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0));
507
if (read_string(file,(unsigned char**) &disk_buff,key_info_length))
508
goto err; /* purecov: inspected */
509
if (disk_buff[0] & 0x80)
511
share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
512
share->key_parts= key_parts= uint2korr(disk_buff+2);
516
share->keys= keys= disk_buff[0];
517
share->key_parts= key_parts= disk_buff[1];
519
share->keys_for_keyread.init(0);
520
share->keys_in_use.init(keys);
522
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
523
if (!(keyinfo = (KEY*) alloc_root(&share->mem_root,
524
n_length + uint2korr(disk_buff+4))))
525
goto err; /* purecov: inspected */
526
memset(keyinfo, 0, n_length);
527
share->key_info= keyinfo;
528
key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
531
if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
532
sizeof(ulong*)*key_parts)))
535
for (i=0 ; i < keys ; i++, keyinfo++)
537
keyinfo->table= 0; // Updated in open_frm
538
if (new_frm_ver >= 3)
540
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
541
keyinfo->key_length= (uint) uint2korr(strpos+2);
542
keyinfo->key_parts= (uint) strpos[4];
543
keyinfo->algorithm= (enum ha_key_alg) strpos[5];
544
keyinfo->block_size= uint2korr(strpos+6);
548
keyinfo->key_part= key_part;
496
share->max_rows= table_options.has_max_rows() ?
497
table_options.max_rows() : 0;
499
share->min_rows= table_options.has_min_rows() ?
500
table_options.min_rows() : 0;
502
share->keys= table.indexes_size();
505
for(int indx= 0; indx < table.indexes_size(); indx++)
506
share->key_parts+= table.indexes(indx).index_part_size();
508
share->key_info= (KEY*) alloc_root(&share->mem_root,
509
table.indexes_size() * sizeof(KEY)
510
+share->key_parts*sizeof(KEY_PART_INFO));
512
KEY_PART_INFO *key_part;
514
key_part= reinterpret_cast<KEY_PART_INFO*>
515
(share->key_info+table.indexes_size());
518
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
519
sizeof(ulong*)*share->key_parts);
521
share->keynames.count= table.indexes_size();
522
share->keynames.name= NULL;
523
share->keynames.type_names= (const char**)
524
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
526
share->keynames.type_lengths= (unsigned int*)
527
alloc_root(&share->mem_root,
528
sizeof(unsigned int) * (table.indexes_size()+1));
530
share->keynames.type_names[share->keynames.count]= NULL;
531
share->keynames.type_lengths[share->keynames.count]= 0;
533
KEY* keyinfo= share->key_info;
534
for (int keynr=0; keynr < table.indexes_size(); keynr++, keyinfo++)
536
drizzle::Table::Index indx= table.indexes(keynr);
542
keyinfo->flags|= HA_NOSAME;
544
if(indx.has_options())
546
drizzle::Table::Index::IndexOptions indx_options= indx.options();
547
if(indx_options.pack_key())
548
keyinfo->flags|= HA_PACK_KEY;
550
if(indx_options.var_length_key())
551
keyinfo->flags|= HA_VAR_LENGTH_PART;
553
if(indx_options.null_part_key())
554
keyinfo->flags|= HA_NULL_PART_KEY;
556
if(indx_options.binary_pack_key())
557
keyinfo->flags|= HA_BINARY_PACK_KEY;
559
if(indx_options.has_partial_segments())
560
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
562
if(indx_options.auto_generated_key())
563
keyinfo->flags|= HA_GENERATED_KEY;
565
if(indx_options.has_key_block_size())
567
keyinfo->flags|= HA_USES_BLOCK_SIZE;
568
keyinfo->block_size= indx_options.key_block_size();
572
keyinfo->block_size= 0;
579
case drizzle::Table::Index::UNKNOWN_INDEX:
580
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
582
case drizzle::Table::Index::BTREE:
583
keyinfo->algorithm= HA_KEY_ALG_BTREE;
585
case drizzle::Table::Index::RTREE:
586
keyinfo->algorithm= HA_KEY_ALG_RTREE;
588
case drizzle::Table::Index::HASH:
589
keyinfo->algorithm= HA_KEY_ALG_HASH;
591
case drizzle::Table::Index::FULLTEXT:
592
keyinfo->algorithm= HA_KEY_ALG_FULLTEXT;
595
/* TODO: suitable warning ? */
596
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
600
keyinfo->key_length= indx.key_length();
602
keyinfo->key_parts= indx.index_part_size();
604
keyinfo->key_part= key_part;
549
605
keyinfo->rec_per_key= rec_per_key;
550
for (j=keyinfo->key_parts ; j-- ; key_part++)
607
for(unsigned int partnr= 0;
608
partnr < keyinfo->key_parts;
609
partnr++, key_part++)
611
drizzle::Table::Index::IndexPart part;
612
part= indx.index_part(partnr);
552
614
*rec_per_key++=0;
553
key_part->fieldnr= (uint16_t) (uint2korr(strpos) & FIELD_NR_MASK);
554
key_part->offset= (uint) uint2korr(strpos+2)-1;
555
key_part->key_type= (uint) uint2korr(strpos+5);
556
// key_part->field= (Field*) 0; // Will be fixed later
557
if (new_frm_ver >= 1)
559
key_part->key_part_flag= *(strpos+4);
560
key_part->length= (uint) uint2korr(strpos+7);
565
key_part->length= *(strpos+4);
566
key_part->key_part_flag=0;
567
if (key_part->length > 128)
569
key_part->length&=127; /* purecov: inspected */
570
key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
574
key_part->store_length=key_part->length;
577
keynames=(char*) key_part;
578
strpos+= (my_stpcpy(keynames, (char *) strpos) - keynames)+1;
580
//reading index comments
581
for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
583
if (keyinfo->flags & HA_USES_COMMENT)
585
keyinfo->comment.length= uint2korr(strpos);
586
keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
587
keyinfo->comment.length);
588
strpos+= 2 + keyinfo->comment.length;
590
assert(test(keyinfo->flags & HA_USES_COMMENT) ==
591
(keyinfo->comment.length > 0));
594
share->reclength = uint2korr((head+16));
596
record_offset= (ulong) (uint2korr(head+6)+
597
((uint2korr(head+14) == 0xffff ?
598
uint4korr(head+47) : uint2korr(head+14))));
600
if ((n_length= uint4korr(head+55)))
602
/* Read extra data segment */
603
unsigned char *next_chunk, *buff_end;
604
if (!(next_chunk= buff= (unsigned char*) my_malloc(n_length, MYF(MY_WME))))
606
if (pread(file, buff, n_length, record_offset + share->reclength) == 0)
610
share->connect_string.length= uint2korr(buff);
611
if (!(share->connect_string.str= strmake_root(&share->mem_root,
612
(char*) next_chunk + 2,
613
share->connect_string.
618
next_chunk+= share->connect_string.length + 2;
619
buff_end= buff + n_length;
620
if (next_chunk + 2 < buff_end)
622
uint32_t str_db_type_length= uint2korr(next_chunk);
624
name.str= (char*) next_chunk + 2;
625
name.length= str_db_type_length;
627
plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name);
628
if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin))
630
if (legacy_db_type > DB_TYPE_UNKNOWN &&
631
legacy_db_type < DB_TYPE_FIRST_DYNAMIC &&
632
legacy_db_type != ha_legacy_type(
633
plugin_data(tmp_plugin, handlerton *)))
635
/* bad file, legacy_db_type did not match the name */
640
tmp_plugin is locked with a local lock.
641
we unlock the old value of share->db_plugin before
642
replacing it with a globally locked version of tmp_plugin
644
plugin_unlock(NULL, share->db_plugin);
645
share->db_plugin= my_plugin_lock(NULL, &tmp_plugin);
647
else if (!tmp_plugin)
649
/* purecov: begin inspected */
651
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
656
next_chunk+= str_db_type_length + 2;
658
if (share->mysql_version >= 50110)
660
/* New auto_partitioned indicator introduced in 5.1.11 */
663
if (forminfo[46] == (unsigned char)255)
665
//reading long table comment
666
if (next_chunk + 2 > buff_end)
671
share->comment.length = uint2korr(next_chunk);
672
if (! (share->comment.str= strmake_root(&share->mem_root,
673
(char*)next_chunk + 2, share->comment.length)))
678
next_chunk+= 2 + share->comment.length;
680
assert(next_chunk <= buff_end);
681
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM_CGE)
684
New frm format in mysql_version 5.2.5 (originally in
685
mysql-5.1.22-ndb-6.2.5)
686
New column properties added:
687
COLUMN_FORMAT DYNAMIC|FIXED and STORAGE DISK|MEMORY
688
TABLESPACE name is now stored in frm
690
if (next_chunk >= buff_end)
692
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM)
699
const uint32_t format_section_header_size= 8;
700
uint32_t format_section_len= uint2korr(next_chunk+0);
702
field_extra_info= next_chunk + format_section_header_size + 1;
703
next_chunk+= format_section_len;
706
assert (next_chunk <= buff_end);
707
if (next_chunk > buff_end)
712
share->key_block_size= uint2korr(head+62);
715
extra_rec_buf_length= uint2korr(head+59);
716
rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length);
616
key_part->field= NULL;
617
key_part->fieldnr= part.fieldnr() + 1; // start from 1.
618
key_part->null_bit= 0;
619
/* key_part->null_offset is only set if null_bit (see later) */
620
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
621
/* key_part->type ???? */
622
key_part->key_part_flag= 0;
623
if(part.has_in_reverse_order())
624
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
626
key_part->length= part.compare_length();
628
key_part->store_length= key_part->length;
630
/* key_part->offset is set later */
631
key_part->key_type= part.key_type();
635
if(!indx.has_comment())
637
keyinfo->comment.length= 0;
638
keyinfo->comment.str= NULL;
642
keyinfo->flags|= HA_USES_COMMENT;
643
keyinfo->comment.length= indx.comment().length();
644
keyinfo->comment.str= strmake_root(&share->mem_root,
645
indx.comment().c_str(),
646
keyinfo->comment.length);
649
keyinfo->name= strmake_root(&share->mem_root,
651
indx.name().length());
653
share->keynames.type_names[keynr]= keyinfo->name;
654
share->keynames.type_lengths[keynr]= indx.name().length();
657
share->keys_for_keyread.init(0);
658
share->keys_in_use.init(share->keys);
660
if(table_options.has_connect_string())
662
size_t len= table_options.connect_string().length();
663
const char* str= table_options.connect_string().c_str();
665
share->connect_string.length= len;
666
share->connect_string.str= strmake_root(&share->mem_root, str, len);
669
if(table_options.has_comment())
671
size_t len= table_options.comment().length();
672
const char* str= table_options.comment().c_str();
674
share->comment.length= len;
675
share->comment.str= strmake_root(&share->mem_root, str, len);
678
share->key_block_size= table_options.has_key_block_size() ?
679
table_options.key_block_size() : 0;
681
share->fields= table.field_size();
683
share->stored_fields= share->fields;
685
share->field= (Field**) alloc_root(&share->mem_root,
686
((share->fields+1) * sizeof(Field*)));
687
share->field[share->fields]= NULL;
689
uint32_t null_fields= 0;
692
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
693
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
695
assert(field_offsets && field_pack_length); // TODO: fixme
697
uint32_t interval_count= 0;
698
uint32_t interval_parts= 0;
700
uint32_t stored_columns_reclength= 0;
702
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
704
drizzle::Table::Field pfield= table.field(fieldnr);
705
if(pfield.has_constraints() && pfield.constraints().is_nullable())
708
bool field_is_stored= true;
710
enum_field_types drizzle_field_type=
711
proto_field_type_to_drizzle_type(pfield.type());
713
if(drizzle_field_type==DRIZZLE_TYPE_VIRTUAL)
715
drizzle::Table::Field::VirtualFieldOptions field_options=
716
pfield.virtual_options();
718
drizzle_field_type=proto_field_type_to_drizzle_type(field_options.type());
720
field_is_stored= field_options.physically_stored();
723
field_offsets[fieldnr]= stored_columns_reclength;
725
/* the below switch is very similar to
726
Create_field::create_length_to_internal_length in field.cc
727
(which should one day be replace by just this code)
729
switch(drizzle_field_type)
731
case DRIZZLE_TYPE_BLOB:
732
case DRIZZLE_TYPE_VARCHAR:
734
drizzle::Table::Field::StringFieldOptions field_options=
735
pfield.string_options();
737
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id()?
738
field_options.collation_id() : 0);
741
cs= default_charset_info;
743
field_pack_length[fieldnr]=
744
calc_pack_length(drizzle_field_type,
745
field_options.length() * cs->mbmaxlen);
749
case DRIZZLE_TYPE_ENUM:
751
drizzle::Table::Field::SetFieldOptions field_options=
752
pfield.set_options();
754
field_pack_length[fieldnr]=
755
get_enum_pack_length(field_options.field_value_size());
758
interval_parts+= field_options.field_value_size();
761
case DRIZZLE_TYPE_NEWDECIMAL:
763
drizzle::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
765
field_pack_length[fieldnr]=
766
my_decimal_get_binary_size(fo.precision(), fo.scale());
770
/* Zero is okay here as length is fixed for other types. */
771
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
774
share->reclength+= field_pack_length[fieldnr];
777
stored_columns_reclength+= field_pack_length[fieldnr];
780
/* data_offset added to stored_rec_length later */
781
share->stored_rec_length= stored_columns_reclength;
783
/* fix up offsets for non-stored fields (at end of record) */
784
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
786
drizzle::Table::Field pfield= table.field(fieldnr);
788
bool field_is_stored= true;
790
enum_field_types drizzle_field_type=
791
proto_field_type_to_drizzle_type(pfield.type());
793
if(drizzle_field_type==DRIZZLE_TYPE_VIRTUAL)
795
drizzle::Table::Field::VirtualFieldOptions field_options=
796
pfield.virtual_options();
798
field_is_stored= field_options.physically_stored();
803
field_offsets[fieldnr]= stored_columns_reclength;
804
stored_columns_reclength+= field_pack_length[fieldnr];
807
share->null_fields= null_fields;
809
ulong null_bits= null_fields;
810
if(!table_options.pack_record())
812
ulong data_offset= (null_bits + 7)/8;
815
share->reclength+= data_offset;
816
share->stored_rec_length+= data_offset;
818
ulong rec_buff_length;
820
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
717
821
share->rec_buff_length= rec_buff_length;
823
unsigned char* record= NULL;
718
825
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
719
826
rec_buff_length)))
720
goto err; /* purecov: inspected */
829
memset(record, 0, rec_buff_length);
833
if(!table_options.pack_record())
835
null_count++; // one bit for delete mark.
721
839
share->default_values= record;
722
if (pread(file, record, (size_t) share->reclength, record_offset) == 0)
723
goto err; /* purecov: inspected */
725
my_seek(file,pos+288,MY_SEEK_SET,MYF(0));
727
share->fields= uint2korr(forminfo+258);
728
pos= uint2korr(forminfo+260); /* Length of all screens */
729
n_length= uint2korr(forminfo+268);
730
interval_count= uint2korr(forminfo+270);
731
interval_parts= uint2korr(forminfo+272);
732
int_length= uint2korr(forminfo+274);
733
share->null_fields= uint2korr(forminfo+282);
734
com_length= uint2korr(forminfo+284);
735
if (forminfo[46] != (unsigned char)255)
737
share->comment.length= (int) (forminfo[46]);
738
share->comment.str= strmake_root(&share->mem_root, (char*) forminfo+47,
739
share->comment.length);
843
share->intervals= (TYPELIB*)alloc_root(&share->mem_root,
844
interval_count*sizeof(TYPELIB));
743
if (!(field_ptr = (Field **)
744
alloc_root(&share->mem_root,
745
(uint) ((share->fields+1)*sizeof(Field*)+
746
interval_count*sizeof(TYPELIB)+
747
(share->fields+interval_parts+
748
keys+3)*sizeof(char *)+
749
(n_length+int_length+com_length)))))
750
goto err; /* purecov: inspected */
752
share->field= field_ptr;
753
read_length=(uint) (share->fields * field_pack_length +
754
pos+ (uint) (n_length+int_length+com_length));
755
if (read_string(file,(unsigned char**) &disk_buff,read_length))
756
goto err; /* purecov: inspected */
757
strpos= disk_buff+pos;
759
share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
760
interval_array= (const char **) (share->intervals+interval_count);
761
names= (char*) (interval_array+share->fields+interval_parts+keys+3);
763
share->intervals= 0; // For better debugging
764
memcpy(names, strpos+(share->fields*field_pack_length),
765
(uint) (n_length+int_length));
766
comment_pos= names+(n_length+int_length);
767
memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
769
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
770
if (share->fieldnames.count != share->fields)
772
fix_type_pointers(&interval_array, share->intervals, interval_count,
847
share->intervals= NULL;
849
share->fieldnames.type_names= (const char**)alloc_root(&share->mem_root,
850
(share->fields+1)*sizeof(char*));
852
share->fieldnames.type_lengths= (unsigned int*) alloc_root(&share->mem_root,
853
(share->fields+1)*sizeof(unsigned int));
855
share->fieldnames.type_names[share->fields]= NULL;
856
share->fieldnames.type_lengths[share->fields]= 0;
857
share->fieldnames.count= share->fields;
860
/* Now fix the TYPELIBs for the intervals (enum values)
864
uint32_t interval_nr= 0;
866
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
776
/* Set ENUM and SET lengths */
778
for (interval= share->intervals;
779
interval < share->intervals + interval_count;
868
drizzle::Table::Field pfield= table.field(fieldnr);
871
share->fieldnames.type_names[fieldnr]= strmake_root(&share->mem_root,
872
pfield.name().c_str(),
873
pfield.name().length());
875
share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
878
if(pfield.type() != drizzle::Table::Field::ENUM)
881
drizzle::Table::Field::SetFieldOptions field_options=
882
pfield.set_options();
884
const CHARSET_INFO *charset= get_charset(field_options.has_collation_id()?
885
field_options.collation_id() : 0);
888
charset= default_charset_info;
890
TYPELIB *t= &(share->intervals[interval_nr]);
892
t->type_names= (const char**)alloc_root(&share->mem_root,
893
(field_options.field_value_size()+1)*sizeof(char*));
895
t->type_lengths= (unsigned int*) alloc_root(&share->mem_root,
896
(field_options.field_value_size()+1)*sizeof(unsigned int));
898
t->type_names[field_options.field_value_size()]= NULL;
899
t->type_lengths[field_options.field_value_size()]= 0;
901
t->count= field_options.field_value_size();
904
for(int n=0; n < field_options.field_value_size(); n++)
782
uint32_t count= (uint) (interval->count + 1) * sizeof(uint);
783
if (!(interval->type_lengths= (uint32_t *) alloc_root(&share->mem_root,
786
for (count= 0; count < interval->count; count++)
788
char *val= (char*) interval->type_names[count];
789
interval->type_lengths[count]= strlen(val);
791
interval->type_lengths[count]= 0;
906
t->type_names[n]= strmake_root(&share->mem_root,
907
field_options.field_value(n).c_str(),
908
field_options.field_value(n).length());
910
/* Go ask the charset what the length is as for "" length=1
911
and there's stripping spaces or some other crack going on.
914
lengthsp= charset->cset->lengthsp(charset, t->type_names[n],
915
field_options.field_value(n).length());
916
t->type_lengths[n]= lengthsp;
796
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
798
/* Allocate handler */
799
if (!(handler_file= get_new_handler(share, thd->mem_root,
803
record= share->default_values-1; /* Fieldstart = 1 */
804
if (share->null_field_first)
806
null_flags= null_pos= (unsigned char*) record+1;
807
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
809
null_bytes below is only correct under the condition that
810
there are no bit fields. Correct values is set below after the
811
table struct is initialized
813
share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
816
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
922
/* and read the fields */
925
bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
818
928
use_hash= !hash_init(&share->name_hash,
819
929
system_charset_info,
821
(hash_get_key) get_field_name,0,0);
823
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
931
(hash_get_key) get_field_name, 0, 0);
933
unsigned char* null_pos= record;;
934
int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
936
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
825
uint32_t pack_flag, interval_nr, unireg_type, recpos, field_length;
826
enum_field_types field_type;
938
drizzle::Table::Field pfield= table.field(fieldnr);
827
940
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
828
const CHARSET_INFO *charset= NULL;
942
switch(pfield.format())
944
case drizzle::Table::Field::DefaultFormat:
945
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
947
case drizzle::Table::Field::FixedFormat:
948
column_format= COLUMN_FORMAT_TYPE_FIXED;
950
case drizzle::Table::Field::DynamicFormat:
951
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
957
Field::utype unireg_type= Field::NONE;
959
if(pfield.has_numeric_options()
960
&& pfield.numeric_options().is_autoincrement())
962
unireg_type= Field::NEXT_NUMBER;
965
if(pfield.has_options()
966
&& pfield.options().has_default_value()
967
&& pfield.options().default_value().compare("NOW()")==0)
969
if(pfield.options().has_update_value()
970
&& pfield.options().update_value().compare("NOW()")==0)
972
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
974
else if (!pfield.options().has_update_value())
976
unireg_type= Field::TIMESTAMP_DN_FIELD;
979
assert(1); // Invalid update value.
981
else if (pfield.has_options()
982
&& pfield.options().has_update_value()
983
&& pfield.options().update_value().compare("NOW()")==0)
985
unireg_type= Field::TIMESTAMP_UN_FIELD;
829
988
LEX_STRING comment;
831
if (field_extra_info)
833
char tmp= field_extra_info[i];
834
column_format= (enum column_format_type)
835
((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
837
if (new_frm_ver >= 3)
839
/* new frm file in 4.1 */
840
field_length= uint2korr(strpos+3);
841
recpos= uint3korr(strpos+5);
842
pack_flag= uint2korr(strpos+8);
843
unireg_type= (uint) strpos[10];
844
interval_nr= (uint) strpos[12];
845
uint32_t comment_length=uint2korr(strpos+15);
846
field_type=(enum_field_types) (uint) strpos[13];
850
charset= &my_charset_bin;
851
else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
853
error= 5; // Unknown or unavailable charset
854
errarg= (int) strpos[14];
860
comment.str= (char*) "";
865
comment.str= (char*) comment_pos;
866
comment.length= comment_length;
867
comment_pos+= comment_length;
989
if(!pfield.has_comment())
991
comment.str= (char*)"";
872
field_length= (uint) strpos[3];
873
recpos= uint2korr(strpos+4),
874
pack_flag= uint2korr(strpos+6);
875
pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
876
unireg_type= (uint) strpos[8];
877
interval_nr= (uint) strpos[10];
880
field_type= (enum_field_types) f_packtype(pack_flag);
881
if (f_is_binary(pack_flag))
884
Try to choose the best 4.1 type:
885
- for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
886
try to find a binary collation for character set.
887
- for other types (e.g. BLOB) just use my_charset_bin.
889
if (!f_is_blob(pack_flag))
891
// 3.23 or 4.0 string
892
if (!(charset= get_charset_by_csname(share->table_charset->csname,
893
MY_CS_BINSORT, MYF(0))))
894
charset= &my_charset_bin;
897
charset= &my_charset_bin;
900
charset= share->table_charset;
901
memset(&comment, 0, sizeof(comment));
904
if (interval_nr && charset->mbminlen > 1)
906
/* Unescape UCS2 intervals from HEX notation */
907
TYPELIB *interval= share->intervals + interval_nr - 1;
908
unhex_type2(interval);
911
*field_ptr= reg_field=
912
make_field(share, record+recpos,
913
(uint32_t) field_length,
914
null_pos, null_bit_pos,
918
(Field::utype) MTYP_TYPENR(unireg_type),
920
share->intervals+interval_nr-1 :
922
share->fieldnames.type_names[i]);
923
if (!reg_field) // Not supported field type
926
goto err; /* purecov: inspected */
929
reg_field->flags|= ((uint)column_format << COLUMN_FORMAT_FLAGS);
930
reg_field->field_index= i;
931
reg_field->comment=comment;
932
if (!(reg_field->flags & NOT_NULL_FLAG))
996
size_t len= pfield.comment().length();
997
const char* str= pfield.comment().c_str();
999
comment.str= strmake_root(&share->mem_root, str, len);
1000
comment.length= len;
1003
enum_field_types field_type;
1004
virtual_column_info *vcol_info= NULL;
1005
bool field_is_stored= true;
1008
field_type= proto_field_type_to_drizzle_type(pfield.type());
1010
if(field_type==DRIZZLE_TYPE_VIRTUAL)
1012
drizzle::Table::Field::VirtualFieldOptions field_options=
1013
pfield.virtual_options();
1015
vcol_info= new virtual_column_info();
1016
field_type= proto_field_type_to_drizzle_type(field_options.type());
1017
field_is_stored= field_options.physically_stored();
1019
size_t len= field_options.expression().length();
1020
const char* str= field_options.expression().c_str();
1022
vcol_info->expr_str.str= strmake_root(&share->mem_root, str, len);
1023
vcol_info->expr_str.length= len;
1028
const CHARSET_INFO *charset= &my_charset_bin;
1030
if(field_type==DRIZZLE_TYPE_BLOB
1031
|| field_type==DRIZZLE_TYPE_VARCHAR)
1033
drizzle::Table::Field::StringFieldOptions field_options=
1034
pfield.string_options();
1036
charset= get_charset(field_options.has_collation_id()?
1037
field_options.collation_id() : 0);
1040
charset= default_charset_info;
1044
if(field_type==DRIZZLE_TYPE_ENUM)
1046
drizzle::Table::Field::SetFieldOptions field_options=
1047
pfield.set_options();
1049
charset= get_charset(field_options.has_collation_id()?
1050
field_options.collation_id() : 0);
1053
charset= default_charset_info;
1057
Item *default_value= NULL;
1059
if(pfield.options().has_default_value()
1060
|| pfield.options().has_default_null()
1061
|| pfield.options().has_default_bin_value())
1063
default_value= default_value_item(field_type,
1065
pfield.options().default_null(),
1066
&pfield.options().default_value(),
1067
&pfield.options().default_bin_value());
1070
uint32_t pack_flag= pfield.pack_flag(); /* TODO: MUST DIE */
1072
Table temp_table; /* Use this so that BLOB DEFAULT '' works */
1073
memset(&temp_table, 0, sizeof(temp_table));
1074
temp_table.s= share;
1075
temp_table.in_use= session;
1076
temp_table.s->db_low_byte_first= 1; //handler->low_byte_first();
1077
temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
1079
Field* f= make_field(share, &share->mem_root,
1080
record+field_offsets[fieldnr]+data_offset,
1081
pfield.options().length(),
1087
(Field::utype) MTYP_TYPENR(unireg_type),
1088
((field_type==DRIZZLE_TYPE_ENUM)?
1089
share->intervals+(interval_nr++)
1091
share->fieldnames.type_names[fieldnr]);
1093
share->field[fieldnr]= f;
1095
f->init(&temp_table); /* blob default values need table obj */
1097
if(!(f->flags & NOT_NULL_FLAG))
1099
*f->null_ptr|= f->null_bit;
934
1100
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
937
if (f_no_default(pack_flag))
938
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
940
if (reg_field->unireg_check == Field::NEXT_NUMBER)
941
share->found_next_number_field= field_ptr;
942
if (share->timestamp_field == reg_field)
943
share->timestamp_field_offset= i;
1107
enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
1108
session->count_cuted_fields= CHECK_FIELD_WARN;
1109
int res= default_value->save_in_field(f, 1);
1110
session->count_cuted_fields= old_count_cuted_fields;
1111
if (res != 0 && res != 3)
1113
my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
1118
else if(f->real_type() == DRIZZLE_TYPE_ENUM &&
1119
(f->flags & NOT_NULL_FLAG))
1122
f->store((int64_t) 1, true);
1127
/* hack to undo f->init() */
1129
f->orig_table= NULL;
1131
f->field_index= fieldnr;
1132
f->comment= comment;
1133
f->vcol_info= vcol_info;
1134
f->is_stored= field_is_stored;
1136
&& !(f->unireg_check==Field::NEXT_NUMBER)
1137
&& (f->flags & NOT_NULL_FLAG)
1138
&& (f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
1139
f->flags|= NO_DEFAULT_VALUE_FLAG;
1141
if(f->unireg_check == Field::NEXT_NUMBER)
1142
share->found_next_number_field= &(share->field[fieldnr]);
1144
if(share->timestamp_field == f)
1145
share->timestamp_field_offset= fieldnr;
1147
if (use_hash) /* supposedly this never fails... but comments lie */
946
1148
(void) my_hash_insert(&share->name_hash,
947
(unsigned char*) field_ptr); // never fail
949
*field_ptr=0; // End marker
951
/* Fix key->name and key_part->field */
954
uint32_t primary_key=(uint) (find_type((char*) primary_key_name,
1149
(unsigned char*)&(share->field[fieldnr]));
1153
share->stored_fields--;
1157
keyinfo= share->key_info;
1158
for (unsigned int keynr=0; keynr < share->keys; keynr++, keyinfo++)
1160
key_part= keyinfo->key_part;
1162
for(unsigned int partnr= 0;
1163
partnr < keyinfo->key_parts;
1164
partnr++, key_part++)
1166
/* Fix up key_part->offset by adding data_offset.
1167
We really should compute offset as well.
1168
But at least this way we are a little better. */
1169
key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
1174
We need to set the unused bits to 1. If the number of bits is a multiple
1175
of 8 there are no unused bits.
1179
*(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1181
share->null_bytes= (null_pos - (unsigned char*) record +
1182
(null_bit_pos + 7) / 8);
1184
share->last_null_bit_pos= null_bit_pos;
1186
free(field_offsets);
1187
free(field_pack_length);
1189
if(!(handler_file= get_new_handler(share, session->mem_root,
1194
if (share->key_parts)
1196
uint32_t primary_key=(uint32_t) (find_type((char*) "PRIMARY",
955
1197
&share->keynames, 3) - 1);
956
1199
int64_t ha_option= handler_file->ha_table_flags();
957
1201
keyinfo= share->key_info;
958
1202
key_part= keyinfo->key_part;
960
1204
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
962
1206
uint32_t usable_parts= 0;
963
keyinfo->name=(char*) share->keynames.type_names[key];
965
1208
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1146
the correct null_bytes can now be set, since bitfields have been taken
1149
share->null_bytes= (null_pos - (unsigned char*) null_flags +
1150
(null_bit_pos + 7) / 8);
1151
share->last_null_bit_pos= null_bit_pos;
1153
1374
share->db_low_byte_first= handler_file->low_byte_first();
1154
1375
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1377
my_bitmap_map *bitmaps;
1156
1379
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1157
1380
share->column_bitmap_size)))
1159
1382
bitmap_init(&share->all_set, bitmaps, share->fields, false);
1160
1383
bitmap_set_all(&share->all_set);
1162
delete handler_file;
1386
delete handler_file;
1170
1390
share->error= error;
1171
1391
share->open_errno= my_errno;
1172
share->errarg= errarg;
1175
delete handler_file;
1176
1393
hash_free(&share->name_hash);
1178
open_table_error(share, error, share->open_errno, errarg);
1395
delete handler_file;
1396
open_table_error(share, error, share->open_errno, 0);
1401
Read table definition from a binary / text based .frm file
1405
session Thread handler
1406
share Fill this with table definition
1407
db_flags Bit mask of the following flags: OPEN_VIEW
1410
This function is called when the table definition is not cached in
1412
The data is returned in 'share', which is alloced by
1413
alloc_table_share().. The code assumes that share is initialized.
1417
1 Error (see open_table_error)
1418
2 Error (see open_table_error)
1419
3 Wrong data in .frm file
1420
4 Error (see open_table_error)
1421
5 Error (see open_table_error: charset unavailable)
1422
6 Unknown .frm version
1425
int open_table_def(Session *session, TABLE_SHARE *share, uint32_t)
1429
string proto_path("");
1434
proto_path.reserve(FN_REFLEN);
1435
proto_path.append(share->normalized_path.str);
1437
proto_path.append(".dfe");
1439
drizzle::Table table;
1441
if((error= drizzle_read_table_proto(proto_path.c_str(), &table)))
1450
if(!table.IsInitialized())
1458
error= parse_table_proto(session, table, share);
1460
share->table_category= get_table_category(& share->db, & share->table_name);
1463
session->status_var.opened_shares++;
1466
if (error && !error_given)
1468
share->error= error;
1469
open_table_error(share, error, (share->open_errno= my_errno), 0);
1180
} /* open_binary_frm */
1476
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1477
This routine is used for error handling purposes.
1481
table Table object for which virtual columns are set-up
1486
static void clear_field_flag(Table *table)
1490
for (ptr= table->field; *ptr; ptr++)
1491
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1495
The function uses the feature in fix_fields where the flag
1496
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1497
This field must always be reset before returning from the function
1498
since it is used for other purposes as well.
1501
fix_fields_vcol_func()
1502
session The thread object
1503
func_item The item tree reference of the virtual columnfunction
1504
table The table object
1505
field_name The name of the processed field
1508
true An error occurred, something was wrong with the
1510
false Ok, a partition field array was created
1513
bool fix_fields_vcol_func(Session *session,
1516
const char *field_name)
1518
uint32_t dir_length, home_dir_length;
1521
TableList *save_table_list, *save_first_table, *save_last_table;
1523
Name_resolution_context *context;
1524
const char *save_where;
1526
char db_name_string[FN_REFLEN];
1527
bool save_use_only_table_context;
1528
Field **ptr, *field;
1529
enum_mark_columns save_mark_used_columns= session->mark_used_columns;
1533
Set-up the TABLE_LIST object to be a list with a single table
1534
Set the object to zero to create NULL pointers and set alias
1535
and real name to table name and get database name from file name.
1538
bzero((void*)&tables, sizeof(TableList));
1539
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1540
tables.table= table;
1541
tables.next_local= NULL;
1542
tables.next_name_resolution_table= NULL;
1543
memcpy(db_name_string,
1544
table->s->normalized_path.str,
1545
table->s->normalized_path.length);
1546
db_name_string[table->s->normalized_path.length]= '\0';
1547
dir_length= dirname_length(db_name_string);
1548
db_name_string[dir_length - 1]= 0;
1549
home_dir_length= dirname_length(db_name_string);
1550
db_name= &db_name_string[home_dir_length];
1553
session->mark_used_columns= MARK_COLUMNS_NONE;
1555
context= session->lex->current_context();
1556
table->map= 1; //To ensure correct calculation of const item
1557
table->get_fields_in_item_tree= true;
1558
save_table_list= context->table_list;
1559
save_first_table= context->first_name_resolution_table;
1560
save_last_table= context->last_name_resolution_table;
1561
context->table_list= &tables;
1562
context->first_name_resolution_table= &tables;
1563
context->last_name_resolution_table= NULL;
1564
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1565
save_where= session->where;
1566
session->where= "virtual column function";
1568
/* Save the context before fixing the fields*/
1569
save_use_only_table_context= session->lex->use_only_table_context;
1570
session->lex->use_only_table_context= true;
1571
/* Fix fields referenced to by the virtual column function */
1572
error= func_expr->fix_fields(session, (Item**)0);
1573
/* Restore the original context*/
1574
session->lex->use_only_table_context= save_use_only_table_context;
1575
context->table_list= save_table_list;
1576
context->first_name_resolution_table= save_first_table;
1577
context->last_name_resolution_table= save_last_table;
1579
if (unlikely(error))
1581
clear_field_flag(table);
1584
session->where= save_where;
1586
Walk through the Item tree checking if all items are valid
1587
to be part of the virtual column
1589
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1592
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1593
clear_field_flag(table);
1596
if (unlikely(func_expr->const_item()))
1598
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1599
clear_field_flag(table);
1602
/* Ensure that this virtual column is not based on another virtual field. */
1604
while ((field= *(ptr++)))
1606
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1609
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1610
clear_field_flag(table);
1615
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1616
when calling fix_fields.
1618
clear_field_flag(table);
1622
table->get_fields_in_item_tree= false;
1623
session->mark_used_columns= save_mark_used_columns;
1624
table->map= 0; //Restore old value
1629
Unpack the definition of a virtual column
1632
unpack_vcol_info_from_frm()
1633
session Thread handler
1634
table Table with the checked field
1635
field Pointer to Field object
1636
open_mode Open table mode needed to determine
1637
which errors need to be generated in a failure
1638
error_reported updated flag for the caller that no other error
1639
messages are to be generated.
1645
bool unpack_vcol_info_from_frm(Session *session,
1648
LEX_STRING *vcol_expr,
1649
open_table_mode open_mode,
1650
bool *error_reported)
1655
Step 1: Construct a statement for the parser.
1656
The parsed string needs to take the following format:
1657
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1659
char *vcol_expr_str;
1662
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1664
parse_vcol_keyword.length + 3)))
1668
memcpy(vcol_expr_str,
1669
(char*) parse_vcol_keyword.str,
1670
parse_vcol_keyword.length);
1671
str_len= parse_vcol_keyword.length;
1672
memcpy(vcol_expr_str + str_len, "(", 1);
1674
memcpy(vcol_expr_str + str_len,
1675
(char*) vcol_expr->str,
1677
str_len+= vcol_expr->length;
1678
memcpy(vcol_expr_str + str_len, ")", 1);
1680
memcpy(vcol_expr_str + str_len, "\0", 1);
1682
Lex_input_stream lip(session, vcol_expr_str, str_len);
1685
Step 2: Setup session for parsing.
1686
1) make Item objects be created in the memory allocated for the Table
1687
object (not TABLE_SHARE)
1688
2) ensure that created Item's are not put on to session->free_list
1689
(which is associated with the parsed statement and hence cleared after
1691
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1692
to be parsed as a SQL command.
1694
MEM_ROOT **root_ptr, *old_root;
1695
Item *backup_free_list= session->free_list;
1696
root_ptr= current_mem_root_ptr();
1697
old_root= *root_ptr;
1698
*root_ptr= &table->mem_root;
1699
session->free_list= NULL;
1700
session->lex->parse_vcol_expr= true;
1703
Step 3: Use the parser to build an Item object from.
1705
if (parse_sql(session, &lip))
1709
/* From now on use vcol_info generated by the parser. */
1710
field->vcol_info= session->lex->vcol_info;
1712
/* Validate the Item tree. */
1713
if (fix_fields_vcol_func(session,
1714
field->vcol_info->expr_item,
1718
if (open_mode == OTM_CREATE)
1721
During CREATE/ALTER TABLE it is ok to receive errors here.
1722
It is not ok if it happens during the opening of an frm
1723
file as part of a normal query.
1725
*error_reported= true;
1727
field->vcol_info= NULL;
1730
field->vcol_info->item_free_list= session->free_list;
1731
session->free_list= backup_free_list;
1732
*root_ptr= old_root;
1737
session->lex->parse_vcol_expr= false;
1738
session->free_items();
1739
*root_ptr= old_root;
1740
session->free_list= backup_free_list;