diff options
Diffstat (limited to 'sql/unireg.cc')
-rw-r--r-- | sql/unireg.cc | 273 |
1 files changed, 115 insertions, 158 deletions
diff --git a/sql/unireg.cc b/sql/unireg.cc index 40fde228f80..d019b5f8a75 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -39,7 +39,7 @@ /* threshold for safe_alloca */ #define ALLOCA_THRESHOLD 2048 -static uint pack_keys(uchar *,uint, KEY *, ulong); +static uint pack_keys(uchar *,uint, KEY *, ulong, uint); static bool pack_header(THD *, uchar *, List<Create_field> &, HA_CREATE_INFO *, ulong, handler *); static bool pack_vcols(String *, List<Create_field> &, List<Virtual_column_info> *); @@ -72,19 +72,24 @@ static uchar *extra2_write_len(uchar *pos, size_t len) return pos; } +static uchar* extra2_write_str(uchar *pos, const LEX_CSTRING &str) +{ + pos= extra2_write_len(pos, str.length); + memcpy(pos, str.str, str.length); + return pos + str.length; +} + static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, - const LEX_CSTRING *str) + const LEX_CSTRING &str) { *pos++ = type; - pos= extra2_write_len(pos, str->length); - memcpy(pos, str->str, str->length); - return pos + str->length; + return extra2_write_str(pos, str); } static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, - LEX_CUSTRING *str) + const LEX_CUSTRING &str) { - return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str)); + return extra2_write(pos, type, *reinterpret_cast<const LEX_CSTRING*>(&str)); } static uchar *extra2_write_field_properties(uchar *pos, @@ -106,25 +111,18 @@ static uchar *extra2_write_field_properties(uchar *pos, 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) +static uint16 +get_fieldno_by_name(HA_CREATE_INFO *create_info, List<Create_field> &create_fields, + const Lex_ident &field_name) { - 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); + DBUG_ASSERT(field_name); for (unsigned field_no = 0; (sql_field = it++); ++field_no) { - if (row_field.streq(sql_field->field_name)) + if (field_name.streq(sql_field->field_name)) { DBUG_ASSERT(field_no <= uint16(~0U)); return uint16(field_no); @@ -149,6 +147,11 @@ bool has_extra2_field_flags(List<Create_field> &create_fields) return false; } +static size_t extra2_str_size(size_t len) +{ + return (len > 255 ? 3 : 1) + len; +} + /** Create a frm (table definition) file @@ -164,7 +167,7 @@ bool has_extra2_field_flags(List<Create_field> &create_fields) or null LEX_CUSTRING (str==0) in case of an error. */ -LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *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) @@ -176,6 +179,12 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, ulong data_offset; uint options_len; uint gis_extra2_len= 0; + size_t period_info_len= create_info->period_info.name + ? extra2_str_size(create_info->period_info.name.length) + + extra2_str_size(create_info->period_info.constr->name.length) + + 2 * frm_fieldno_size + : 0; + uint e_unique_hash_extra_parts= 0; uchar fileinfo[FRM_HEADER_SIZE],forminfo[FRM_FORMINFO_SIZE]; const partition_info *part_info= IF_PARTITIONING(thd->work_part_info, 0); bool error; @@ -238,7 +247,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *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->str)) + ER_TOO_LONG_TABLE_COMMENT, table.str)) DBUG_RETURN(frm); /* If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes, @@ -272,28 +281,35 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, prepare_frm_header(thd, reclength, fileinfo, create_info, keys, key_info); /* one byte for a type, one or three for a length */ - size_t extra2_size= 1 + 1 + create_info->tabledef_version.length; + size_t extra2_size= 1 + extra2_str_size(create_info->tabledef_version.length); if (options_len) - extra2_size+= 1 + (options_len > 255 ? 3 : 1) + options_len; + extra2_size+= 1 + extra2_str_size(options_len); if (part_info) - extra2_size+= 1 + 1 + hton_name(part_info->default_engine_type)->length; + extra2_size+= 1 + extra2_str_size(hton_name(part_info->default_engine_type)->length); if (gis_extra2_len) - extra2_size+= 1 + (gis_extra2_len > 255 ? 3 : 1) + gis_extra2_len; + extra2_size+= 1 + extra2_str_size(gis_extra2_len); if (create_info->versioned()) { - extra2_size+= 1 + 1 + 2 * sizeof(uint16); + extra2_size+= 1 + extra2_str_size(2 * frm_fieldno_size); + } + + if (create_info->period_info.name) + { + extra2_size+= 1 + extra2_str_size(period_info_len); } 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; + extra2_size+= 1 + extra2_str_size(create_fields.elements); } + for (i= 0; i < keys; i++) + if (key_info[i].algorithm == HA_KEY_ALG_LONG_HASH) + e_unique_hash_extra_parts++; key_buff_length= uint4korr(fileinfo+47); frm.length= FRM_HEADER_SIZE; // fileinfo; @@ -313,7 +329,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, if (frm.length > FRM_MAX_SIZE || create_info->expression_length > UINT_MAX32) { - my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table->str); + my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table.str); DBUG_RETURN(frm); } @@ -326,11 +342,11 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, pos = frm_ptr + 64; compile_time_assert(EXTRA2_TABLEDEF_VERSION != '/'); pos= extra2_write(pos, EXTRA2_TABLEDEF_VERSION, - &create_info->tabledef_version); + create_info->tabledef_version); if (part_info) pos= extra2_write(pos, EXTRA2_DEFAULT_PART_ENGINE, - hton_name(part_info->default_engine_type)); + *hton_name(part_info->default_engine_type)); if (options_len) { @@ -349,14 +365,32 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, } #endif /*HAVE_SPATIAL*/ + // PERIOD + if (create_info->period_info.is_set()) + { + *pos++= EXTRA2_APPLICATION_TIME_PERIOD; + pos= extra2_write_len(pos, period_info_len); + pos= extra2_write_str(pos, create_info->period_info.name); + pos= extra2_write_str(pos, create_info->period_info.constr->name); + + store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields, + create_info->period_info.period.start)); + pos+= frm_fieldno_size; + store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields, + create_info->period_info.period.end)); + pos+= frm_fieldno_size; + } + 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); + *pos++= 2 * frm_fieldno_size; + store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields, + create_info->vers_info.as_row.start)); + pos+= frm_fieldno_size; + store_frm_fieldno(pos, get_fieldno_by_name(create_info, create_fields, + create_info->vers_info.as_row.end)); + pos+= frm_fieldno_size; } if (has_extra2_field_flags_) @@ -366,13 +400,13 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING *table, pos+= 4; DBUG_ASSERT(pos == frm_ptr + uint2korr(fileinfo+6)); - key_info_length= pack_keys(pos, keys, key_info, data_offset); + key_info_length= pack_keys(pos, keys, key_info, data_offset, e_unique_hash_extra_parts); if (key_info_length > UINT_MAX16) { 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->str); + MYF(0), table.str); goto err; } @@ -475,60 +509,10 @@ err: } -/** - Create a frm (table definition) file and the tables - - @param thd Thread handler - @param frm Binary frm image of the table to create - @param path Name of file (including database, without .frm) - @param db Data base name - @param table_name Table name - @param create_info create info parameters - @param file Handler to use or NULL if only frm needs to be created - - @retval 0 ok - @retval 1 error -*/ - -int rea_create_table(THD *thd, LEX_CUSTRING *frm, - const char *path, const char *db, const char *table_name, - HA_CREATE_INFO *create_info, handler *file, - bool no_ha_create_table) -{ - DBUG_ENTER("rea_create_table"); - - if (no_ha_create_table) - { - if (writefrm(path, db, table_name, true, frm->str, frm->length)) - goto err_frm; - } - - if (thd->variables.keep_files_on_create) - create_info->options|= HA_CREATE_KEEP_FILES; - - if (file->ha_create_partitioning_metadata(path, NULL, CHF_CREATE_FLAG)) - goto err_part; - - if (!no_ha_create_table) - { - if (ha_create_table(thd, path, db, table_name, create_info, frm)) - goto err_part; - } - - DBUG_RETURN(0); - -err_part: - file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG); -err_frm: - deletefrm(path); - DBUG_RETURN(1); -} /* rea_create_table */ - - /* Pack keyinfo and keynames to keybuff for save in form-file. */ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, - ulong data_offset) + ulong data_offset, uint e_unique_hash_extra_parts) { uint key_parts,length; uchar *pos, *keyname_pos; @@ -590,6 +574,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, } } + key_parts+= e_unique_hash_extra_parts; if (key_count > 127 || key_parts > 127) { keybuff[0]= (key_count & 0x7f) | 0x80; @@ -656,7 +641,7 @@ static bool pack_vcols(String *buf, List<Create_field> &create_fields, for (uint field_nr=0; (field= it++); field_nr++) { - if (field->vcol_info) + if (field->vcol_info && field->vcol_info->expr) if (pack_expression(buf, field->vcol_info, field_nr, field->vcol_info->stored_in_db ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL)) @@ -897,32 +882,12 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, while ((field=it++)) { uint recpos; - int2store(buff+3, field->length); /* The +1 is here becasue the col offset in .frm file have offset 1 */ recpos= field->offset+1 + (uint) data_offset; int3store(buff+5,recpos); - int2store(buff+8,field->pack_flag); - buff[10]= (uchar) field->unireg_check; buff[12]= (uchar) field->interval_id; - buff[13]= (uchar) field->real_field_type(); - if (field->real_field_type() == MYSQL_TYPE_GEOMETRY) - { - buff[11]= 0; - buff[14]= (uchar) field->geom_type; -#ifndef HAVE_SPATIAL - DBUG_ASSERT(0); // Should newer happen -#endif - } - else if (field->charset) - { - buff[11]= (uchar) (field->charset->number >> 8); - buff[14]= (uchar) field->charset->number; - } - else - { - buff[11]= buff[14]= 0; // Numerical - } - + buff[13]= (uchar) field->type_handler()->real_field_type(); + field->type_handler()->Column_definition_attributes_frm_pack(field, buff); int2store(buff+15, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); @@ -1009,13 +974,36 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, DBUG_RETURN(0); } + +static bool make_empty_rec_store_default(THD *thd, Field *regfield, + Virtual_column_info *default_value) +{ + if (default_value && !default_value->flags) + { + Item *expr= default_value->expr; + // may be already fixed if ALTER TABLE + if (expr->fix_fields_if_needed(thd, &expr)) + return true; + DBUG_ASSERT(expr == default_value->expr); // Should not change + if (regfield->make_empty_rec_store_default_value(thd, expr)) + { + my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str); + return true; + } + return false; + } + regfield->make_empty_rec_reset(thd); + return false; +} + + /* save an empty record on start of formfile */ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, List<Create_field> &create_fields, uint reclength, ulong data_offset) { - int error= 0; + int error= false; uint null_count; uchar *null_pos; TABLE table; @@ -1043,24 +1031,19 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values while ((field=it++)) { + Record_addr addr(buff + field->offset + data_offset, + null_pos + null_count / 8, null_count & 7); + Column_definition_attributes tmp(*field); + tmp.interval= field->save_interval ? + field->save_interval : field->interval; /* regfield don't have to be deleted as it's allocated on THD::mem_root */ - Field *regfield= make_field(&share, thd->mem_root, - buff+field->offset + data_offset, - (uint32)field->length, - null_pos + null_count / 8, - null_count & 7, - field->pack_flag, - 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->flags); + Field *regfield= tmp.make_field(&share, thd->mem_root, &addr, + field->type_handler(), + &field->field_name, + field->flags); if (!regfield) { - error= 1; + error= true; goto err; // End of memory } @@ -1077,36 +1060,10 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, !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->real_field_type() == MYSQL_TYPE_GEOMETRY)) - { - Item *expr= field->default_value->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)) - regfield->reset(); - - /* If not ok or warning of level 'note' */ - if (res != 0 && res != 3) - { - my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str); - error= 1; - delete regfield; //To avoid memory leak - goto err; - } - delete regfield; //To avoid memory leak - } - else if (regfield->real_type() == MYSQL_TYPE_ENUM && - (field->flags & NOT_NULL_FLAG)) - { - regfield->set_notnull(); - regfield->store((longlong) 1, TRUE); - } - else - regfield->reset(); + error= make_empty_rec_store_default(thd, regfield, field->default_value); + delete regfield; // Avoid memory leaks + if (error) + goto err; } DBUG_ASSERT(data_offset == ((null_count + 7) / 8)); |