diff options
author | Sergei Golubchik <sergii@pisem.net> | 2010-11-25 18:17:28 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2010-11-25 18:17:28 +0100 |
commit | 65ca700def99289cc31a7040537f5aa6e12bf485 (patch) | |
tree | 97b3a07299b626c519da0e80c122b5b79b933914 /sql/unireg.cc | |
parent | 2ab57de38d13d927ddff2d51aed4af34e13998f5 (diff) | |
parent | 6e5bcca7935d3c62f84bb640e5357664a210ee12 (diff) | |
download | mariadb-git-65ca700def99289cc31a7040537f5aa6e12bf485.tar.gz |
merge.
checkpoint.
does not compile.
Diffstat (limited to 'sql/unireg.cc')
-rw-r--r-- | sql/unireg.cc | 124 |
1 files changed, 112 insertions, 12 deletions
diff --git a/sql/unireg.cc b/sql/unireg.cc index 6433b8bc7c2..b4fbd2aea3e 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -28,11 +28,15 @@ #include "sql_partition.h" // struct partition_info #include "sql_table.h" // check_duplicate_warning #include "sql_class.h" // THD, Internal_error_handler +#include "create_options.h" #include <m_ctype.h> #include <assert.h> #define FCOMP 17 /* Bytes for a packed field */ +/* threshold for safe_alloca */ +#define ALLOCA_THRESHOLD 2048 + static uchar * pack_screens(List<Create_field> &create_fields, uint *info_length, uint *screens, bool small_file); static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info, @@ -116,6 +120,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, ulong key_buff_length; File file; ulong filepos, data_offset; + uint options_len; uchar fileinfo[64],forminfo[288],*keybuff; uchar *screen_buff; char buff[128]; @@ -166,8 +171,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, reclength=uint2korr(forminfo+266); /* Calculate extra data segment length */ - str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type); - str_db_type.length= strlen(str_db_type.str); + str_db_type= *hton_name(create_info->db_type); /* str_db_type */ create_info->extra_size= (2 + str_db_type.length + 2 + create_info->connect_string.length); @@ -191,6 +195,19 @@ bool mysql_create_frm(THD *thd, const char *file_name, if (key_info[i].parser_name) create_info->extra_size+= key_info[i].parser_name->length + 1; } + + options_len= engine_table_options_frm_length(create_info->option_list, + create_fields, + keys, key_info); + DBUG_PRINT("info", ("Options length: %u", options_len)); + if (options_len) + { + create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS; + create_info->extra_size+= (options_len + 4); + } + else + create_info->table_options&= ~HA_OPTION_TEXT_CREATE_OPTIONS; + /* This gives us the byte-position of the character at (character-position, not byte-position) TABLE_COMMENT_MAXLEN. @@ -334,6 +351,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, if (mysql_file_write(file, (uchar*) buff, 6, MYF_RW)) goto err; } + for (i= 0; i < keys; i++) { if (key_info[i].parser_name) @@ -353,6 +371,24 @@ bool mysql_create_frm(THD *thd, const char *file_name, goto err; } + if (options_len) + { + uchar *optbuff= (uchar *)my_safe_alloca(options_len + 4, ALLOCA_THRESHOLD); + my_bool error; + DBUG_PRINT("info", ("Create options length: %u", options_len)); + if (!optbuff) + goto err; + int4store(optbuff, options_len); + engine_table_options_frm_image(optbuff + 4, + create_info->option_list, + create_fields, + keys, key_info); + error= my_write(file, optbuff, options_len + 4, MYF_RW); + my_safe_afree(optbuff, options_len + 4, ALLOCA_THRESHOLD); + if (error) + goto err; + } + mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0)); if (mysql_file_write(file, forminfo, 288, MYF_RW) || mysql_file_write(file, screen_buff, info_length, MYF_RW) || @@ -572,7 +608,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, int2store(pos+6, key->block_size); pos+=8; key_parts+=key->key_parts; - DBUG_PRINT("loop", ("flags: %lu key_parts: %d at 0x%lx", + DBUG_PRINT("loop", ("flags: %lu key_parts: %d key_part: 0x%lx", key->flags, key->key_parts, (long) key->key_part)); for (key_part=key->key_part,key_part_end=key_part+key->key_parts ; @@ -642,7 +678,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, { uint length,int_count,int_length,no_empty, int_parts; uint time_stamp_pos,null_fields; - ulong reclength, totlength, n_length, com_length; + ulong reclength, totlength, n_length, com_length, vcol_info_length; DBUG_ENTER("pack_header"); if (create_fields.elements > MAX_FIELDS) @@ -653,8 +689,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, totlength= 0L; reclength= data_offset; - no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields= - com_length=0; + no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0; + com_length=vcol_info_length=0; n_length=2L; /* Check fields */ @@ -686,6 +722,30 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ER_TOO_LONG_FIELD_COMMENT, warn_buff); field->comment.length= tmp_len; } + if (field->vcol_info) + { + tmp_len= + system_charset_info->cset->charpos(system_charset_info, + field->vcol_info->expr_str.str, + field->vcol_info->expr_str.str + + field->vcol_info->expr_str.length, + VIRTUAL_COLUMN_EXPRESSION_MAXLEN); + + if (tmp_len < field->vcol_info->expr_str.length) + { + my_error(ER_WRONG_STRING_LENGTH, MYF(0), + field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION", + (uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN); + DBUG_RETURN(1); + } + /* + Sum up the length of the expression string and the length of the + mandatory header to the total length of info on the defining + expressions saved in the frm file for virtual columns. + */ + vcol_info_length+= field->vcol_info->expr_str.length+ + (uint)FRM_VCOL_HEADER_SIZE; + } totlength+= field->length; com_length+= field->comment.length; @@ -705,8 +765,6 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, !time_stamp_pos) time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1; length=field->pack_length; - /* Ensure we don't have any bugs when generating offsets */ - DBUG_ASSERT(reclength == field->offset + data_offset); if ((uint) field->offset+ (uint) data_offset+ length > reclength) reclength=(uint) (field->offset+ data_offset + length); n_length+= (ulong) strlen(field->field_name)+1; @@ -773,7 +831,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, /* Hack to avoid bugs with small static rows in MySQL */ reclength=max(file->min_record_length(table_options),reclength); if (info_length+(ulong) create_fields.elements*FCOMP+288+ - n_length+int_length+com_length > 65535L || int_count > 255) + n_length+int_length+com_length+vcol_info_length > 65535L || + int_count > 255) { my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0)); DBUG_RETURN(1); @@ -781,7 +840,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, bzero((char*)forminfo,288); length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+ - com_length); + com_length+vcol_info_length); int2store(forminfo,length); forminfo[256] = (uint8) screens; int2store(forminfo+258,create_fields.elements); @@ -798,7 +857,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, int2store(forminfo+280,22); /* Rows needed */ int2store(forminfo+282,null_fields); int2store(forminfo+284,com_length); - /* Up to forminfo+288 is free to use for additional information */ + int2store(forminfo+286,vcol_info_length); + /* forminfo+288 is free to use for additional information */ DBUG_RETURN(0); } /* pack_header */ @@ -837,7 +897,7 @@ static bool pack_fields(File file, List<Create_field> &create_fields, ulong data_offset) { reg2 uint i; - uint int_count, comment_length=0; + uint int_count, comment_length= 0, vcol_info_length=0; uchar buff[MAX_FIELD_WIDTH]; Create_field *field; DBUG_ENTER("pack_fields"); @@ -850,6 +910,7 @@ static bool pack_fields(File file, List<Create_field> &create_fields, while ((field=it++)) { uint recpos; + uint cur_vcol_expr_len= 0; buff[0]= (uchar) field->row; buff[1]= (uchar) field->col; buff[2]= (uchar) field->sc_length; @@ -879,6 +940,17 @@ static bool pack_fields(File file, List<Create_field> &create_fields, { buff[11]= buff[14]= 0; // Numerical } + if (field->vcol_info) + { + /* + Use the interval_id place in the .frm file to store the length of + the additional data saved for the virtual field + */ + buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length + + (uint)FRM_VCOL_HEADER_SIZE; + vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE; + buff[13]= (uchar) MYSQL_TYPE_VIRTUAL; + } int2store(buff+15, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); @@ -973,6 +1045,34 @@ static bool pack_fields(File file, List<Create_field> &create_fields, DBUG_RETURN(1); } } + if (vcol_info_length) + { + it.rewind(); + int_count=0; + while ((field=it++)) + { + /* + Pack each virtual field as follows: + byte 1 = 1 (always 1 to allow for future extensions) + byte 2 = sql_type + byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored) + byte 4-... = virtual column expression (text data) + */ + if (field->vcol_info && field->vcol_info->expr_str.length) + { + buff[0]= (uchar)1; + buff[1]= (uchar) field->sql_type; + buff[2]= (uchar) field->stored_in_db; + if (my_write(file, buff, 3, MYF_RW)) + DBUG_RETURN(1); + if (my_write(file, + (uchar*) field->vcol_info->expr_str.str, + field->vcol_info->expr_str.length, + MYF_RW)) + DBUG_RETURN(1); + } + } + } DBUG_RETURN(0); } |