diff options
-rw-r--r-- | sql/field.cc | 64 | ||||
-rw-r--r-- | sql/field.h | 17 | ||||
-rw-r--r-- | sql/sql_type.cc | 64 | ||||
-rw-r--r-- | sql/sql_type.h | 31 |
4 files changed, 115 insertions, 61 deletions
diff --git a/sql/field.cc b/sql/field.cc index f92ffeaf6ee..d58ef8f03f4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10653,7 +10653,7 @@ bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) Column_definition_attributes::Column_definition_attributes(const Field *field) - :length(field->field_length), + :length(field->character_octet_length() / field->charset()->mbmaxlen), unireg_check(field->unireg_check), interval(NULL), charset(field->charset()), // May be NULL ptr @@ -10682,6 +10682,8 @@ Column_definition::Column_definition(THD *thd, Field *old_field, compression_method_ptr= 0; versioning= VERSIONING_NOT_SET; invisible= old_field->invisible; + interval_list.empty(); // prepare_interval_field() needs this + char_length= (uint) length; if (orig_field) { @@ -10699,61 +10701,7 @@ Column_definition::Column_definition(THD *thd, Field *old_field, check_constraint= 0; } - switch (real_field_type()) { - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - length/= charset->mbmaxlen; - key_length/= charset->mbmaxlen; - break; - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_VAR_STRING: - /* This is corrected in create_length_to_internal_length */ - length= (length+charset->mbmaxlen-1) / charset->mbmaxlen - - MY_TEST(old_field->compression_method()); - break; -#ifdef HAVE_SPATIAL - case MYSQL_TYPE_GEOMETRY: - geom_type= ((Field_geom*)old_field)->geom_type; - srid= ((Field_geom*)old_field)->srid; - break; -#endif - case MYSQL_TYPE_YEAR: - if (length != 4) - { - char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1]; - my_snprintf(buff, sizeof(buff), "YEAR(%llu)", length); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_WARN_DEPRECATED_SYNTAX, - ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), - buff, "YEAR(4)"); - } - break; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - /* - Floating points are stored with FLOATING_POINT_DECIMALS but internally - in MariaDB used with NOT_FIXED_DEC, which is >= FLOATING_POINT_DECIMALS. - */ - if (decimals >= FLOATING_POINT_DECIMALS) - decimals= NOT_FIXED_DEC; - break; - default: - break; - } - - if (flags & (ENUM_FLAG | SET_FLAG)) - interval= ((Field_enum*) old_field)->typelib; - else - interval=0; - - interval_list.empty(); // prepare_interval_field() needs this - - char_length= (uint)length; + type_handler()->Column_definition_reuse_fix_attributes(thd, this, old_field); type_handler()->Column_definition_implicit_upgrade(this); @@ -10837,11 +10785,11 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, uint32 Field_blob::char_length() const { - return Field_blob::octet_length(); + return Field_blob::character_octet_length(); } -uint32 Field_blob::octet_length() const +uint32 Field_blob::character_octet_length() const { switch (packlength) { diff --git a/sql/field.h b/sql/field.h index 597480d8719..c821c921962 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1484,12 +1484,21 @@ public: /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, int *err); + /* + Maximum number of bytes in character representation. + - For string types it is equal to the field capacity, in bytes. + - For non-string types it represents the longest possible string length + after conversion to string. + */ + virtual uint32 character_octet_length() const + { + return field_length; + } /* The max. number of characters */ virtual uint32 char_length() const { return field_length / charset()->mbmaxlen; } - virtual geometry_type get_geometry_type() { /* shouldn't get here. */ @@ -1812,6 +1821,7 @@ public: enum Derivation derivation(void) const { return field_derivation; } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_display_length() const { return field_length; } + uint32 character_octet_length() const { return field_length; } uint32 char_length() const { return field_length / field_charset->mbmaxlen; } Information_schema_character_attributes information_schema_character_attributes() const @@ -3571,6 +3581,7 @@ private: str.append(STRING_WITH_LEN(" /*!100301 COMPRESSED*/")); } uint32 max_display_length() const { return field_length - 1; } + uint32 character_octet_length() const { return field_length - 1; } uint32 char_length() const { return (field_length - 1) / field_charset->mbmaxlen; @@ -3703,7 +3714,7 @@ public: Information_schema_character_attributes information_schema_character_attributes() const { - uint32 octets= Field_blob::octet_length(); + uint32 octets= Field_blob::character_octet_length(); uint32 chars= octets / field_charset->mbminlen; return Information_schema_character_attributes(octets, chars); } @@ -3869,7 +3880,7 @@ public: { return charset() == &my_charset_bin ? FALSE : TRUE; } uint32 max_display_length() const; uint32 char_length() const; - uint32 octet_length() const; + uint32 character_octet_length() const; uint is_equal(Create_field *new_field); friend void TABLE::remember_blob_values(String *blob_storage); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 70d4a6a6fd5..924f077a76c 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1642,6 +1642,70 @@ bool Type_handler_bit:: /*************************************************************************/ +void Type_handler_blob_common:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + DBUG_ASSERT(def->key_length == 0); +} + + +void Type_handler_typelib:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + DBUG_ASSERT(def->flags & (ENUM_FLAG | SET_FLAG)); + def->interval= field->get_typelib(); +} + + +#ifdef HAVE_SPATIAL +void Type_handler_geometry:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + def->geom_type= ((Field_geom*) field)->geom_type; + def->srid= ((Field_geom*) field)->srid; +} +#endif + + +void Type_handler_year:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + if (def->length != 4) + { + char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1]; + my_snprintf(buff, sizeof(buff), "YEAR(%llu)", def->length); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_WARN_DEPRECATED_SYNTAX, + ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), + buff, "YEAR(4)"); + } +} + + +void Type_handler_real_result:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + /* + Floating points are stored with FLOATING_POINT_DECIMALS but internally + in MariaDB used with NOT_FIXED_DEC, which is >= FLOATING_POINT_DECIMALS. + */ + if (def->decimals >= FLOATING_POINT_DECIMALS) + def->decimals= NOT_FIXED_DEC; +} + + +/*************************************************************************/ + bool Type_handler:: Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, diff --git a/sql/sql_type.h b/sql/sql_type.h index d4b93ec9563..f6f03618a89 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -1275,7 +1275,17 @@ public: // Automatic upgrade, e.g. for ALTER TABLE t1 FORCE virtual void Column_definition_implicit_upgrade(Column_definition *c) const { } + // Fix attributes after the parser virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0; + /* + Fix attributes from an existing field. Used for: + - ALTER TABLE (for columns that do not change) + - DECLARE var TYPE OF t1.col1; (anchored SP variables) + */ + virtual void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const + { } virtual bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -1630,6 +1640,12 @@ public: { return false; } + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const + { + DBUG_ASSERT(0); + } bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -1934,6 +1950,9 @@ public: Item_result cmp_type() const { return REAL_RESULT; } virtual ~Type_handler_real_result() {} const Type_handler *type_handler_for_comparison() const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; @@ -2766,6 +2785,9 @@ public: Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; bool Column_definition_fix_attributes(Column_definition *c) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const @@ -3605,6 +3627,9 @@ public: } bool is_param_long_data_type() const { return true; } bool Column_definition_fix_attributes(Column_definition *c) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const; @@ -3732,6 +3757,9 @@ public: const uchar *buffer, LEX_CUSTRING *gis_options) const; bool Column_definition_fix_attributes(Column_definition *c) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -3802,6 +3830,9 @@ public: Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, |