diff --git a/sql/field.cc b/sql/field.cc index 5ce4ef89996..faa80caf70b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10529,21 +10529,32 @@ uint pack_length_to_packflag(uint type) } -Field *make_field(TABLE_SHARE *share, - MEM_ROOT *mem_root, - const Record_addr *rec, - uint32 field_length, - uint pack_flag, - const Type_handler *handler, - CHARSET_INFO *field_charset, - Field::geometry_type geom_type, uint srid, - Field::utype unireg_check, - TYPELIB *interval, - const LEX_CSTRING *field_name, - uint32 flags) +uint Column_definition_attributes::pack_flag_to_pack_length() const { + uint type= f_packtype(pack_flag); // 0..15 + DBUG_ASSERT(type < 16); + switch (type) { + case MYSQL_TYPE_TINY: return 1; + case MYSQL_TYPE_SHORT: return 2; + case MYSQL_TYPE_LONG: return 4; + case MYSQL_TYPE_LONGLONG: return 8; + case MYSQL_TYPE_INT24: return 3; + } + return 0; // This should not happen +} + + +Field *Column_definition_attributes::make_field(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const Record_addr *rec, + const Type_handler *handler, + const LEX_CSTRING *field_name, + uint32 flags) + const +{ + DBUG_ASSERT(length <= UINT_MAX32); DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s", - handler->name().ptr(), field_length, interval, + handler->name().ptr(), (uint) length, interval, FLAGSTR(pack_flag, FIELDFLAG_BINARY), FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), FLAGSTR(pack_flag, FIELDFLAG_NUMBER), @@ -10552,288 +10563,51 @@ Field *make_field(TABLE_SHARE *share, Record_addr addr(rec->ptr(), f_maybe_null(pack_flag) ? rec->null() : Bit_addr()); - - if (handler == &type_handler_row) - { - DBUG_ASSERT(field_length == 0); - DBUG_ASSERT(f_maybe_null(pack_flag)); - return new (mem_root) Field_row(addr.ptr(), field_name); - } - - if (f_is_alpha(pack_flag)) - { - if (!f_is_packed(pack_flag)) - { - enum_field_types field_type= handler->real_field_type(); - if (field_type == MYSQL_TYPE_STRING || - field_type == MYSQL_TYPE_DECIMAL || // 3.23 or 4.0 string - field_type == MYSQL_TYPE_VAR_STRING) - return new (mem_root) - Field_string(addr.ptr(), field_length, - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - field_charset); - if (field_type == MYSQL_TYPE_VARCHAR) - { - if (unireg_check == Field::TMYSQL_COMPRESSED) - return new (mem_root) - Field_varstring_compressed( - addr.ptr(), field_length, - HA_VARCHAR_PACKLENGTH(field_length), - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - share, field_charset, zlib_compression_method); - - return new (mem_root) - Field_varstring(addr.ptr(), field_length, - HA_VARCHAR_PACKLENGTH(field_length), - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - share, - field_charset); - } - return 0; // Error - } - - // MYSQL_TYPE_VAR_STRING is handled above - DBUG_ASSERT(f_packtype(pack_flag) != MYSQL_TYPE_VAR_STRING); - const Type_handler *tmp; - tmp= Type_handler::get_handler_by_real_type((enum_field_types) - f_packtype(pack_flag)); - uint pack_length= tmp->calc_pack_length(field_length); - -#ifdef HAVE_SPATIAL - if (f_is_geom(pack_flag)) - { - status_var_increment(current_thd->status_var.feature_gis); - return new (mem_root) - Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, share, - pack_length, geom_type, srid); - } -#endif - if (f_is_blob(pack_flag)) - { - if (unireg_check == Field::TMYSQL_COMPRESSED) - return new (mem_root) - Field_blob_compressed(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, share, - pack_length, field_charset, zlib_compression_method); - - return new (mem_root) - Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, share, - pack_length, field_charset); - } - if (interval) - { - if (f_is_enum(pack_flag)) - return new (mem_root) - Field_enum(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - pack_length, interval, field_charset); - else - return new (mem_root) - Field_set(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - pack_length, interval, field_charset); - } - } - - switch (handler->real_field_type()) { - case MYSQL_TYPE_DECIMAL: - return new (mem_root) - Field_decimal(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_decimals(pack_flag), - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_NEWDECIMAL: - return new (mem_root) - Field_new_decimal(addr.ptr(), field_length, - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_decimals(pack_flag), - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_FLOAT: - { - int decimals= f_decimals(pack_flag); - if (decimals == FLOATING_POINT_DECIMALS) - decimals= NOT_FIXED_DEC; - return new (mem_root) - Field_float(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - decimals, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag)== 0); - } - case MYSQL_TYPE_DOUBLE: - { - int decimals= f_decimals(pack_flag); - if (decimals == FLOATING_POINT_DECIMALS) - decimals= NOT_FIXED_DEC; - return new (mem_root) - Field_double(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - decimals, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag)== 0); - } - case MYSQL_TYPE_TINY: - return new (mem_root) - Field_tiny(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_SHORT: - return new (mem_root) - Field_short(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_INT24: - return new (mem_root) - Field_medium(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_LONG: - return new (mem_root) - Field_long(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_LONGLONG: - if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) - { - return new (mem_root) - Field_vers_trx_id(addr.ptr(), field_length, - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - } - else - { - return new (mem_root) - Field_longlong(addr.ptr(), field_length, - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - } - case MYSQL_TYPE_TIMESTAMP: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new_Field_timestamp(mem_root, addr.ptr(), - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, share, dec); - } - case MYSQL_TYPE_TIMESTAMP2: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new (mem_root) - Field_timestampf(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, share, dec); - } - case MYSQL_TYPE_YEAR: - return new (mem_root) - Field_year(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(), - unireg_check, field_name); - case MYSQL_TYPE_DATE: - return new (mem_root) - Field_date(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name); - case MYSQL_TYPE_NEWDATE: - return new (mem_root) - Field_newdate(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name); - case MYSQL_TYPE_TIME: - { - uint dec= field_length > MIN_TIME_WIDTH ? - field_length - MIN_TIME_WIDTH - 1: 0; - return new_Field_time(mem_root, addr.ptr(), - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, dec); - } - case MYSQL_TYPE_TIME2: - { - uint dec= field_length > MIN_TIME_WIDTH ? - field_length - MIN_TIME_WIDTH - 1: 0; - return new (mem_root) - Field_timef(addr.ptr(), addr.null_ptr(), addr.null_bit(), unireg_check, - field_name, dec); - } - case MYSQL_TYPE_DATETIME: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new_Field_datetime(mem_root, addr.ptr(), - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, dec); - } - case MYSQL_TYPE_DATETIME2: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new (mem_root) - Field_datetimef(addr.ptr(), addr.null_ptr(), addr.null_bit(), - unireg_check, field_name, dec); - } - case MYSQL_TYPE_NULL: - return new (mem_root) - Field_null(addr.ptr(), field_length, unireg_check, field_name, - field_charset); - case MYSQL_TYPE_BIT: - { - Bit_addr bit(rec->null()); - if (!f_bit_as_char(pack_flag) && f_maybe_null(pack_flag)) - bit.inc(); - return (f_bit_as_char(pack_flag) ? - new (mem_root) - Field_bit_as_char(addr.ptr(), field_length, - addr.null_ptr(), addr.null_bit(), - unireg_check, field_name) : - new (mem_root) - Field_bit(addr.ptr(), field_length, - addr.null_ptr(), addr.null_bit(), - bit.ptr(), bit.offs(), unireg_check, field_name)); - - } - default: // Impossible (Wrong version) - break; - } - return 0; + /* + Special code for the BIT-alike data types + who store data bits together with NULL-bits. + */ + Bit_addr bit(rec->null()); + if (f_maybe_null(pack_flag)) + bit.inc(); + return handler->make_table_field_from_def(share, mem_root, field_name, + addr, bit, this, flags); } + bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) const { return item->type() == Item::DATE_ITEM; } +Column_definition_attributes::Column_definition_attributes(const Field *field) + :length(field->field_length), + unireg_check(field->unireg_check), + interval(NULL), + charset(field->charset()), // May be NULL ptr + srid(0), + geom_type(Field::GEOM_GEOMETRY), + pack_flag(0) +{} + + /** Create a field suitable for create of table. */ Column_definition::Column_definition(THD *thd, Field *old_field, Field *orig_field) + :Column_definition_attributes(old_field) { on_update= NULL; field_name= old_field->field_name; - length= old_field->field_length; flags= old_field->flags; - unireg_check=old_field->unireg_check; pack_length=old_field->pack_length(); key_length= old_field->key_length(); set_handler(old_field->type_handler()); - charset= old_field->charset(); // May be NULL ptr comment= old_field->comment; decimals= old_field->decimals(); vcol_info= old_field->vcol_info; option_list= old_field->option_list; - pack_flag= 0; compression_method_ptr= 0; versioning= VERSIONING_NOT_SET; invisible= old_field->invisible; diff --git a/sql/field.h b/sql/field.h index be6befb6904..ab8d66a7b8d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4072,21 +4072,53 @@ public: extern const LEX_CSTRING null_clex_str; -Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, - const Record_addr *rec, - uint32 field_length, - uint pack_flag, const Type_handler *handler, - CHARSET_INFO *cs, - Field::geometry_type geom_type, uint srid, - Field::utype unireg_check, - TYPELIB *interval, const LEX_CSTRING *field_name, - uint32 flags); +class Column_definition_attributes +{ +public: + /* + At various stages in execution this can be length of field in bytes or + max number of characters. + */ + ulonglong length; + Field::utype unireg_check; + TYPELIB *interval; // Which interval to use + CHARSET_INFO *charset; + uint32 srid; + Field::geometry_type geom_type; + uint pack_flag; + Column_definition_attributes() + :length(0), + unireg_check(Field::NONE), + interval(NULL), + charset(&my_charset_bin), + srid(0), + geom_type(Field::GEOM_GEOMETRY), + pack_flag(0) + { } + Column_definition_attributes(const Field *field); + Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, + const Record_addr *rec, + const Type_handler *handler, + const LEX_CSTRING *field_name, + uint32 flags) const; + uint temporal_dec(uint intlen) const + { + return (uint) (length > intlen ? length - intlen - 1 : 0); + } + uint pack_flag_to_pack_length() const; + void frm_pack_basic(uchar *buff) const; + void frm_pack_charset(uchar *buff) const; + void frm_unpack_basic(const uchar *buff); + bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff); +}; + /* Create field class for CREATE TABLE */ class Column_definition: public Sql_alloc, - public Type_handler_hybrid_field_type + public Type_handler_hybrid_field_type, + public Column_definition_attributes { /** Create "interval" from "interval_list". @@ -4141,11 +4173,6 @@ public: WITHOUT_VERSIONING }; Item *on_update; // ON UPDATE NOW() - /* - At various stages in execution this can be length of field in bytes or - max number of characters. - */ - ulonglong length; field_visibility_t invisible; /* The value of `length' as set by parser: is the number of characters @@ -4153,15 +4180,9 @@ public: */ uint32 char_length; uint decimals, flags, pack_length, key_length; - Field::utype unireg_check; - TYPELIB *interval; // Which interval to use List interval_list; - CHARSET_INFO *charset; - uint32 srid; - Field::geometry_type geom_type; engine_option_value *option_list; - uint pack_flag; /* This is additinal data provided for any computed(virtual) field. @@ -4179,11 +4200,9 @@ public: :Type_handler_hybrid_field_type(&type_handler_null), compression_method_ptr(0), comment(null_clex_str), - on_update(NULL), length(0), invisible(VISIBLE), decimals(0), - flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE), - interval(0), charset(&my_charset_bin), - srid(0), geom_type(Field::GEOM_GEOMETRY), - option_list(NULL), pack_flag(0), + on_update(NULL), invisible(VISIBLE), decimals(0), + flags(0), pack_length(0), key_length(0), + option_list(NULL), vcol_info(0), default_value(0), check_constraint(0), versioning(VERSIONING_NOT_SET) { @@ -4316,10 +4335,9 @@ public: const Record_addr *addr, const LEX_CSTRING *field_name_arg) const { - return ::make_field(share, mem_root, addr, (uint32) length, - pack_flag, type_handler(), charset, - geom_type, srid, unireg_check, interval, - field_name_arg, flags); + return Column_definition_attributes::make_field(share, mem_root, addr, + type_handler(), + field_name_arg, flags); } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *field_name_arg) const @@ -4647,7 +4665,7 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name, #define FIELDFLAG_DEC_SHIFT 8 #define FIELDFLAG_MAX_DEC 63U -#define MTYP_TYPENR(type) (type & 127U) /* Remove bits from type */ +#define MTYP_TYPENR(type) ((type) & 127U) // Remove bits from type #define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL) #define f_is_num(x) ((x) & FIELDFLAG_NUMBER) diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 95dc931e435..154b63a9ce6 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -5780,3 +5780,487 @@ void Type_handler_geometry::Item_param_set_param_func(Item_param *param, #endif /***************************************************************************/ + +Field *Type_handler_row:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + DBUG_ASSERT(attr->length == 0); + DBUG_ASSERT(f_maybe_null(attr->pack_flag)); + return new (mem_root) Field_row(rec.ptr(), name); +} + + +Field *Type_handler_olddecimal:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_decimal(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_decimals(attr->pack_flag), + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_newdecimal:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_new_decimal(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_decimals(attr->pack_flag), + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_float:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + int decimals= f_decimals(attr->pack_flag); + if (decimals == FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; + return new (mem_root) + Field_float(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, decimals, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag)== 0); +} + + +Field *Type_handler_double:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + int decimals= f_decimals(attr->pack_flag); + if (decimals == FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; + return new (mem_root) + Field_double(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, decimals, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag)== 0); +} + + +Field *Type_handler_tiny:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_tiny(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_short:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_short(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_int24:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_medium(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_long:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_long(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_longlong:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) + return new (mem_root) + Field_vers_trx_id(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); + return new (mem_root) + Field_longlong(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_timestamp:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new_Field_timestamp(mem_root, + rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_timestamp2:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_timestampf(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, + name, share, attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_year:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_year(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name); +} + + +Field *Type_handler_date:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_date(rec.ptr(),rec.null_ptr(),rec.null_bit(), + attr->unireg_check, name); +} + + +Field *Type_handler_newdate:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_newdate(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name); +} + + +Field *Type_handler_time:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new_Field_time(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MIN_TIME_WIDTH)); +} + + +Field *Type_handler_time2:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_timef(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MIN_TIME_WIDTH)); +} + + +Field *Type_handler_datetime:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new_Field_datetime(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_datetime2:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_datetimef(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_null:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_null(rec.ptr(), (uint32) attr->length, attr->unireg_check, + name, attr->charset); +} + + +Field *Type_handler_bit:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return f_bit_as_char(attr->pack_flag) ? + new (mem_root) Field_bit_as_char(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name) : + new (mem_root) Field_bit(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + bit.ptr(), bit.offs(), attr->unireg_check, name); +} + + +#ifdef HAVE_SPATIAL +Field *Type_handler_geometry:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + status_var_increment(current_thd->status_var.feature_gis); + return new (mem_root) + Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), attr->geom_type, attr->srid); +} +#endif + + +Field *Type_handler_string:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_string(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, attr->charset); +} + + +Field *Type_handler_varchar:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + if (attr->unireg_check == Field::TMYSQL_COMPRESSED) + return new (mem_root) + Field_varstring_compressed(rec.ptr(), (uint32) attr->length, + HA_VARCHAR_PACKLENGTH((uint32) attr->length), + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, attr->charset, + zlib_compression_method); + return new (mem_root) + Field_varstring(rec.ptr(), (uint32) attr->length, + HA_VARCHAR_PACKLENGTH((uint32) attr->length), + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, attr->charset); +} + + +Field *Type_handler_blob_common:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + if (attr->unireg_check == Field::TMYSQL_COMPRESSED) + return new (mem_root) + Field_blob_compressed(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), attr->charset, + zlib_compression_method); + return new (mem_root) + Field_blob(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), attr->charset); +} + + +Field *Type_handler_enum:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_enum(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, attr->pack_flag_to_pack_length(), + attr->interval, attr->charset); +} + + +Field *Type_handler_set:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_set(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, attr->pack_flag_to_pack_length(), + attr->interval, attr->charset); +} + + +/***************************************************************************/ + +void Type_handler:: + Column_definition_attributes_frm_pack(const Column_definition_attributes *def, + uchar *buff) const +{ + def->frm_pack_basic(buff); + def->frm_pack_charset(buff); +} + + +#ifdef HAVE_SPATIAL +void Type_handler_geometry:: + Column_definition_attributes_frm_pack(const Column_definition_attributes *def, + uchar *buff) const +{ + def->frm_pack_basic(buff); + buff[11]= 0; + buff[14]= (uchar) def->geom_type; +} +#endif + + +/***************************************************************************/ + +bool Type_handler:: + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) + const +{ + attr->frm_unpack_basic(buffer); + return attr->frm_unpack_charset(share, buffer); +} + + +#ifdef HAVE_SPATIAL +bool Type_handler_geometry:: + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) + const +{ + uint gis_opt_read, gis_length, gis_decimals; + Field_geom::storage_type st_type; + attr->frm_unpack_basic(buffer); + // charset and geometry_type share the same byte in frm + attr->geom_type= (Field::geometry_type) buffer[14]; + gis_opt_read= gis_field_options_read(gis_options->str, + gis_options->length, + &st_type, &gis_length, + &gis_decimals, &attr->srid); + gis_options->str+= gis_opt_read; + gis_options->length-= gis_opt_read; + return false; +} +#endif + +/***************************************************************************/ diff --git a/sql/sql_type.h b/sql/sql_type.h index b02ea4b2824..dbd50dd77b5 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -28,6 +28,7 @@ class Field; class Column_definition; +class Column_definition_attributes; class Item; class Item_param; class Item_cache; @@ -1179,6 +1180,23 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + virtual Field * + make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const= 0; + virtual void + Column_definition_attributes_frm_pack(const Column_definition_attributes *at, + uchar *buff) const; + virtual bool + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) const; + virtual void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const= 0; @@ -1465,6 +1483,13 @@ public: DBUG_ASSERT(0); return NULL; } + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const @@ -2189,6 +2214,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2218,6 +2250,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2250,6 +2289,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2283,6 +2329,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2323,6 +2376,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2350,6 +2410,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; }; @@ -2392,6 +2459,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2421,6 +2495,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2453,6 +2534,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2536,6 +2624,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2555,6 +2650,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2617,6 +2719,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2636,6 +2745,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2697,6 +2813,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2716,6 +2839,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2779,6 +2909,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2800,6 +2937,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2824,6 +2968,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2855,6 +3006,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2893,6 +3051,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2929,6 +3094,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2987,6 +3159,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; bool adjust_spparam_type(Spvar_definition *def, Item *from) const; }; @@ -3030,6 +3209,13 @@ public: Item **items, uint nitems) const; void Item_param_setup_conversion(THD *thd, Item_param *) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3131,6 +3317,14 @@ public: const st_value *value) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + void + Column_definition_attributes_frm_pack(const Column_definition_attributes *at, + uchar *buff) const; + bool + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) const; bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, @@ -3145,6 +3339,14 @@ public: const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; + bool can_return_int() const { return false; } bool can_return_decimal() const { return false; } bool can_return_real() const { return false; } @@ -3227,6 +3429,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3248,6 +3457,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; diff --git a/sql/table.cc b/sql/table.cc index 37f759a5325..93684cb5221 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -915,6 +915,54 @@ static uint upgrade_collation(ulong mysql_version, uint cs_number) } +void Column_definition_attributes::frm_pack_basic(uchar *buff) const +{ + int2store(buff + 3, length); + int2store(buff + 8, pack_flag); + buff[10]= (uchar) unireg_check; +} + + +void Column_definition_attributes::frm_unpack_basic(const uchar *buff) +{ + length= uint2korr(buff + 3); + pack_flag= uint2korr(buff + 8); + unireg_check= (Field::utype) MTYP_TYPENR((uint) buff[10]); +} + + +void Column_definition_attributes::frm_pack_charset(uchar *buff) const +{ + buff[11]= (uchar) (charset->number >> 8); + buff[14]= (uchar) charset->number; +} + + +bool Column_definition_attributes::frm_unpack_charset(TABLE_SHARE *share, + const uchar *buff) +{ + uint cs_org= buff[14] + (((uint) buff[11]) << 8); + uint cs_new= upgrade_collation(share->mysql_version, cs_org); + if (cs_org != cs_new) + share->incompatible_version|= HA_CREATE_USED_CHARSET; + if (cs_new && !(charset= get_charset(cs_new, MYF(0)))) + { + const char *csname= get_charset_name((uint) cs_new); + char tmp[10]; + if (!csname || csname[0] =='?') + { + my_snprintf(tmp, sizeof(tmp), "#%u", cs_new); + csname= tmp; + } + my_printf_error(ER_UNKNOWN_COLLATION, + "Unknown collation '%s' in table '%-.64s' definition", + MYF(0), csname, share->table_name.str); + return true; + } + return false; +} + + /* In MySQL 5.7 the null bits for not stored virtual fields are last. Calculate the position for these bits @@ -1145,6 +1193,38 @@ end: DBUG_RETURN(res); } + +static const Type_handler *old_frm_type_handler(uint pack_flag, + uint interval_nr) +{ + enum_field_types field_type= (enum_field_types) f_packtype(pack_flag); + DBUG_ASSERT(field_type < 16); + + if (!f_is_alpha(pack_flag)) + return Type_handler::get_handler_by_real_type(field_type); + + if (!f_is_packed(pack_flag)) + { + if (field_type == MYSQL_TYPE_DECIMAL) // 3.23 or 4.0 string + return &type_handler_string; + if (field_type == MYSQL_TYPE_VARCHAR) // Since mysql-5.0 + return &type_handler_varchar; + return NULL; // Error (bad frm?) + } + + if (f_is_blob(pack_flag)) + return &type_handler_blob; // QQ: exact type?? + + if (interval_nr) + { + if (f_is_enum(pack_flag)) + return &type_handler_enum; + return &type_handler_set; + } + return Type_handler::get_handler_by_real_type(field_type); +} + + /** Read data from a binary .frm file image into a TABLE_SHARE @@ -1191,8 +1271,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, size_t UNINIT_VAR(options_len); uchar *vcol_screen_pos; const uchar *options= 0; - size_t UNINIT_VAR(gis_options_len); - const uchar *gis_options= 0; + LEX_CUSTRING gis_options= { NULL, 0}; KEY first_keyinfo; uint len; uint ext_key_parts= 0; @@ -1288,10 +1367,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, case EXTRA2_GIS: #ifdef HAVE_SPATIAL { - if (gis_options) + if (gis_options.str) goto err; - gis_options= extra2; - gis_options_len= length; + gis_options.str= extra2; + gis_options.length= length; } #endif /*HAVE_SPATIAL*/ break; @@ -1781,82 +1860,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++) { - uint pack_flag, interval_nr, unireg_type, recpos, field_length; - uint vcol_info_length=0; - uint vcol_expr_length=0; - enum_field_types field_type; - CHARSET_INFO *charset=NULL; - Field::geometry_type geom_type= Field::GEOM_GEOMETRY; + uint interval_nr= 0, recpos; LEX_CSTRING comment; LEX_CSTRING name; Virtual_column_info *vcol_info= 0; - uint gis_length, gis_decimals, srid= 0; - Field::utype unireg_check; const Type_handler *handler; uint32 flags= 0; + Column_definition_attributes attr; if (new_frm_ver >= 3) { /* new frm file in 4.1 */ - field_length= uint2korr(strpos+3); recpos= uint3korr(strpos+5); - pack_flag= uint2korr(strpos+8); - unireg_type= (uint) strpos[10]; - interval_nr= (uint) strpos[12]; uint comment_length=uint2korr(strpos+15); - field_type=(enum_field_types) (uint) strpos[13]; - - /* charset and geometry_type share the same byte in frm */ - if (field_type == MYSQL_TYPE_GEOMETRY) - { -#ifdef HAVE_SPATIAL - uint gis_opt_read; - Field_geom::storage_type st_type; - geom_type= (Field::geometry_type) strpos[14]; - charset= &my_charset_bin; - gis_opt_read= gis_field_options_read(gis_options, gis_options_len, - &st_type, &gis_length, &gis_decimals, &srid); - gis_options+= gis_opt_read; - gis_options_len-= gis_opt_read; -#else - goto err; -#endif - } - else - { - uint cs_org= strpos[14] + (((uint) strpos[11]) << 8); - uint cs_new= upgrade_collation(share->mysql_version, cs_org); - if (cs_org != cs_new) - share->incompatible_version|= HA_CREATE_USED_CHARSET; - if (!cs_new) - charset= &my_charset_bin; - else if (!(charset= get_charset(cs_new, MYF(0)))) - { - const char *csname= get_charset_name((uint) cs_new); - char tmp[10]; - if (!csname || csname[0] =='?') - { - my_snprintf(tmp, sizeof(tmp), "#%u", cs_new); - csname= tmp; - } - my_printf_error(ER_UNKNOWN_COLLATION, - "Unknown collation '%s' in table '%-.64s' definition", - MYF(0), csname, share->table_name.str); - goto err; - } - } - - if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL) - { - DBUG_ASSERT(interval_nr); // Expect non-null expression - /* - MariaDB version 10.0 version. - The interval_id byte in the .frm file stores the length of the - expression statement for a virtual column. - */ - vcol_info_length= interval_nr; - interval_nr= 0; - } if (!comment_length) { @@ -1870,32 +1886,20 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, comment_pos+= comment_length; } - if (unireg_type & MYSQL57_GENERATED_FIELD) + if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL) { - unireg_type&= MYSQL57_GENERATED_FIELD; - /* - MySQL 5.7 generated fields - - byte 1 = 1 - byte 2,3 = expr length - byte 4 = stored_in_db - byte 5.. = expr + MariaDB version 10.0 version. + The interval_id byte in the .frm file stores the length of the + expression statement for a virtual column. */ - if ((uint)(vcol_screen_pos)[0] != 1) - goto err; - vcol_info= new (&share->mem_root) Virtual_column_info(); - vcol_info_length= uint2korr(vcol_screen_pos + 1); - DBUG_ASSERT(vcol_info_length); - vcol_info->stored_in_db= vcol_screen_pos[3]; - vcol_info->utf8= 0; - vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;; - share->virtual_fields++; - vcol_info_length= 0; - } + uint vcol_info_length= (uint) strpos[12]; - if (vcol_info_length) - { + DBUG_ASSERT(vcol_info_length); // Expect non-null expression + + attr.frm_unpack_basic(strpos); + if (attr.frm_unpack_charset(share, strpos)) + goto err; /* Old virtual field information before 10.2 @@ -1909,7 +1913,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, vcol_info= new (&share->mem_root) Virtual_column_info(); bool opt_interval_id= (uint)vcol_screen_pos[0] == 2; - field_type= (enum_field_types) (uchar) vcol_screen_pos[1]; + enum_field_types ftype= (enum_field_types) (uchar) vcol_screen_pos[1]; + if (!(handler= Type_handler::get_handler_by_real_type(ftype))) + goto err; if (opt_interval_id) interval_nr= (uint)vcol_screen_pos[3]; else if ((uint)vcol_screen_pos[0] != 1) @@ -1917,26 +1923,63 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, bool stored= vcol_screen_pos[2] & 1; vcol_info->stored_in_db= stored; vcol_info->set_vcol_type(stored ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL); - vcol_expr_length= vcol_info_length - - (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id)); + uint vcol_expr_length= vcol_info_length - + (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id)); vcol_info->utf8= 0; // before 10.2.1 the charset was unknown int2store(vcol_screen_pos+1, vcol_expr_length); // for parse_vcol_defs() vcol_screen_pos+= vcol_info_length; share->virtual_fields++; } + else + { + interval_nr= (uint) strpos[12]; + enum_field_types field_type= (enum_field_types) strpos[13]; + if (!(handler= Type_handler::get_handler_by_real_type(field_type))) + goto err; // Not supported field type + if (handler->Column_definition_attributes_frm_unpack(&attr, share, + strpos, + &gis_options)) + goto err; + } + + if (((uint) strpos[10]) & MYSQL57_GENERATED_FIELD) + { + attr.unireg_check= Field::NONE; + + /* + MySQL 5.7 generated fields + + byte 1 = 1 + byte 2,3 = expr length + byte 4 = stored_in_db + byte 5.. = expr + */ + if ((uint)(vcol_screen_pos)[0] != 1) + goto err; + vcol_info= new (&share->mem_root) Virtual_column_info(); + uint vcol_info_length= uint2korr(vcol_screen_pos + 1); + DBUG_ASSERT(vcol_info_length); + vcol_info->stored_in_db= vcol_screen_pos[3]; + vcol_info->utf8= 0; + vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;; + share->virtual_fields++; + } } else { - field_length= (uint) strpos[3]; + attr.length= (uint) strpos[3]; recpos= uint2korr(strpos+4), - pack_flag= uint2korr(strpos+6); - pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files - unireg_type= (uint) strpos[8]; + attr.pack_flag= uint2korr(strpos+6); + attr.pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files + attr.unireg_check= (Field::utype) MTYP_TYPENR((uint) strpos[8]); interval_nr= (uint) strpos[10]; /* old frm file */ - field_type= (enum_field_types) f_packtype(pack_flag); - if (f_is_binary(pack_flag)) + enum_field_types ftype= (enum_field_types) f_packtype(attr.pack_flag); + if (!(handler= Type_handler::get_handler_by_real_type(ftype))) + goto err; // Not supported field type + + if (f_is_binary(attr.pack_flag)) { /* Try to choose the best 4.1 type: @@ -1944,26 +1987,26 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, try to find a binary collation for character set. - for other types (e.g. BLOB) just use my_charset_bin. */ - if (!f_is_blob(pack_flag)) + if (!f_is_blob(attr.pack_flag)) { // 3.23 or 4.0 string - if (!(charset= get_charset_by_csname(share->table_charset->csname, - MY_CS_BINSORT, MYF(0)))) - charset= &my_charset_bin; + if (!(attr.charset= get_charset_by_csname(share->table_charset->csname, + MY_CS_BINSORT, MYF(0)))) + attr.charset= &my_charset_bin; } - else - charset= &my_charset_bin; } else - charset= share->table_charset; + attr.charset= share->table_charset; bzero((char*) &comment, sizeof(comment)); + if ((!(handler= old_frm_type_handler(attr.pack_flag, interval_nr)))) + goto err; // Not supported field type } /* Remove >32 decimals from old files */ if (share->mysql_version < 100200) - pack_flag&= ~FIELDFLAG_LONG_DECIMAL; + attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL; - if (interval_nr && charset->mbminlen > 1) + if (interval_nr && attr.charset->mbminlen > 1) { /* Unescape UCS2 intervals from HEX notation */ TYPELIB *interval= share->intervals + interval_nr - 1; @@ -1971,17 +2014,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } #ifndef TO_BE_DELETED_ON_PRODUCTION - if (field_type == MYSQL_TYPE_NEWDECIMAL && !share->mysql_version) + if (handler->real_field_type() == MYSQL_TYPE_NEWDECIMAL && + !share->mysql_version) { /* Fix pack length of old decimal values from 5.0.3 -> 5.0.4 The difference is that in the old version we stored precision in the .frm table while we now store the display_length */ - uint decimals= f_decimals(pack_flag); - field_length= my_decimal_precision_to_length(field_length, - decimals, - f_is_dec(pack_flag) == 0); + uint decimals= f_decimals(attr.pack_flag); + attr.length= + my_decimal_precision_to_length((uint) attr.length, decimals, + f_is_dec(attr.pack_flag) == 0); sql_print_error("Found incompatible DECIMAL field '%s' in %s; " "Please do \"ALTER TABLE '%s' FORCE\" to fix it!", share->fieldnames.type_names[i], share->table_name.str, @@ -2012,7 +2056,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (flags & VERS_SYSTEM_FIELD) { - switch (field_type) + switch (handler->real_field_type()) { case MYSQL_TYPE_TIMESTAMP2: case MYSQL_TYPE_DATETIME2: @@ -2034,23 +2078,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } /* Convert pre-10.2.2 timestamps to use Field::default_value */ - unireg_check= (Field::utype) MTYP_TYPENR(unireg_type); name.str= fieldnames.type_names[i]; name.length= strlen(name.str); - if (!(handler= Type_handler::get_handler_by_real_type(field_type))) - goto err; // Not supported field type + attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL; Record_addr addr(record + recpos, null_pos, null_bit_pos); *field_ptr= reg_field= - make_field(share, &share->mem_root, &addr, - (uint32) field_length, pack_flag, handler, charset, - geom_type, srid, unireg_check, - (interval_nr ? share->intervals + interval_nr - 1 : NULL), - &name, flags); + attr.make_field(share, &share->mem_root, &addr, handler, &name, flags); if (!reg_field) // Not supported field type goto err; - if (unireg_check == Field::TIMESTAMP_DNUN_FIELD || - unireg_check == Field::TIMESTAMP_DN_FIELD) + if (attr.unireg_check == Field::TIMESTAMP_DNUN_FIELD || + attr.unireg_check == Field::TIMESTAMP_DN_FIELD) { reg_field->default_value= new (&share->mem_root) Virtual_column_info(); reg_field->default_value->set_vcol_type(VCOL_DEFAULT); @@ -2074,10 +2112,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, status_var_increment(thd->status_var.feature_invisible_columns); if (!reg_field->invisible) share->visible_fields++; - if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag)) + if (handler->real_field_type() == MYSQL_TYPE_BIT && + !f_bit_as_char(attr.pack_flag)) { null_bits_are_used= 1; - if ((null_bit_pos+= field_length & 7) > 7) + if ((null_bit_pos+= (uint) (attr.length & 7)) > 7) { null_pos++; null_bit_pos-= 8; @@ -2100,7 +2139,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } } - if (f_no_default(pack_flag)) + if (f_no_default(attr.pack_flag)) reg_field->flags|= NO_DEFAULT_VALUE_FLAG; if (reg_field->unireg_check == Field::NEXT_NUMBER) diff --git a/sql/unireg.cc b/sql/unireg.cc index dee856ae01f..26f02c8983a 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -897,32 +897,12 @@ static bool pack_fields(uchar **buff_arg, List &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); @@ -1045,18 +1025,14 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, { 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, &addr, - (uint32) field->length, - 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;