diff options
Diffstat (limited to 'sql/unireg.cc')
-rw-r--r-- | sql/unireg.cc | 170 |
1 files changed, 130 insertions, 40 deletions
diff --git a/sql/unireg.cc b/sql/unireg.cc index ff2b406350a..6540e11578b 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -25,7 +25,7 @@ str is a (long) to record position where 0 is the first position. */ -#include <my_global.h> +#include "mariadb.h" #include "sql_priv.h" #include "unireg.h" #include "sql_partition.h" // struct partition_info @@ -73,7 +73,7 @@ static uchar *extra2_write_len(uchar *pos, size_t len) } static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, - LEX_STRING *str) + const LEX_CSTRING *str) { *pos++ = type; pos= extra2_write_len(pos, str->length); @@ -84,10 +84,72 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, LEX_CUSTRING *str) { - return extra2_write(pos, type, reinterpret_cast<LEX_STRING *>(str)); + return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str)); } -/* +static uchar *extra2_write_field_properties(uchar *pos, + List<Create_field> &create_fields) +{ + List_iterator<Create_field> it(create_fields); + *pos++= EXTRA2_FIELD_FLAGS; + /* + always first 2 for field visibility + */ + pos= extra2_write_len(pos, create_fields.elements); + while (Create_field *cf= it++) + { + uchar flags= cf->invisible; + if (cf->flags & VERS_UPDATE_UNVERSIONED_FLAG) + flags|= VERS_OPTIMIZED_UPDATE; + *pos++= flags; + } + return pos; +} + +static const bool ROW_START = true; +static const bool ROW_END = false; + +static inline +uint16 +vers_get_field(HA_CREATE_INFO *create_info, List<Create_field> &create_fields, bool row_start) +{ + DBUG_ASSERT(create_info->versioned()); + + List_iterator<Create_field> it(create_fields); + Create_field *sql_field = NULL; + + const Lex_ident row_field= row_start ? create_info->vers_info.as_row.start + : create_info->vers_info.as_row.end; + DBUG_ASSERT(row_field); + + for (unsigned field_no = 0; (sql_field = it++); ++field_no) + { + if (row_field.streq(sql_field->field_name)) + { + DBUG_ASSERT(field_no <= uint16(~0U)); + return uint16(field_no); + } + } + + DBUG_ASSERT(0); /* Not Reachable */ + return 0; +} + +static inline +bool has_extra2_field_flags(List<Create_field> &create_fields) +{ + List_iterator<Create_field> it(create_fields); + while (Create_field *f= it++) + { + if (f->invisible) + return true; + if (f->flags & VERS_UPDATE_UNVERSIONED_FLAG) + return true; + } + return false; +} + +/** Create a frm (table definition) file @param thd Thread handler @@ -102,20 +164,21 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, or null LEX_CUSTRING (str==0) in case of an error. */ -LEX_CUSTRING build_frm_image(THD *thd, const char *table, +LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, HA_CREATE_INFO *create_info, List<Create_field> &create_fields, uint keys, KEY *key_info, handler *db_file) { - LEX_STRING str_db_type; + LEX_CSTRING str_db_type; uint reclength, key_info_length, i; ulong key_buff_length; - ulong filepos, data_offset; + size_t filepos; + ulong data_offset; uint options_len; uint gis_extra2_len= 0; uchar fileinfo[FRM_HEADER_SIZE],forminfo[FRM_FORMINFO_SIZE]; const partition_info *part_info= IF_PARTITIONING(thd->work_part_info, 0); - int error; + bool error; uchar *frm_ptr, *pos; LEX_CUSTRING frm= {0,0}; StringBuffer<MAX_FIELD_WIDTH> vcols; @@ -131,15 +194,15 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, error= pack_vcols(&vcols, create_fields, create_info->check_constraint_list); thd->variables.sql_mode= save_sql_mode; - if (error) + if (unlikely(error)) DBUG_RETURN(frm); if (vcols.length()) create_info->expression_length= vcols.length() + FRM_VCOL_NEW_BASE_SIZE; error= pack_header(thd, forminfo, create_fields, create_info, - data_offset, db_file); - if (error) + (ulong)data_offset, db_file); + if (unlikely(error)) DBUG_RETURN(frm); reclength= uint2korr(forminfo+266); @@ -147,7 +210,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, /* Calculate extra data segment length */ str_db_type= *hton_name(create_info->db_type); /* str_db_type */ - create_info->extra_size= (2 + str_db_type.length + + create_info->extra_size= (uint)(2 + str_db_type.length + 2 + create_info->connect_string.length); /* Partition: @@ -158,12 +221,12 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, */ create_info->extra_size+= 6; if (part_info) - create_info->extra_size+= part_info->part_info_len; + create_info->extra_size+= (uint)part_info->part_info_len; for (i= 0; i < keys; i++) { if (key_info[i].parser_name) - create_info->extra_size+= key_info[i].parser_name->length + 1; + create_info->extra_size+= (uint)key_info[i].parser_name->length + 1; } options_len= engine_table_options_frm_length(create_info->option_list, @@ -175,8 +238,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, DBUG_PRINT("info", ("Options length: %u", options_len)); if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN, - ER_TOO_LONG_TABLE_COMMENT, - table)) + ER_TOO_LONG_TABLE_COMMENT, table->str)) DBUG_RETURN(frm); /* If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes, @@ -186,7 +248,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN) { forminfo[46]=255; - create_info->extra_size+= 2 + create_info->comment.length; + create_info->extra_size+= 2 + (uint)create_info->comment.length; } else { @@ -210,7 +272,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, prepare_frm_header(thd, reclength, fileinfo, create_info, keys, key_info); /* one byte for a type, one or three for a length */ - uint extra2_size= 1 + 1 + create_info->tabledef_version.length; + size_t extra2_size= 1 + 1 + create_info->tabledef_version.length; if (options_len) extra2_size+= 1 + (options_len > 255 ? 3 : 1) + options_len; @@ -220,6 +282,17 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, if (gis_extra2_len) extra2_size+= 1 + (gis_extra2_len > 255 ? 3 : 1) + gis_extra2_len; + if (create_info->versioned()) + { + extra2_size+= 1 + 1 + 2 * sizeof(uint16); + } + + bool has_extra2_field_flags_= has_extra2_field_flags(create_fields); + if (has_extra2_field_flags_) + { + extra2_size+= 1 + (create_fields.elements > 255 ? 3 : 1) + + create_fields.elements; + } key_buff_length= uint4korr(fileinfo+47); @@ -240,7 +313,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, if (frm.length > FRM_MAX_SIZE || create_info->expression_length > UINT_MAX32) { - my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table); + my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table->str); DBUG_RETURN(frm); } @@ -276,6 +349,19 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, } #endif /*HAVE_SPATIAL*/ + if (create_info->versioned()) + { + *pos++= EXTRA2_PERIOD_FOR_SYSTEM_TIME; + *pos++= 2 * sizeof(uint16); + int2store(pos, vers_get_field(create_info, create_fields, ROW_START)); + pos+= sizeof(uint16); + int2store(pos, vers_get_field(create_info, create_fields, ROW_END)); + pos+= sizeof(uint16); + } + + if (has_extra2_field_flags_) + pos= extra2_write_field_properties(pos, create_fields); + int4store(pos, filepos); // end of the extra2 segment pos+= 4; @@ -286,7 +372,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, my_printf_error(ER_CANT_CREATE_TABLE, "Cannot create table %`s: index information is too long. " "Decrease number of indexes or use shorter index names or shorter comments.", - MYF(0), table); + MYF(0), table->str); goto err; } @@ -487,7 +573,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, *pos++=(uchar) NAMES_SEP_CHAR; for (key=keyinfo ; key != end ; key++) { - uchar *tmp=(uchar*) strmov((char*) pos,key->name); + uchar *tmp=(uchar*) strmov((char*) pos,key->name.str); *tmp++= (uchar) NAMES_SEP_CHAR; *tmp=0; pos=tmp; @@ -548,7 +634,7 @@ static bool pack_expression(String *buf, Virtual_column_info *vcol, size_t len_off= buf->length(); buf->q_append2b(0); // to be added later buf->q_append((char)vcol->name.length); - buf->q_append(vcol->name.str, vcol->name.length); + buf->q_append(&vcol->name); size_t expr_start= buf->length(); vcol->print(buf); size_t expr_len= buf->length() - expr_start; @@ -625,7 +711,8 @@ static bool pack_header(THD *thd, uchar *forminfo, while ((field=it++)) { if (validate_comment_length(thd, &field->comment, COLUMN_COMMENT_MAXLEN, - ER_TOO_LONG_FIELD_COMMENT, field->field_name)) + ER_TOO_LONG_FIELD_COMMENT, + field->field_name.str)) DBUG_RETURN(1); totlength+= (size_t)field->length; @@ -634,14 +721,14 @@ static bool pack_header(THD *thd, uchar *forminfo, We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE as auto-update field. */ - if (field->sql_type == MYSQL_TYPE_TIMESTAMP && + if (field->real_field_type() == MYSQL_TYPE_TIMESTAMP && MTYP_TYPENR(field->unireg_check) != Field::NONE && !time_stamp_pos) time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1; length=field->pack_length; if ((uint) field->offset+ (uint) data_offset+ length > reclength) reclength=(uint) (field->offset+ data_offset + length); - n_length+= (ulong) strlen(field->field_name)+1; + n_length+= field->field_name.length + 1; field->interval_id=0; field->save_interval= 0; if (field->interval) @@ -672,10 +759,10 @@ static bool pack_header(THD *thd, uchar *forminfo, { char *dst; const char *src= field->save_interval->type_names[pos]; - uint hex_length; + size_t hex_length; length= field->save_interval->type_lengths[pos]; hex_length= length * 2; - field->interval->type_lengths[pos]= hex_length; + field->interval->type_lengths[pos]= (uint)hex_length; field->interval->type_names[pos]= dst= (char*) thd->alloc(hex_length + 1); octet2hex(dst, src, length); @@ -785,7 +872,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields) } length+= FCOMP; - length+= strlen(field->field_name)+1; + length+= field->field_name.length + 1; length+= field->comment.length; } length+= 2; @@ -799,7 +886,8 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, ulong data_offset) { uchar *buff= *buff_arg; - uint int_count, comment_length= 0; + uint int_count; + size_t comment_length= 0; Create_field *field; DBUG_ENTER("pack_fields"); @@ -816,8 +904,8 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, int2store(buff+8,field->pack_flag); buff[10]= (uchar) field->unireg_check; buff[12]= (uchar) field->interval_id; - buff[13]= (uchar) field->sql_type; - if (field->sql_type == MYSQL_TYPE_GEOMETRY) + buff[13]= (uchar) field->real_field_type(); + if (field->real_field_type() == MYSQL_TYPE_GEOMETRY) { buff[11]= 0; buff[14]= (uchar) field->geom_type; @@ -846,7 +934,7 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, it.rewind(); while ((field=it++)) { - buff= (uchar*)strmov((char*) buff, field->field_name); + buff= (uchar*)strmov((char*) buff, field->field_name.str); *buff++=NAMES_SEP_CHAR; } *buff++= 0; @@ -962,13 +1050,14 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, null_pos + null_count / 8, null_count & 7, field->pack_flag, - field->sql_type, + field->type_handler(), field->charset, field->geom_type, field->srid, field->unireg_check, field->save_interval ? field->save_interval : field->interval, - field->field_name); + &field->field_name, + field->flags); if (!regfield) { error= 1; @@ -984,16 +1073,17 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, null_count++; } - if (field->sql_type == MYSQL_TYPE_BIT && !f_bit_as_char(field->pack_flag)) + if (field->real_field_type() == MYSQL_TYPE_BIT && + !f_bit_as_char(field->pack_flag)) null_count+= field->length & 7; if (field->default_value && !field->default_value->flags && - (!(field->flags & BLOB_FLAG) || field->sql_type == MYSQL_TYPE_GEOMETRY)) + (!(field->flags & BLOB_FLAG) || + field->real_field_type() == MYSQL_TYPE_GEOMETRY)) { Item *expr= field->default_value->expr; - - int res= !expr->fixed && // may be already fixed if ALTER TABLE - expr->fix_fields(thd, &expr); + // may be already fixed if ALTER TABLE + int res= expr->fix_fields_if_needed(thd, &expr); if (!res) res= expr->save_in_field(regfield, 1); if (!res && (field->flags & BLOB_FLAG)) @@ -1002,7 +1092,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, /* If not ok or warning of level 'note' */ if (res != 0 && res != 3) { - my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name); + my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str); error= 1; delete regfield; //To avoid memory leak goto err; |