Browse Source

MDEV-12588 Add Type_handler::type_handler_for_tmp_table() and Type_handler::type_handler_for_union()

1. Implementing the task according to the description:

a. Adding Type_handler::type_handler_for_tmp_table().
b. Adding Type_handler::type_handler_for_union_table.
c. Adding helper methods Type_handler::varstring_type_handler(const Item*),
   Type_handler::blob_type_handler(const Item*)
d. Removing Item::make_string_field() and
   Item_func_group_concat::make_string_field().
   They are not needed any more.
e. Simplifying Item::tmp_table_field_from_field_type() to just two lines.
f. Renaming Item_type_holder::make_field_by_type() and implementing
   virtual Item_type_holder::create_tmp_field() instead.
   The new implementation is also as simple as two lines.
g. Adding a new virtual method Type_all_attributes::get_typelib(),
   to access to TYPELIB definitions for ENUM and SET columns.
h. Simplifying the code branch for TIME_RESULT, DECIMAL_RESULT, STRING_RESULT
   in Item::create_tmp_field(). It's now just one line.
i. Implementing Type_handler_enum::make_table_field() and
   Type_handler_set::make_table_field().

2. Code simplification in Field_str constructor calls.

a. Changing the "CHARSET_INFO *cs" argument in constuctors for Field_str
   and its descendants to "const DTCollation &collation". This is to
   avoid two step initialization:
   - setting Field_str::derivation and Field_str::repertoire to the
     default values first
   - then resetting them using:
     set_derivation(item->derivation, item->repertoire).

b. Removing Field::set_derivation()

c. Adding a new constructor DTCollation(CHARSET_INFO *cs),
   for the old code compatibility.

3. Changes in test results

As a side effect some test results have changed, because
in the old version Item::make_string_field() converted
TINYBLOB to VARCHAR(255). Now TINYBLOB is preserved.

a. sp-row.result
   This query:
     CREATE TABLE t1 AS SELECT tinyblob_sp_variable;
   Now preserves TINYBLOB as the data type.
   Before the patch a VARCHAR(255) was created.

b. gis-debug.result
   This is a debug test, to make sure that + and - operators
   are commutative and non-commutative correspondingly.
   The exact data type is not really important.
   (But anyway, it now chooses a better data type that fits the result)
pull/381/head
Alexander Barkov 9 years ago
parent
commit
441349aa06
  1. 14
      mysql-test/r/gis-debug.result
  2. 8
      mysql-test/r/sp-row.result
  3. 8
      mysql-test/suite/compat/oracle/r/sp-row.result
  4. 14
      sql/field.cc
  5. 58
      sql/field.h
  6. 133
      sql/item.cc
  7. 26
      sql/item.h
  8. 18
      sql/item_sum.cc
  9. 3
      sql/item_sum.h
  10. 19
      sql/sql_select.cc
  11. 87
      sql/sql_type.cc
  12. 65
      sql/sql_type.h

14
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;

8
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;

8
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;

14
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

58
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;
}

133
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.

26
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; }
};

18
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);

3
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<Item> *is_select,

19
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;
}

87
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;
}
/***************************************************************************/

65
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
{

Loading…
Cancel
Save