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)))
289
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);
291
enum_field_types field_type;
293
switch(proto_field_type)
295
case drizzle::Table::Field::TINYINT:
296
field_type= DRIZZLE_TYPE_TINY;
298
case drizzle::Table::Field::INTEGER:
299
field_type= DRIZZLE_TYPE_LONG;
301
case drizzle::Table::Field::DOUBLE:
302
field_type= DRIZZLE_TYPE_DOUBLE;
304
case drizzle::Table::Field::TIMESTAMP:
305
field_type= DRIZZLE_TYPE_TIMESTAMP;
307
case drizzle::Table::Field::BIGINT:
308
field_type= DRIZZLE_TYPE_LONGLONG;
310
case drizzle::Table::Field::DATETIME:
311
field_type= DRIZZLE_TYPE_DATETIME;
313
case drizzle::Table::Field::DATE:
314
field_type= DRIZZLE_TYPE_DATE;
316
case drizzle::Table::Field::VARCHAR:
317
field_type= DRIZZLE_TYPE_VARCHAR;
319
case drizzle::Table::Field::DECIMAL:
320
field_type= DRIZZLE_TYPE_NEWDECIMAL;
322
case drizzle::Table::Field::ENUM:
323
field_type= DRIZZLE_TYPE_ENUM;
325
case drizzle::Table::Field::BLOB:
326
field_type= DRIZZLE_TYPE_BLOB;
328
case drizzle::Table::Field::VIRTUAL:
329
field_type= DRIZZLE_TYPE_VIRTUAL;
332
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);
339
Item * default_value_item(enum_field_types field_type,
340
const CHARSET_INFO *charset,
341
bool default_null, string default_value,
342
string default_bin_value)
344
Item *default_item= NULL;
349
return new Item_null();
354
case DRIZZLE_TYPE_TINY:
355
case DRIZZLE_TYPE_LONG:
356
case DRIZZLE_TYPE_LONGLONG:
357
default_item= new Item_int(default_value.c_str(),
358
(int64_t) my_strtoll10(default_value.c_str(),
361
default_value.length());
363
case DRIZZLE_TYPE_DOUBLE:
364
default_item= new Item_float(default_value.c_str(), default_value.length());
366
case DRIZZLE_TYPE_NULL:
367
return new Item_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)
410
LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
411
strlen(table.engine().name().c_str()) };
412
share->db_plugin= ha_resolve_by_name(session, &engine_name);
415
share->mysql_version= DRIZZLE_VERSION_ID; // TODO: remove
417
drizzle::Table::TableOptions table_options;
419
if(table.has_options())
420
table_options= table.options();
422
uint32_t db_create_options= HA_OPTION_LONG_BLOB_PTR;
424
if(table_options.has_pack_keys())
426
if(table_options.pack_keys())
427
db_create_options|= HA_OPTION_PACK_KEYS;
429
db_create_options|= HA_OPTION_NO_PACK_KEYS;
432
if(table_options.pack_record())
433
db_create_options|= HA_OPTION_PACK_RECORD;
435
if(table_options.has_checksum())
437
if(table_options.checksum())
438
db_create_options|= HA_OPTION_CHECKSUM;
440
db_create_options|= HA_OPTION_NO_CHECKSUM;
443
if(table_options.has_delay_key_write())
445
if(table_options.delay_key_write())
446
db_create_options|= HA_OPTION_DELAY_KEY_WRITE;
448
db_create_options|= HA_OPTION_NO_DELAY_KEY_WRITE;
451
/* db_create_options was stored as 2 bytes in FRM
452
Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
454
share->db_create_options= (db_create_options & 0x0000FFFF);
469
455
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;
458
share->avg_row_length= table_options.has_avg_row_length() ?
459
table_options.avg_row_length() : 0;
461
share->page_checksum= table_options.has_page_checksum() ?
462
(table_options.page_checksum()?HA_CHOICE_YES:HA_CHOICE_NO)
465
share->row_type= table_options.has_row_type() ?
466
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
468
share->block_size= table_options.has_block_size() ?
469
table_options.block_size() : 0;
471
share->table_charset= get_charset(table_options.has_collation_id()?
472
table_options.collation_id() : 0);
482
474
if (!share->table_charset)
484
476
/* unknown charset in head[38] or pre-3.23 frm */
485
477
if (use_mb(default_charset_info))
487
479
/* 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"),
480
errmsg_printf(ERRMSG_LVL_WARN,
481
_("'%s' had no or invalid character set, "
482
"and default character set is multi-byte, "
483
"so character column sizes may have changed"),
493
486
share->table_charset= default_charset_info;
495
489
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 */
491
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
499
493
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;
495
share->max_rows= table_options.has_max_rows() ?
496
table_options.max_rows() : 0;
498
share->min_rows= table_options.has_min_rows() ?
499
table_options.min_rows() : 0;
501
share->keys= table.indexes_size();
504
for(int indx= 0; indx < table.indexes_size(); indx++)
505
share->key_parts+= table.indexes(indx).index_part_size();
507
share->key_info= (KEY*) alloc_root(&share->mem_root,
508
table.indexes_size() * sizeof(KEY)
509
+share->key_parts*sizeof(KEY_PART_INFO));
511
KEY_PART_INFO *key_part;
513
key_part= reinterpret_cast<KEY_PART_INFO*>
514
(share->key_info+table.indexes_size());
517
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
518
sizeof(ulong*)*share->key_parts);
520
share->keynames.count= table.indexes_size();
521
share->keynames.name= NULL;
522
share->keynames.type_names= (const char**)
523
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
525
share->keynames.type_lengths= (unsigned int*)
526
alloc_root(&share->mem_root,
527
sizeof(unsigned int) * (table.indexes_size()+1));
529
share->keynames.type_names[share->keynames.count]= NULL;
530
share->keynames.type_lengths[share->keynames.count]= 0;
532
KEY* keyinfo= share->key_info;
533
for (int keynr=0; keynr < table.indexes_size(); keynr++, keyinfo++)
535
drizzle::Table::Index indx= table.indexes(keynr);
541
keyinfo->flags|= HA_NOSAME;
543
if(indx.has_options())
545
drizzle::Table::Index::IndexOptions indx_options= indx.options();
546
if(indx_options.pack_key())
547
keyinfo->flags|= HA_PACK_KEY;
549
if(indx_options.var_length_key())
550
keyinfo->flags|= HA_VAR_LENGTH_PART;
552
if(indx_options.null_part_key())
553
keyinfo->flags|= HA_NULL_PART_KEY;
555
if(indx_options.binary_pack_key())
556
keyinfo->flags|= HA_BINARY_PACK_KEY;
558
if(indx_options.has_partial_segments())
559
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
561
if(indx_options.auto_generated_key())
562
keyinfo->flags|= HA_GENERATED_KEY;
564
if(indx_options.has_key_block_size())
566
keyinfo->flags|= HA_USES_BLOCK_SIZE;
567
keyinfo->block_size= indx_options.key_block_size();
571
keyinfo->block_size= 0;
578
case drizzle::Table::Index::UNKNOWN_INDEX:
579
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
581
case drizzle::Table::Index::BTREE:
582
keyinfo->algorithm= HA_KEY_ALG_BTREE;
584
case drizzle::Table::Index::RTREE:
585
keyinfo->algorithm= HA_KEY_ALG_RTREE;
587
case drizzle::Table::Index::HASH:
588
keyinfo->algorithm= HA_KEY_ALG_HASH;
590
case drizzle::Table::Index::FULLTEXT:
591
keyinfo->algorithm= HA_KEY_ALG_FULLTEXT;
594
/* TODO: suitable warning ? */
595
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
599
keyinfo->key_length= indx.key_length();
601
keyinfo->key_parts= indx.index_part_size();
603
keyinfo->key_part= key_part;
549
604
keyinfo->rec_per_key= rec_per_key;
550
for (j=keyinfo->key_parts ; j-- ; key_part++)
606
for(unsigned int partnr= 0;
607
partnr < keyinfo->key_parts;
608
partnr++, key_part++)
610
drizzle::Table::Index::IndexPart part;
611
part= indx.index_part(partnr);
552
613
*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);
615
key_part->field= NULL;
616
key_part->fieldnr= part.fieldnr() + 1; // start from 1.
617
key_part->null_bit= 0;
618
/* key_part->null_offset is only set if null_bit (see later) */
619
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
620
/* key_part->type ???? */
621
key_part->key_part_flag= 0;
622
if(part.has_in_reverse_order())
623
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
625
key_part->length= part.compare_length();
627
key_part->store_length= key_part->length;
629
/* key_part->offset is set later */
630
key_part->key_type= part.key_type();
634
if(!indx.has_comment())
636
keyinfo->comment.length= 0;
637
keyinfo->comment.str= NULL;
641
keyinfo->flags|= HA_USES_COMMENT;
642
keyinfo->comment.length= indx.comment().length();
643
keyinfo->comment.str= strmake_root(&share->mem_root,
644
indx.comment().c_str(),
645
keyinfo->comment.length);
648
keyinfo->name= strmake_root(&share->mem_root,
650
indx.name().length());
652
share->keynames.type_names[keynr]= keyinfo->name;
653
share->keynames.type_lengths[keynr]= indx.name().length();
656
share->keys_for_keyread.init(0);
657
share->keys_in_use.init(share->keys);
659
if(table_options.has_connect_string())
661
size_t len= table_options.connect_string().length();
662
const char* str= table_options.connect_string().c_str();
664
share->connect_string.length= len;
665
share->connect_string.str= strmake_root(&share->mem_root, str, len);
668
if(table_options.has_comment())
670
size_t len= table_options.comment().length();
671
const char* str= table_options.comment().c_str();
673
share->comment.length= len;
674
share->comment.str= strmake_root(&share->mem_root, str, len);
677
share->key_block_size= table_options.has_key_block_size() ?
678
table_options.key_block_size() : 0;
680
share->fields= table.field_size();
682
share->stored_fields= share->fields;
684
share->field= (Field**) alloc_root(&share->mem_root,
685
((share->fields+1) * sizeof(Field*)));
686
share->field[share->fields]= NULL;
688
uint32_t null_fields= 0;
691
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
692
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
694
assert(field_offsets && field_pack_length); // TODO: fixme
696
uint32_t interval_count= 0;
697
uint32_t interval_parts= 0;
699
uint32_t stored_columns_reclength= 0;
701
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
703
drizzle::Table::Field pfield= table.field(fieldnr);
704
if(pfield.has_constraints() && pfield.constraints().is_nullable())
707
bool field_is_stored= true;
709
enum_field_types drizzle_field_type=
710
proto_field_type_to_drizzle_type(pfield.type());
712
if(drizzle_field_type==DRIZZLE_TYPE_VIRTUAL)
714
drizzle::Table::Field::VirtualFieldOptions field_options=
715
pfield.virtual_options();
717
drizzle_field_type=proto_field_type_to_drizzle_type(field_options.type());
719
field_is_stored= field_options.physically_stored();
722
field_offsets[fieldnr]= stored_columns_reclength;
724
/* the below switch is very similar to
725
Create_field::create_length_to_internal_length in field.cc
726
(which should one day be replace by just this code)
728
switch(drizzle_field_type)
730
case DRIZZLE_TYPE_BLOB:
731
case DRIZZLE_TYPE_VARCHAR:
733
drizzle::Table::Field::StringFieldOptions field_options=
734
pfield.string_options();
736
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id()?
737
field_options.collation_id() : 0);
740
cs= default_charset_info;
742
field_pack_length[fieldnr]=
743
calc_pack_length(drizzle_field_type,
744
field_options.length() * cs->mbmaxlen);
748
case DRIZZLE_TYPE_ENUM:
750
drizzle::Table::Field::SetFieldOptions field_options=
751
pfield.set_options();
753
field_pack_length[fieldnr]=
754
get_enum_pack_length(field_options.field_value_size());
757
interval_parts+= field_options.field_value_size();
760
case DRIZZLE_TYPE_NEWDECIMAL:
762
drizzle::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
764
field_pack_length[fieldnr]=
765
my_decimal_get_binary_size(fo.precision(), fo.scale());
769
/* Zero is okay here as length is fixed for other types. */
770
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
773
share->reclength+= field_pack_length[fieldnr];
776
stored_columns_reclength+= field_pack_length[fieldnr];
779
/* data_offset added to stored_rec_length later */
780
share->stored_rec_length= stored_columns_reclength;
782
/* fix up offsets for non-stored fields (at end of record) */
783
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
785
drizzle::Table::Field pfield= table.field(fieldnr);
787
bool field_is_stored= true;
789
enum_field_types drizzle_field_type=
790
proto_field_type_to_drizzle_type(pfield.type());
792
if(drizzle_field_type==DRIZZLE_TYPE_VIRTUAL)
794
drizzle::Table::Field::VirtualFieldOptions field_options=
795
pfield.virtual_options();
797
field_is_stored= field_options.physically_stored();
802
field_offsets[fieldnr]= stored_columns_reclength;
803
stored_columns_reclength+= field_pack_length[fieldnr];
806
share->null_fields= null_fields;
808
ulong null_bits= null_fields;
809
if(!table_options.pack_record())
811
ulong data_offset= (null_bits + 7)/8;
814
share->reclength+= data_offset;
815
share->stored_rec_length+= data_offset;
817
ulong rec_buff_length;
819
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
717
820
share->rec_buff_length= rec_buff_length;
822
unsigned char* record= NULL;
718
824
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
719
825
rec_buff_length)))
720
goto err; /* purecov: inspected */
828
memset(record, 0, rec_buff_length);
832
if(!table_options.pack_record())
834
null_count++; // one bit for delete mark.
721
838
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);
842
share->intervals= (TYPELIB*)alloc_root(&share->mem_root,
843
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,
846
share->intervals= NULL;
848
share->fieldnames.type_names= (const char**)alloc_root(&share->mem_root,
849
(share->fields+1)*sizeof(char*));
851
share->fieldnames.type_lengths= (unsigned int*) alloc_root(&share->mem_root,
852
(share->fields+1)*sizeof(unsigned int));
854
share->fieldnames.type_names[share->fields]= NULL;
855
share->fieldnames.type_lengths[share->fields]= 0;
856
share->fieldnames.count= share->fields;
859
/* Now fix the TYPELIBs for the intervals (enum values)
863
uint32_t interval_nr= 0;
865
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;
867
drizzle::Table::Field pfield= table.field(fieldnr);
870
share->fieldnames.type_names[fieldnr]= strmake_root(&share->mem_root,
871
pfield.name().c_str(),
872
pfield.name().length());
874
share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
877
if(pfield.type() != drizzle::Table::Field::ENUM)
880
drizzle::Table::Field::SetFieldOptions field_options=
881
pfield.set_options();
883
const CHARSET_INFO *charset= get_charset(field_options.has_collation_id()?
884
field_options.collation_id() : 0);
887
charset= default_charset_info;
889
TYPELIB *t= &(share->intervals[interval_nr]);
891
t->type_names= (const char**)alloc_root(&share->mem_root,
892
(field_options.field_value_size()+1)*sizeof(char*));
894
t->type_lengths= (unsigned int*) alloc_root(&share->mem_root,
895
(field_options.field_value_size()+1)*sizeof(unsigned int));
897
t->type_names[field_options.field_value_size()]= NULL;
898
t->type_lengths[field_options.field_value_size()]= 0;
900
t->count= field_options.field_value_size();
903
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;
905
t->type_names[n]= strmake_root(&share->mem_root,
906
field_options.field_value(n).c_str(),
907
field_options.field_value(n).length());
909
/* Go ask the charset what the length is as for "" length=1
910
and there's stripping spaces or some other crack going on.
913
lengthsp= charset->cset->lengthsp(charset, t->type_names[n],
914
field_options.field_value(n).length());
915
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;
921
/* and read the fields */
924
bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
818
927
use_hash= !hash_init(&share->name_hash,
819
928
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++)
930
(hash_get_key) get_field_name, 0, 0);
932
unsigned char* null_pos= record;;
933
int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
935
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;
937
drizzle::Table::Field pfield= table.field(fieldnr);
827
939
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
828
const CHARSET_INFO *charset= NULL;
941
switch(pfield.format())
943
case drizzle::Table::Field::DefaultFormat:
944
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
946
case drizzle::Table::Field::FixedFormat:
947
column_format= COLUMN_FORMAT_TYPE_FIXED;
949
case drizzle::Table::Field::DynamicFormat:
950
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
956
Field::utype unireg_type= Field::NONE;
958
if(pfield.has_numeric_options()
959
&& pfield.numeric_options().is_autoincrement())
961
unireg_type= Field::NEXT_NUMBER;
964
if(pfield.has_options()
965
&& pfield.options().has_default_value()
966
&& pfield.options().default_value().compare("NOW()")==0)
968
if(pfield.options().has_update_value()
969
&& pfield.options().update_value().compare("NOW()")==0)
971
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
973
else if (!pfield.options().has_update_value())
975
unireg_type= Field::TIMESTAMP_DN_FIELD;
978
assert(1); // Invalid update value.
980
else if (pfield.has_options()
981
&& pfield.options().has_update_value()
982
&& pfield.options().update_value().compare("NOW()")==0)
984
unireg_type= Field::TIMESTAMP_UN_FIELD;
829
987
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;
988
if(!pfield.has_comment())
990
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))
995
size_t len= pfield.comment().length();
996
const char* str= pfield.comment().c_str();
998
comment.str= strmake_root(&share->mem_root, str, len);
1002
enum_field_types field_type;
1003
virtual_column_info *vcol_info= NULL;
1004
bool field_is_stored= true;
1007
field_type= proto_field_type_to_drizzle_type(pfield.type());
1009
if(field_type==DRIZZLE_TYPE_VIRTUAL)
1011
drizzle::Table::Field::VirtualFieldOptions field_options=
1012
pfield.virtual_options();
1014
vcol_info= new virtual_column_info();
1015
field_type= proto_field_type_to_drizzle_type(field_options.type());
1016
field_is_stored= field_options.physically_stored();
1018
size_t len= field_options.expression().length();
1019
const char* str= field_options.expression().c_str();
1021
vcol_info->expr_str.str= strmake_root(&share->mem_root, str, len);
1022
vcol_info->expr_str.length= len;
1027
const CHARSET_INFO *charset= &my_charset_bin;
1029
if(field_type==DRIZZLE_TYPE_BLOB
1030
|| field_type==DRIZZLE_TYPE_VARCHAR)
1032
drizzle::Table::Field::StringFieldOptions field_options=
1033
pfield.string_options();
1035
charset= get_charset(field_options.has_collation_id()?
1036
field_options.collation_id() : 0);
1039
charset= default_charset_info;
1043
if(field_type==DRIZZLE_TYPE_ENUM)
1045
drizzle::Table::Field::SetFieldOptions field_options=
1046
pfield.set_options();
1048
charset= get_charset(field_options.has_collation_id()?
1049
field_options.collation_id() : 0);
1052
charset= default_charset_info;
1056
Item *default_value= NULL;
1058
if(pfield.options().has_default_value()
1059
|| pfield.options().has_default_null()
1060
|| pfield.options().has_default_bin_value())
1062
default_value= default_value_item(field_type,
1064
pfield.options().default_null(),
1065
pfield.options().default_value(),
1066
pfield.options().default_bin_value());
1069
uint32_t pack_flag= pfield.pack_flag(); /* TODO: MUST DIE */
1071
Table temp_table; /* Use this so that BLOB DEFAULT '' works */
1072
memset(&temp_table, 0, sizeof(temp_table));
1073
temp_table.s= share;
1074
temp_table.in_use= session;
1075
temp_table.s->db_low_byte_first= 1; //handler->low_byte_first();
1076
temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
1078
Field* f= make_field(share, &share->mem_root,
1079
record+field_offsets[fieldnr]+data_offset,
1080
pfield.options().length(),
1086
(Field::utype) MTYP_TYPENR(unireg_type),
1087
((field_type==DRIZZLE_TYPE_ENUM)?
1088
share->intervals+(interval_nr++)
1090
share->fieldnames.type_names[fieldnr]);
1092
share->field[fieldnr]= f;
1094
f->init(&temp_table); /* blob default values need table obj */
1096
if(!(f->flags & NOT_NULL_FLAG))
1098
*f->null_ptr|= f->null_bit;
934
1099
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;
1106
int res= default_value->save_in_field(f, 1);
1107
(void)res; // TODO error handle;
1109
else if(f->real_type() == DRIZZLE_TYPE_ENUM &&
1110
(f->flags & NOT_NULL_FLAG))
1113
f->store((int64_t) 1, true);
1118
/* hack to undo f->init() */
1120
f->orig_table= NULL;
1122
f->field_index= fieldnr;
1123
f->comment= comment;
1124
f->vcol_info= vcol_info;
1125
f->is_stored= field_is_stored;
1127
&& !(f->unireg_check==Field::NEXT_NUMBER)
1128
&& (f->flags & NOT_NULL_FLAG)
1129
&& (f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
1130
f->flags|= NO_DEFAULT_VALUE_FLAG;
1132
if(f->unireg_check == Field::NEXT_NUMBER)
1133
share->found_next_number_field= &(share->field[fieldnr]);
1135
if(share->timestamp_field == f)
1136
share->timestamp_field_offset= fieldnr;
1138
if (use_hash) /* supposedly this never fails... but comments lie */
946
1139
(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,
1140
(unsigned char*)&(share->field[fieldnr]));
1144
share->stored_fields--;
1148
keyinfo= share->key_info;
1149
for (unsigned int keynr=0; keynr < share->keys; keynr++, keyinfo++)
1151
key_part= keyinfo->key_part;
1153
for(unsigned int partnr= 0;
1154
partnr < keyinfo->key_parts;
1155
partnr++, key_part++)
1157
/* Fix up key_part->offset by adding data_offset.
1158
We really should compute offset as well.
1159
But at least this way we are a little better. */
1160
key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
1165
We need to set the unused bits to 1. If the number of bits is a multiple
1166
of 8 there are no unused bits.
1170
*(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1172
share->null_bytes= (null_pos - (unsigned char*) record +
1173
(null_bit_pos + 7) / 8);
1175
share->last_null_bit_pos= null_bit_pos;
1177
free(field_offsets);
1178
free(field_pack_length);
1180
handler *handler_file;
1182
if(!(handler_file= get_new_handler(share, session->mem_root,
1187
if (share->key_parts)
1189
uint32_t primary_key=(uint32_t) (find_type((char*) "PRIMARY",
955
1190
&share->keynames, 3) - 1);
956
1192
int64_t ha_option= handler_file->ha_table_flags();
957
1194
keyinfo= share->key_info;
958
1195
key_part= keyinfo->key_part;
960
1197
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
962
1199
uint32_t usable_parts= 0;
963
keyinfo->name=(char*) share->keynames.type_names[key];
965
1201
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1160
1376
bitmap_set_all(&share->all_set);
1162
1378
delete handler_file;
1170
1382
share->error= error;
1171
1383
share->open_errno= my_errno;
1172
share->errarg= errarg;
1385
hash_free(&share->name_hash);
1175
1386
delete handler_file;
1176
hash_free(&share->name_hash);
1178
open_table_error(share, error, share->open_errno, errarg);
1387
open_table_error(share, error, share->open_errno, 0);
1392
Read table definition from a binary / text based .frm file
1396
session Thread handler
1397
share Fill this with table definition
1398
db_flags Bit mask of the following flags: OPEN_VIEW
1401
This function is called when the table definition is not cached in
1403
The data is returned in 'share', which is alloced by
1404
alloc_table_share().. The code assumes that share is initialized.
1408
1 Error (see open_table_error)
1409
2 Error (see open_table_error)
1410
3 Wrong data in .frm file
1411
4 Error (see open_table_error)
1412
5 Error (see open_table_error: charset unavailable)
1413
6 Unknown .frm version
1416
int open_table_def(Session *session, TABLE_SHARE *share, uint32_t)
1425
path.reserve(FN_REFLEN);
1426
path.append(share->normalized_path.str);
1427
string proto_path= path;
1429
path.append(reg_ext);
1431
proto_path.append(".dfe");
1433
drizzle::Table table;
1435
if((error= drizzle_read_table_proto(proto_path.c_str(), &table)))
1444
if(!table.IsInitialized())
1452
parse_table_proto(session, table, share);
1454
share->table_category= get_table_category(& share->db, & share->table_name);
1457
session->status_var.opened_shares++;
1460
if (error && !error_given)
1462
share->error= error;
1463
open_table_error(share, error, (share->open_errno= my_errno), 0);
1180
} /* open_binary_frm */
1470
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1471
This routine is used for error handling purposes.
1475
table Table object for which virtual columns are set-up
1480
static void clear_field_flag(Table *table)
1484
for (ptr= table->field; *ptr; ptr++)
1485
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1489
The function uses the feature in fix_fields where the flag
1490
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1491
This field must always be reset before returning from the function
1492
since it is used for other purposes as well.
1495
fix_fields_vcol_func()
1496
session The thread object
1497
func_item The item tree reference of the virtual columnfunction
1498
table The table object
1499
field_name The name of the processed field
1502
true An error occurred, something was wrong with the
1504
false Ok, a partition field array was created
1507
bool fix_fields_vcol_func(Session *session,
1510
const char *field_name)
1512
uint32_t dir_length, home_dir_length;
1515
TableList *save_table_list, *save_first_table, *save_last_table;
1517
Name_resolution_context *context;
1518
const char *save_where;
1520
char db_name_string[FN_REFLEN];
1521
bool save_use_only_table_context;
1522
Field **ptr, *field;
1523
enum_mark_columns save_mark_used_columns= session->mark_used_columns;
1527
Set-up the TABLE_LIST object to be a list with a single table
1528
Set the object to zero to create NULL pointers and set alias
1529
and real name to table name and get database name from file name.
1532
bzero((void*)&tables, sizeof(TableList));
1533
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1534
tables.table= table;
1535
tables.next_local= NULL;
1536
tables.next_name_resolution_table= NULL;
1537
memcpy(db_name_string,
1538
table->s->normalized_path.str,
1539
table->s->normalized_path.length);
1540
db_name_string[table->s->normalized_path.length]= '\0';
1541
dir_length= dirname_length(db_name_string);
1542
db_name_string[dir_length - 1]= 0;
1543
home_dir_length= dirname_length(db_name_string);
1544
db_name= &db_name_string[home_dir_length];
1547
session->mark_used_columns= MARK_COLUMNS_NONE;
1549
context= session->lex->current_context();
1550
table->map= 1; //To ensure correct calculation of const item
1551
table->get_fields_in_item_tree= true;
1552
save_table_list= context->table_list;
1553
save_first_table= context->first_name_resolution_table;
1554
save_last_table= context->last_name_resolution_table;
1555
context->table_list= &tables;
1556
context->first_name_resolution_table= &tables;
1557
context->last_name_resolution_table= NULL;
1558
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1559
save_where= session->where;
1560
session->where= "virtual column function";
1562
/* Save the context before fixing the fields*/
1563
save_use_only_table_context= session->lex->use_only_table_context;
1564
session->lex->use_only_table_context= true;
1565
/* Fix fields referenced to by the virtual column function */
1566
error= func_expr->fix_fields(session, (Item**)0);
1567
/* Restore the original context*/
1568
session->lex->use_only_table_context= save_use_only_table_context;
1569
context->table_list= save_table_list;
1570
context->first_name_resolution_table= save_first_table;
1571
context->last_name_resolution_table= save_last_table;
1573
if (unlikely(error))
1575
clear_field_flag(table);
1578
session->where= save_where;
1580
Walk through the Item tree checking if all items are valid
1581
to be part of the virtual column
1583
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1586
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1587
clear_field_flag(table);
1590
if (unlikely(func_expr->const_item()))
1592
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1593
clear_field_flag(table);
1596
/* Ensure that this virtual column is not based on another virtual field. */
1598
while ((field= *(ptr++)))
1600
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1603
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1604
clear_field_flag(table);
1609
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1610
when calling fix_fields.
1612
clear_field_flag(table);
1616
table->get_fields_in_item_tree= false;
1617
session->mark_used_columns= save_mark_used_columns;
1618
table->map= 0; //Restore old value
1623
Unpack the definition of a virtual column
1626
unpack_vcol_info_from_frm()
1627
session Thread handler
1628
table Table with the checked field
1629
field Pointer to Field object
1630
open_mode Open table mode needed to determine
1631
which errors need to be generated in a failure
1632
error_reported updated flag for the caller that no other error
1633
messages are to be generated.
1639
bool unpack_vcol_info_from_frm(Session *session,
1642
LEX_STRING *vcol_expr,
1643
open_table_mode open_mode,
1644
bool *error_reported)
1649
Step 1: Construct a statement for the parser.
1650
The parsed string needs to take the following format:
1651
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1653
char *vcol_expr_str;
1656
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1658
parse_vcol_keyword.length + 3)))
1662
memcpy(vcol_expr_str,
1663
(char*) parse_vcol_keyword.str,
1664
parse_vcol_keyword.length);
1665
str_len= parse_vcol_keyword.length;
1666
memcpy(vcol_expr_str + str_len, "(", 1);
1668
memcpy(vcol_expr_str + str_len,
1669
(char*) vcol_expr->str,
1671
str_len+= vcol_expr->length;
1672
memcpy(vcol_expr_str + str_len, ")", 1);
1674
memcpy(vcol_expr_str + str_len, "\0", 1);
1676
Lex_input_stream lip(session, vcol_expr_str, str_len);
1679
Step 2: Setup session for parsing.
1680
1) make Item objects be created in the memory allocated for the Table
1681
object (not TABLE_SHARE)
1682
2) ensure that created Item's are not put on to session->free_list
1683
(which is associated with the parsed statement and hence cleared after
1685
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1686
to be parsed as a SQL command.
1688
MEM_ROOT **root_ptr, *old_root;
1689
Item *backup_free_list= session->free_list;
1690
root_ptr= current_mem_root_ptr();
1691
old_root= *root_ptr;
1692
*root_ptr= &table->mem_root;
1693
session->free_list= NULL;
1694
session->lex->parse_vcol_expr= true;
1697
Step 3: Use the parser to build an Item object from.
1699
if (parse_sql(session, &lip))
1703
/* From now on use vcol_info generated by the parser. */
1704
field->vcol_info= session->lex->vcol_info;
1706
/* Validate the Item tree. */
1707
if (fix_fields_vcol_func(session,
1708
field->vcol_info->expr_item,
1712
if (open_mode == OTM_CREATE)
1715
During CREATE/ALTER TABLE it is ok to receive errors here.
1716
It is not ok if it happens during the opening of an frm
1717
file as part of a normal query.
1719
*error_reported= true;
1721
field->vcol_info= NULL;
1724
field->vcol_info->item_free_list= session->free_list;
1725
session->free_list= backup_free_list;
1726
*root_ptr= old_root;
1731
session->lex->parse_vcol_expr= false;
1732
session->free_items();
1733
*root_ptr= old_root;
1734
session->free_list= backup_free_list;