diff --git a/mysql-test/r/gis-debug.result b/mysql-test/r/gis-debug.result index 889ee5c9513..1516c3d5089 100644 --- a/mysql-test/r/gis-debug.result +++ b/mysql-test/r/gis-debug.result @@ -381,11 +381,11 @@ POINT(0,0) MOD '0' LIMIT 0; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `POINT(0,0)+'0'` longtext DEFAULT NULL, - `POINT(0,0)-'0'` longtext DEFAULT NULL, - `POINT(0,0)*'0'` longtext DEFAULT NULL, - `POINT(0,0)/'0'` longtext DEFAULT NULL, - `POINT(0,0) MOD '0'` longtext DEFAULT NULL + `POINT(0,0)+'0'` tinytext DEFAULT NULL, + `POINT(0,0)-'0'` tinytext DEFAULT NULL, + `POINT(0,0)*'0'` tinytext DEFAULT NULL, + `POINT(0,0)/'0'` tinytext DEFAULT NULL, + `POINT(0,0) MOD '0'` tinytext DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 AS SELECT @@ -394,8 +394,8 @@ CREATE TABLE t1 AS SELECT SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `'0'+POINT(0,0)` longtext DEFAULT NULL, - `'0'*POINT(0,0)` longtext DEFAULT NULL + `'0'+POINT(0,0)` tinytext DEFAULT NULL, + `'0'*POINT(0,0)` tinytext DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0; diff --git a/mysql-test/r/sp-row.result b/mysql-test/r/sp-row.result index 687e6629b8d..1f33f11a519 100644 --- a/mysql-test/r/sp-row.result +++ b/mysql-test/r/sp-row.result @@ -2052,8 +2052,8 @@ CALL p1(); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `var` varchar(255) DEFAULT NULL, - `rec.var` varchar(255) DEFAULT NULL + `var` tinytext DEFAULT NULL, + `rec.var` tinytext DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; DROP PROCEDURE p1; @@ -2092,8 +2092,8 @@ CALL p1(); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `var` varchar(255) CHARACTER SET utf8 DEFAULT NULL, - `rec.var` varchar(255) CHARACTER SET utf8 DEFAULT NULL + `var` text CHARACTER SET utf8 DEFAULT NULL, + `rec.var` text CHARACTER SET utf8 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; DROP PROCEDURE p1; diff --git a/mysql-test/suite/compat/oracle/r/sp-row.result b/mysql-test/suite/compat/oracle/r/sp-row.result index 5712bce3cee..6526b3e1ec3 100644 --- a/mysql-test/suite/compat/oracle/r/sp-row.result +++ b/mysql-test/suite/compat/oracle/r/sp-row.result @@ -2129,8 +2129,8 @@ CALL p1(); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE "t1" ( - "var" varchar(255) DEFAULT NULL, - "rec.var" varchar(255) DEFAULT NULL + "var" tinytext DEFAULT NULL, + "rec.var" tinytext DEFAULT NULL ) DROP TABLE t1; DROP PROCEDURE p1; @@ -2169,8 +2169,8 @@ CALL p1(); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE "t1" ( - "var" varchar(255) CHARACTER SET utf8 DEFAULT NULL, - "rec.var" varchar(255) CHARACTER SET utf8 DEFAULT NULL + "var" text CHARACTER SET utf8 DEFAULT NULL, + "rec.var" text CHARACTER SET utf8 DEFAULT NULL ) DROP TABLE t1; DROP PROCEDURE p1; diff --git a/sql/field.cc b/sql/field.cc index fa3104f69fe..8b4aac93a9c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2003,15 +2003,15 @@ bool Field_num::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - CHARSET_INFO *charset_arg) + const DTCollation &collation) :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) { - field_charset= charset_arg; - if (charset_arg->state & MY_CS_BINSORT) + field_charset= collation.collation; + if (collation.collation->state & MY_CS_BINSORT) flags|=BINARY_FLAG; - field_derivation= DERIVATION_IMPLICIT; - field_repertoire= my_charset_repertoire(charset_arg); + field_derivation= collation.derivation; + field_repertoire= collation.repertoire; } @@ -7756,10 +7756,10 @@ Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, - CHARSET_INFO *cs) + const DTCollation &collation) :Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, - cs), + collation), packlength(blob_pack_length) { DBUG_ASSERT(blob_pack_length <= 4); // Only pack lengths 1-4 supported currently diff --git a/sql/field.h b/sql/field.h index 814f3b05811..6a350642463 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1306,9 +1306,6 @@ public: virtual enum Derivation derivation(void) const { return DERIVATION_IMPLICIT; } virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; } - virtual void set_derivation(enum Derivation derivation_arg, - uint repertoire_arg) - { } virtual int set_time() { return 1; } bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment) const; @@ -1659,7 +1656,8 @@ public: const Item_equal *item_equal); Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const LEX_CSTRING *field_name_arg, CHARSET_INFO *charset); + const LEX_CSTRING *field_name_arg, + const DTCollation &collation); uint decimals() const { return NOT_FIXED_DEC; } int save_in_field(Field *to) { return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const @@ -1679,12 +1677,6 @@ public: uint repertoire(void) const { return field_repertoire; } CHARSET_INFO *charset(void) const { return field_charset; } enum Derivation derivation(void) const { return field_derivation; } - void set_derivation(enum Derivation derivation_arg, - uint repertoire_arg) - { - field_derivation= derivation_arg; - field_repertoire= repertoire_arg; - } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_display_length() { return field_length; } friend class Create_field; @@ -1726,9 +1718,10 @@ protected: public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const LEX_CSTRING *field_name_arg, CHARSET_INFO *charset_arg) + const LEX_CSTRING *field_name_arg, + const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, charset_arg) + field_name_arg, collation) {} int store_decimal(const my_decimal *d); @@ -2222,9 +2215,9 @@ class Field_null :public Field_str { public: Field_null(uchar *ptr_arg, uint32 len_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - CHARSET_INFO *cs) + const DTCollation &collation) :Field_str(ptr_arg, len_arg, null, 1, - unireg_check_arg, field_name_arg, cs) + unireg_check_arg, field_name_arg, collation) {} const Type_handler *type_handler() const { return &type_handler_null; } Copy_func *get_copy_func(const Field *from) const @@ -3023,15 +3016,15 @@ public: Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - CHARSET_INFO *cs) + const DTCollation &collation) :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, cs), + unireg_check_arg, field_name_arg, collation), can_alter_field_type(1) {}; Field_string(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - CHARSET_INFO *cs) + const DTCollation &collation) :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs), + NONE, field_name_arg, collation), can_alter_field_type(1) {}; const Type_handler *type_handler() const @@ -3110,18 +3103,18 @@ public: uint32 len_arg, uint length_bytes_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - TABLE_SHARE *share, CHARSET_INFO *cs) + TABLE_SHARE *share, const DTCollation &collation) :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, cs), + unireg_check_arg, field_name_arg, collation), length_bytes(length_bytes_arg) { share->varchar_fields++; } Field_varstring(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - TABLE_SHARE *share, CHARSET_INFO *cs) + TABLE_SHARE *share, const DTCollation &collation) :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs), + NONE, field_name_arg, collation), length_bytes(len_arg < 256 ? 1 :2) { share->varchar_fields++; @@ -3210,20 +3203,21 @@ protected: public: Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs); + TABLE_SHARE *share, uint blob_pack_length, + const DTCollation &collation); Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - CHARSET_INFO *cs) + const DTCollation &collation) :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs), + NONE, field_name_arg, collation), packlength(4) { flags|= BLOB_FLAG; } Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - CHARSET_INFO *cs, bool set_packlength) + const DTCollation &collation, bool set_packlength) :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs) + NONE, field_name_arg, collation) { flags|= BLOB_FLAG; packlength= 4; @@ -3501,9 +3495,9 @@ public: enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint packlength_arg, TYPELIB *typelib_arg, - CHARSET_INFO *charset_arg) + const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, charset_arg), + unireg_check_arg, field_name_arg, collation), packlength(packlength_arg),typelib(typelib_arg) { flags|=ENUM_FLAG; @@ -3594,12 +3588,12 @@ public: uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint32 packlength_arg, - TYPELIB *typelib_arg, CHARSET_INFO *charset_arg) + TYPELIB *typelib_arg, const DTCollation &collation) :Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, packlength_arg, - typelib_arg,charset_arg), - empty_set_string("", 0, charset_arg) + typelib_arg, collation), + empty_set_string("", 0, collation.collation) { flags=(flags & ~ENUM_FLAG) | SET_FLAG; } diff --git a/sql/item.cc b/sql/item.cc index 6199aba12d5..3ee8985c779 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6205,82 +6205,6 @@ bool Item::eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs) } -/** - Create a field to hold a string value from an item. - - If too_big_for_varchar() create a blob @n - If max_length > 0 create a varchar @n - If max_length == 0 create a CHAR(0) - - @param table Table for which the field is created -*/ - -Field *Item::make_string_field(TABLE *table) -{ - Field *field; - MEM_ROOT *mem_root= table->in_use->mem_root; - DBUG_ASSERT(collation.collation); - /* - Note: the following check is repeated in - subquery_types_allow_materialization(): - */ - if (too_big_for_varchar()) - field= new (mem_root) - Field_blob(max_length, maybe_null, &name, - collation.collation, TRUE); - /* Item_type_holder holds the exact type, do not change it */ - else if (max_length > 0 && - (type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING)) - field= new (mem_root) - Field_varstring(max_length, maybe_null, &name, table->s, - collation.collation); - else - field= new (mem_root) - Field_string(max_length, maybe_null, &name, collation.collation); - if (field) - field->init(table); - return field; -} - - -/** - Create a field based on field_type of argument. - - This is used to create a field for - - IFNULL(x,something) - - time functions - - prepared statement placeholders - - SP variables with data type references: DECLARE a t1.a%TYPE; - - @retval - NULL error - @retval - \# Created field -*/ - -Field *Item::tmp_table_field_from_field_type(TABLE *table) -{ - const Type_handler *handler= type_handler(); - Record_addr addr(maybe_null); - - switch (handler->field_type()) { - case MYSQL_TYPE_DECIMAL: - handler= &type_handler_newdecimal; - break; - case MYSQL_TYPE_NULL: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - return make_string_field(table); - default: - break; - } - return handler->make_and_init_table_field(&name, addr, *this, table); -} - - /* ARGSUSED */ void Item_field::make_field(THD *thd, Send_field *tmp_field) { @@ -10256,6 +10180,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) }; maybe_null|= item->maybe_null; get_full_info(item); + set_handler(Item_type_holder::type_handler()->type_handler_for_union(this)); /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */ prev_decimal_int_part= decimal_int_part(); @@ -10266,62 +10191,6 @@ bool Item_type_holder::join_types(THD *thd, Item *item) } -/** - Make temporary table field according collected information about type - of UNION result. - - @param table temporary table for which we create fields - - @return - created field -*/ - -Field *Item_type_holder::make_field_by_type(TABLE *table) -{ - /* - The field functions defines a field to be not null if null_ptr is not 0 - */ - uchar *null_ptr= maybe_null ? (uchar*) "" : 0; - Field *field; - - switch (Item_type_holder::real_type_handler()->real_field_type()) { - case MYSQL_TYPE_ENUM: - { - DBUG_ASSERT(enum_set_typelib); - field= new Field_enum((uchar *) 0, max_length, null_ptr, 0, - Field::NONE, &name, - get_enum_pack_length(enum_set_typelib->count), - enum_set_typelib, collation.collation); - if (field) - field->init(table); - return field; - } - case MYSQL_TYPE_SET: - { - DBUG_ASSERT(enum_set_typelib); - field= new Field_set((uchar *) 0, max_length, null_ptr, 0, - Field::NONE, &name, - get_set_pack_length(enum_set_typelib->count), - enum_set_typelib, collation.collation); - if (field) - field->init(table); - return field; - } - case MYSQL_TYPE_NULL: - return make_string_field(table); - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - set_handler(Type_handler::blob_type_handler(max_length)); - break; - default: - break; - } - return tmp_table_field_from_field_type(table); -} - - /** Get full information from Item about enum/set fields to be able to create them later. diff --git a/sql/item.h b/sql/item.h index 28bc0283495..7200b69b7b5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -536,8 +536,22 @@ protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); - virtual Field *make_string_field(TABLE *table); - Field *tmp_table_field_from_field_type(TABLE *table); + /** + Create a field based on field_type of argument. + This is used to create a field for + - IFNULL(x,something) + - time functions + - prepared statement placeholders + - SP variables with data type references: DECLARE a TYPE OF t1.a; + @retval NULL error + @retval !NULL on success + */ + Field *tmp_table_field_from_field_type(TABLE *table) + { + const Type_handler *h= type_handler()->type_handler_for_tmp_table(this); + return h->make_and_init_table_field(&name, Record_addr(maybe_null), + *this, table); + } Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); void push_note_converted_to_negative_complement(THD *thd); @@ -5891,12 +5905,18 @@ public: } enum Type type() const { return TYPE_HOLDER; } + TYPELIB *get_typelib() const { return enum_set_typelib; } double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); String *val_str(String*); bool join_types(THD *thd, Item *); - Field *make_field_by_type(TABLE *table); + Field *create_tmp_field(bool group, TABLE *table) + { + return Item_type_holder::type_handler()-> + make_and_init_table_field(&name, Record_addr(maybe_null), + *this, table); + } Field::geometry_type get_geometry_type() const { return geometry_type; }; Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 1eac5ed2593..6d510253259 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3318,24 +3318,6 @@ void Item_func_group_concat::cleanup() } -Field *Item_func_group_concat::make_string_field(TABLE *table_arg) -{ - Field *field; - DBUG_ASSERT(collation.collation); - - if (too_big_for_varchar()) - field= new Field_blob(max_length, - maybe_null, &name, collation.collation, TRUE); - else - field= new Field_varstring(max_length, - maybe_null, &name, table_arg->s, collation.collation); - - if (field) - field->init(table_arg); - return field; -} - - Item *Item_func_group_concat::copy_or_same(THD* thd) { return new (thd->mem_root) Item_func_group_concat(thd, this); diff --git a/sql/item_sum.h b/sql/item_sum.h index 039ae0de1a8..33ee83f147b 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1636,9 +1636,6 @@ class Item_func_group_concat : public Item_sum friend int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), void* item_arg); -protected: - virtual Field *make_string_field(TABLE *table); - public: Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, bool is_distinct, List *is_select, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3eecd9b2544..b3c427bf043 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15880,19 +15880,8 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) } case TIME_RESULT: case DECIMAL_RESULT: - new_field= tmp_table_field_from_field_type(table); - break; case STRING_RESULT: - DBUG_ASSERT(collation.collation); - /* - GEOMETRY fields have STRING_RESULT result type. - To preserve type they needed to be handled separately. - */ - if (field_type() == MYSQL_TYPE_GEOMETRY) - new_field= tmp_table_field_from_field_type(table); - else - new_field= make_string_field(table); - new_field->set_derivation(collation.derivation, collation.repertoire); + new_field= tmp_table_field_from_field_type(table); break; case ROW_RESULT: // This case should never be choosen @@ -16029,6 +16018,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } switch (type) { + case Item::TYPE_HOLDER: case Item::SUM_FUNC_ITEM: { result= item->create_tmp_field(group, table); @@ -16158,11 +16148,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, return create_tmp_field_from_item(thd, item, table, (make_copy_field ? 0 : copy_func), modify_item); - case Item::TYPE_HOLDER: - result= ((Item_type_holder *)item)->make_field_by_type(table); - result->set_derivation(item->collation.derivation, - item->collation.repertoire); - return result; default: // Dosen't have to be stored return 0; } diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 61521052444..9b4aa61cbdb 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -154,6 +154,17 @@ Type_handler::string_type_handler(uint max_octet_length) } +const Type_handler * +Type_handler::varstring_type_handler(const Item *item) +{ + if (!item->max_length) + return &type_handler_string; + if (item->too_big_for_varchar()) + return blob_type_handler(item->max_length); + return &type_handler_varchar; +} + + const Type_handler * Type_handler::blob_type_handler(uint max_octet_length) { @@ -167,6 +178,12 @@ Type_handler::blob_type_handler(uint max_octet_length) } +const Type_handler * +Type_handler::blob_type_handler(const Item *item) +{ + return blob_type_handler(item->max_length); +} + /** This method is used by: - Item_sum_hybrid, e.g. MAX(item), MIN(item). @@ -1514,7 +1531,7 @@ Field *Type_handler_string::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) Field_string(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, - Field::NONE, name, attr.collation.collation); + Field::NONE, name, attr.collation); } @@ -1529,7 +1546,7 @@ Field *Type_handler_varchar::make_table_field(const LEX_CSTRING *name, HA_VARCHAR_PACKLENGTH(attr.max_length), addr.null_ptr, addr.null_bit, Field::NONE, name, - table->s, attr.collation.collation); + table->s, attr.collation); } @@ -1542,7 +1559,7 @@ Field *Type_handler_tiny_blob::make_table_field(const LEX_CSTRING *name, return new (table->in_use->mem_root) Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, Field::NONE, name, table->s, - 1, attr.collation.collation); + 1, attr.collation); } @@ -1555,7 +1572,7 @@ Field *Type_handler_blob::make_table_field(const LEX_CSTRING *name, return new (table->in_use->mem_root) Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, Field::NONE, name, table->s, - 2, attr.collation.collation); + 2, attr.collation); } @@ -1569,7 +1586,7 @@ Type_handler_medium_blob::make_table_field(const LEX_CSTRING *name, return new (table->in_use->mem_root) Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, Field::NONE, name, table->s, - 3, attr.collation.collation); + 3, attr.collation); } @@ -1582,7 +1599,7 @@ Field *Type_handler_long_blob::make_table_field(const LEX_CSTRING *name, return new (table->in_use->mem_root) Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, Field::NONE, name, table->s, - 4, attr.collation.collation); + 4, attr.collation); } @@ -1607,12 +1624,13 @@ Field *Type_handler_enum::make_table_field(const LEX_CSTRING *name, const Type_all_attributes &attr, TABLE *table) const { - /* - Will be implemented when we split Item_type_holder::make_field_by_type() - and/or reuse Type_handler::make_table_field() in make_field() in field.cc - */ - DBUG_ASSERT(0); - return 0; + TYPELIB *typelib= attr.get_typelib(); + DBUG_ASSERT(typelib); + return new (table->in_use->mem_root) + Field_enum(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, + get_enum_pack_length(typelib->count), typelib, + attr.collation); } @@ -1622,12 +1640,13 @@ Field *Type_handler_set::make_table_field(const LEX_CSTRING *name, TABLE *table) const { - /* - Will be implemented when we split Item_type_holder::make_field_by_type() - and/or reuse Type_handler::make_table_field() in make_field() in field.cc - */ - DBUG_ASSERT(0); - return 0; + TYPELIB *typelib= attr.get_typelib(); + DBUG_ASSERT(typelib); + return new (table->in_use->mem_root) + Field_set(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, + get_enum_pack_length(typelib->count), typelib, + attr.collation); } /*************************************************************************/ @@ -3714,7 +3733,7 @@ bool Type_handler_string_result:: /* Materialization also is unable to work when create_tmp_table() will create a blob column because item->max_length is too big. - The following test is copied from Item::make_string_field(): + The following test is copied from varstring_type_handler(). */ !inner->too_big_for_varchar(); } @@ -3730,3 +3749,33 @@ bool Type_handler_temporal_result:: } /***************************************************************************/ + + +const Type_handler * +Type_handler_null::type_handler_for_tmp_table(const Item *item) const +{ + return &type_handler_string; +} + + +const Type_handler * +Type_handler_null::type_handler_for_union(const Item *item) const +{ + return &type_handler_string; +} + + +const Type_handler * +Type_handler_olddecimal::type_handler_for_tmp_table(const Item *item) const +{ + return &type_handler_newdecimal; +} + +const Type_handler * +Type_handler_olddecimal::type_handler_for_union(const Item *item) const +{ + return &type_handler_newdecimal; +} + + +/***************************************************************************/ diff --git a/sql/sql_type.h b/sql/sql_type.h index 0d4230403f4..e3e86ae7204 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -130,6 +130,21 @@ public: derivation= DERIVATION_NONE; repertoire= MY_REPERTOIRE_UNICODE30; } + DTCollation(CHARSET_INFO *collation_arg) + { + /* + This constructor version is used in combination with Field constructors, + to pass "CHARSET_INFO" instead of the full DTCollation. + Therefore, derivation is set to DERIVATION_IMPLICIT, which is the + proper derivation for table fields. + We should eventually remove all code pieces that pass "CHARSET_INFO" + (e.g. in storage engine sources) and fix to pass the full DTCollation + instead. Then, this constructor can be removed. + */ + collation= collation_arg; + derivation= DERIVATION_IMPLICIT; + repertoire= my_charset_repertoire(collation_arg); + } DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) { collation= collation_arg; @@ -332,6 +347,7 @@ public: datatype indepented method. */ virtual uint uint_geometry_type() const= 0; + virtual TYPELIB *get_typelib() const { return NULL; } }; @@ -390,6 +406,15 @@ protected: public: static const Type_handler *blob_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length); + /** + Return a string type handler for Item + If too_big_for_varchar() returns a BLOB variant, according to length. + If max_length > 0 create a VARCHAR(n) + If max_length == 0 create a CHAR(0) + @param item - the Item to get the handler to. + */ + static const Type_handler *varstring_type_handler(const Item *item); + static const Type_handler *blob_type_handler(const Item *item); static const Type_handler *get_handler_by_field_type(enum_field_types type); static const Type_handler *get_handler_by_real_type(enum_field_types type); static const Type_handler *get_handler_by_cmp_type(Item_result type); @@ -426,6 +451,14 @@ public: */ virtual bool is_param_long_data_type() const { return false; } virtual const Type_handler *type_handler_for_comparison() const= 0; + virtual const Type_handler *type_handler_for_tmp_table(const Item *) const + { + return this; + } + virtual const Type_handler *type_handler_for_union(const Item *) const + { + return this; + } virtual const Type_handler *cast_to_int_type_handler() const { return this; @@ -1594,6 +1627,8 @@ public: virtual ~Type_handler_olddecimal() {} const Name name() const { return m_name_decimal; } enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; } + const Type_handler *type_handler_for_tmp_table(const Item *item) const; + const Type_handler *type_handler_for_union(const Item *item) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; Field *make_table_field(const LEX_CSTRING *name, @@ -1627,6 +1662,8 @@ public: const Name name() const { return m_name_null; } enum_field_types field_type() const { return MYSQL_TYPE_NULL; } const Type_handler *type_handler_for_comparison() const; + const Type_handler *type_handler_for_tmp_table(const Item *item) const; + const Type_handler *type_handler_for_union(const Item *) const; uint32 max_display_length(const Item *item) const { return 0; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -1645,6 +1682,10 @@ public: const Name name() const { return m_name_char; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; } bool is_param_long_data_type() const { return true; } + const Type_handler *type_handler_for_tmp_table(const Item *item) const + { + return varstring_type_handler(item); + } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; Field *make_table_field(const LEX_CSTRING *name, @@ -1663,6 +1704,14 @@ public: const Name name() const { return m_name_var_string; } enum_field_types field_type() const { return MYSQL_TYPE_VAR_STRING; } enum_field_types real_field_type() const { return MYSQL_TYPE_STRING; } + const Type_handler *type_handler_for_tmp_table(const Item *item) const + { + return varstring_type_handler(item); + } + const Type_handler *type_handler_for_union(const Item *item) const + { + return varstring_type_handler(item); + } }; @@ -1673,6 +1722,14 @@ public: virtual ~Type_handler_varchar() {} const Name name() const { return m_name_varchar; } enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } + const Type_handler *type_handler_for_tmp_table(const Item *item) const + { + return varstring_type_handler(item); + } + const Type_handler *type_handler_for_union(const Item *item) const + { + return varstring_type_handler(item); + } bool is_param_long_data_type() const { return true; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -1687,6 +1744,14 @@ class Type_handler_blob_common: public Type_handler_string_result { public: virtual ~Type_handler_blob_common() { } + const Type_handler *type_handler_for_tmp_table(const Item *item) const + { + return blob_type_handler(item); + } + const Type_handler *type_handler_for_union(const Item *item) const + { + return blob_type_handler(item); + } bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const {