From 5b034f1cf86b91a463878ce7e63018aa5e4ab072 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 17 May 2017 18:07:20 +0400 Subject: [PATCH] MDEV-12833 Split Column_definition::create_length_to_internal_length() to virtual methods in Type_handler --- sql/field.cc | 82 +++++++++++++++------------------------------ sql/field.h | 11 +++++- sql/sql_table.cc | 32 +++--------------- sql/sql_type.cc | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ sql/sql_type.h | 57 +++++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 84 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 577b09e948d..6320121d1c3 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9805,61 +9805,6 @@ void Column_definition::create_length_to_internal_length_newdecimal() } -/** - Convert create_field::length from number of characters to number of bytes. -*/ - -void Column_definition::create_length_to_internal_length(void) -{ - switch (real_field_type()) { - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VARCHAR: - create_length_to_internal_length_string(); - break; - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - create_length_to_internal_length_typelib(); - break; - case MYSQL_TYPE_BIT: - create_length_to_internal_length_bit(); - break; - case MYSQL_TYPE_NEWDECIMAL: - create_length_to_internal_length_newdecimal(); - break; - - case MYSQL_TYPE_NULL: - create_length_to_internal_length_null(); - break; - - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_YEAR: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_TIME2: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_DATETIME2: - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_TIMESTAMP2: - create_length_to_internal_length_simple(); - break; - } -} - - bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name, enum_vcol_info_type type) @@ -10496,6 +10441,33 @@ Column_definition::Column_definition(THD *thd, Field *old_field, } +/** + The common part for data type redefinition: + CREATE TABLE t1 (a INT) AS SELECT a FROM t2; + See Type_handler::Column_definition_redefine_stage1() + for data type specific code. +*/ +void +Column_definition::redefine_stage1_common(const Column_definition *dup_field, + const handler *file, + const Schema_specification_st *schema) +{ + set_handler(dup_field->type_handler()); + default_value= dup_field->default_value; + charset= dup_field->charset ? dup_field->charset : + schema->default_table_charset; + length= dup_field->char_length; + pack_length= dup_field->pack_length; + key_length= dup_field->key_length; + decimals= dup_field->decimals; + unireg_check= dup_field->unireg_check; + flags= dup_field->flags; + interval= dup_field->interval; + vcol_info= dup_field->vcol_info; +} + + + /** maximum possible character length for blob. diff --git a/sql/field.h b/sql/field.h index 10363fd855b..bfdb06984af 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3887,7 +3887,6 @@ public: } Column_definition(THD *thd, Field *field, Field *orig_field); void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs); - void create_length_to_internal_length(void); void create_length_to_internal_length_null() { DBUG_ASSERT(length == 0); @@ -3955,6 +3954,16 @@ public: bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root, handler *file, ulonglong table_flags); + void redefine_stage1_common(const Column_definition *dup_field, + const handler *file, + const Schema_specification_st *schema); + bool redefine_stage1(const Column_definition *dup_field, const handler *file, + const Schema_specification_st *schema) + { + const Type_handler *handler= dup_field->type_handler(); + return handler->Column_definition_redefine_stage1(this, dup_field, + file, schema); + } bool prepare_stage2(handler *handler, ulonglong table_flags); bool prepare_stage2_blob(handler *handler, ulonglong table_flags, uint field_flags); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e202552ac8a..a84cc5bbbf9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3355,30 +3355,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, file->ha_table_flags() & HA_CAN_BIT_FIELD) total_uneven_bit_length-= sql_field->length & 7; - sql_field->default_value= dup_field->default_value; - sql_field->set_handler(dup_field->type_handler()); - - /* - If we are replacing a field with a BIT field, we need - to initialize pack_flag. Note that we do not need to - increment total_uneven_bit_length here as this dup_field - has already been processed. - */ - if (sql_field->real_field_type() == MYSQL_TYPE_BIT) - { - sql_field->pack_flag= FIELDFLAG_NUMBER; - if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD)) - sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR; - } - - sql_field->charset= (dup_field->charset ? - dup_field->charset : - create_info->default_table_charset); - sql_field->length= dup_field->char_length; - sql_field->pack_length= dup_field->pack_length; - sql_field->key_length= dup_field->key_length; - sql_field->decimals= dup_field->decimals; - sql_field->unireg_check= dup_field->unireg_check; /* We're making one field from two, the result field will have dup_field->flags as flags. If we've incremented null_fields @@ -3386,10 +3362,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, */ if (!(sql_field->flags & NOT_NULL_FLAG)) null_fields--; - sql_field->flags= dup_field->flags; - sql_field->create_length_to_internal_length(); - sql_field->interval= dup_field->interval; - sql_field->vcol_info= dup_field->vcol_info; + + if (sql_field->redefine_stage1(dup_field, file, create_info)) + DBUG_RETURN(true); + it2.remove(); // Remove first (create) definition select_field_pos--; break; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 1dd7d6ce391..5477cdb87b7 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1634,6 +1634,93 @@ bool Type_handler_geometry:: #endif +/*************************************************************************/ + +bool Type_handler:: + Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const +{ + def->redefine_stage1_common(dup, file, schema); + def->create_length_to_internal_length_simple(); + return false; +} + + +bool Type_handler_null:: + Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const +{ + def->redefine_stage1_common(dup, file, schema); + def->create_length_to_internal_length_null(); + return false; +} + + +bool Type_handler_newdecimal:: + Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const +{ + def->redefine_stage1_common(dup, file, schema); + def->create_length_to_internal_length_newdecimal(); + return false; +} + + +bool Type_handler_string_result:: + Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const +{ + def->redefine_stage1_common(dup, file, schema); + def->create_length_to_internal_length_string(); + return false; +} + + +bool Type_handler_typelib:: + Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const +{ + def->redefine_stage1_common(dup, file, schema); + def->create_length_to_internal_length_typelib(); + return false; +} + + +bool Type_handler_bit:: + Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const +{ + def->redefine_stage1_common(dup, file, schema); + /* + If we are replacing a field with a BIT field, we need + to initialize pack_flag. + */ + def->pack_flag= FIELDFLAG_NUMBER; + if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD)) + def->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR; + def->create_length_to_internal_length_bit(); + return false; +} + + /*************************************************************************/ bool Type_handler:: diff --git a/sql/sql_type.h b/sql/sql_type.h index 0f035d0ebd5..9c04593c7f4 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -68,6 +68,7 @@ class Arg_comparator; struct st_value; class Protocol; class handler; +struct Schema_specification_st; struct TABLE; struct SORT_FIELD_ATTR; @@ -707,6 +708,28 @@ public: Column_definition *c, handler *file, ulonglong table_flags) const; + /* + This method is called on queries like: + CREATE TABLE t2 (a INT) AS SELECT a FROM t1; + I.e. column "a" is queried from another table, + but its data type is redefined. + @param OUT def - The column definition to be redefined + @param IN dup - The column definition to take the data type from + (i.e. "a INT" in the above example). + @param IN file - Table owner handler. If it does not support certain + data types, some conversion can be applied. + I.g. true BIT to BIT-AS-CHAR. + @param IN schema - the owner schema definition, e.g. for the default + character set and collation. + @retval true - on error + @retval false - on success + */ + virtual bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st * + schema) + const; virtual bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const= 0; @@ -966,6 +989,15 @@ public: DBUG_ASSERT(0); return true; } + bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const + { + DBUG_ASSERT(0); + return true; + } bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const @@ -1536,6 +1568,11 @@ public: Column_definition *c, handler *file, ulonglong table_flags) const; + bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const; uint32 max_display_length(const Item *item) const; uint Item_time_precision(Item *item) const { @@ -1830,6 +1867,11 @@ public: Column_definition *c, handler *file, ulonglong table_flags) const; + bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const; @@ -2250,6 +2292,11 @@ public: Column_definition *c, handler *file, ulonglong table_flags) const; + bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const; @@ -2282,6 +2329,11 @@ public: Column_definition *c, handler *file, ulonglong table_flags) const; + bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const @@ -2573,6 +2625,11 @@ public: Column_definition *c, handler *file, ulonglong table_flags) const; + bool Column_definition_redefine_stage1(Column_definition *def, + const Column_definition *dup, + const handler *file, + const Schema_specification_st *schema) + const; };