diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-07-11 14:50:39 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-07-11 21:51:18 +0400 |
commit | 1517087b546bf97ab2afe0e81af0cdfddd323e77 (patch) | |
tree | 4de8845cdec7338ffdd33a574162c0b38e267b53 /sql/unireg.cc | |
parent | c8e94e5eda777578f07409e8a060305776b7ac55 (diff) | |
download | mariadb-git-1517087b546bf97ab2afe0e81af0cdfddd323e77.tar.gz |
MDEV-20042 Implement EXTRA2_FIELD_DATA_TYPE_INFO in FRM
Diffstat (limited to 'sql/unireg.cc')
-rw-r--r-- | sql/unireg.cc | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/sql/unireg.cc b/sql/unireg.cc index b82927a9d47..7130b3e5d8a 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -171,6 +171,61 @@ static uint gis_field_options_image(uchar *buff, } +class Field_data_type_info_image: public BinaryStringBuffer<512> +{ + static uchar *store_length(uchar *pos, ulonglong length) + { + return net_store_length(pos, length); + } + static uchar *store_string(uchar *pos, const LEX_CSTRING &str) + { + pos= store_length(pos, str.length); + memcpy(pos, str.str, str.length); + return pos + str.length; + } + static uint store_length_required_length(ulonglong length) + { + return net_length_size(length); + } +public: + Field_data_type_info_image() { } + bool append(uint fieldnr, const Column_definition &def) + { + BinaryStringBuffer<64> type_info; + if (def.type_handler()-> + Column_definition_data_type_info_image(&type_info, def) || + type_info.length() > 0xFFFF/*Some reasonable limit*/) + return true; // Error + if (!type_info.length()) + return false; + size_t need_length= store_length_required_length(fieldnr) + + store_length_required_length(type_info.length()) + + type_info.length(); + if (reserve(need_length)) + return true; // Error + uchar *pos= (uchar *) end(); + pos= store_length(pos, fieldnr); + pos= store_string(pos, type_info.lex_cstring()); + size_t new_length= (const char *) pos - ptr(); + DBUG_ASSERT(new_length < alloced_length()); + length((uint32) new_length); + return false; + } + bool append(List<Create_field> &fields) + { + uint fieldnr= 0; + Create_field *field; + List_iterator<Create_field> it(fields); + for (field= it++; field; field= it++, fieldnr++) + { + if (append(fieldnr, *field)) + return true; // Error + } + return false; + } +}; + + /** Create a frm (table definition) file @@ -210,6 +265,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, uchar *frm_ptr, *pos; LEX_CUSTRING frm= {0,0}; StringBuffer<MAX_FIELD_WIDTH> vcols; + Field_data_type_info_image field_data_type_info_image; DBUG_ENTER("build_frm_image"); /* If fixed row records, we need one bit to check for deleted rows */ @@ -263,6 +319,22 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, gis_extra2_len= gis_field_options_image(NULL, create_fields); DBUG_PRINT("info", ("Options length: %u", options_len)); + if (field_data_type_info_image.append(create_fields)) + { + my_printf_error(ER_CANT_CREATE_TABLE, + "Cannot create table %`s: " + "Building the field data type info image failed.", + MYF(0), table.str); + DBUG_RETURN(frm); + } + DBUG_PRINT("info", ("Field data type info length: %u", + (uint) field_data_type_info_image.length())); + DBUG_EXECUTE_IF("frm_data_type_info", + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, + "build_frm_image: Field data type info length: %u", + (uint) field_data_type_info_image.length());); + if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN, ER_TOO_LONG_TABLE_COMMENT, table.str)) DBUG_RETURN(frm); @@ -308,6 +380,9 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, if (gis_extra2_len) extra2_size+= 1 + extra2_str_size(gis_extra2_len); + if (field_data_type_info_image.length()) + extra2_size+= 1 + extra2_str_size(field_data_type_info_image.length()); + if (create_info->versioned()) { extra2_size+= 1 + extra2_str_size(2 * frm_fieldno_size); @@ -380,6 +455,22 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, pos+= gis_field_options_image(pos, create_fields); } + if (field_data_type_info_image.length()) + { + if (field_data_type_info_image.length() > 0xFFFF) + { + my_printf_error(ER_CANT_CREATE_TABLE, + "Cannot create table %`s: " + "field data type info image is too large. " + "Decrease the number of columns with " + "extended data types.", + MYF(0), table.str); + goto err; + } + *pos= EXTRA2_FIELD_DATA_TYPE_INFO; + pos= extra2_write_str(pos + 1, field_data_type_info_image.lex_cstring()); + } + // PERIOD if (create_info->period_info.is_set()) { |