maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #10658
Please review MDEV-12588 Add Type_handler::type_handler_for_tmp_table() and Type_handler::type_handler_for_union()
Hello Sanja,
Please review a patch for MDEV-12588.
Thanks!
commit 595f33775d49c6a77511d5f4b92f54a9ea4bda1c
Author: Alexander Barkov <bar@xxxxxxxxxxx>
Date: Tue Apr 25 19:05:33 2017 +0400
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)
diff --git a/mysql-test/r/gis-debug.result b/mysql-test/r/gis-debug.result
index 889ee5c..1516c3d 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 687e662..1f33f11 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 5712bce..6526b3e 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 13bef70..2b602e1 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 30a379a..73c725f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1306,9 +1306,6 @@ class Field: public Value_source
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 @@ class Field_str :public Field {
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 @@ class Field_str :public Field {
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 @@ class Field_longstr :public Field_str
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 @@ class Field_string :public Field_longstr {
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 @@ class Field_varstring :public Field_longstr {
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 @@ class Field_blob :public Field_longstr {
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;
@@ -3509,9 +3503,9 @@ class Field_enum :public Field_str {
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;
@@ -3602,12 +3596,12 @@ class Field_set :public Field_enum {
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 6199aba..3ee8985 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();
@@ -10267,62 +10192,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 28bc028..575b8e1 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -536,8 +536,22 @@ class Item: public Value_source,
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 t1.a%TYPE;
+ @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 @@ class Item_type_holder: public Item,
}
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 1eac5ed..6d51025 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 039ae0d..33ee83f 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<Item> *is_select,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3eecd9b..b3c427b 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 6152105..9b4aa61 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -155,6 +155,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)
{
if (max_octet_length <= 255)
@@ -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 0d42304..745c966 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -130,6 +130,12 @@ class DTCollation {
derivation= DERIVATION_NONE;
repertoire= MY_REPERTOIRE_UNICODE30;
}
+ DTCollation(CHARSET_INFO *collation_arg)
+ {
+ 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 +338,7 @@ class Type_all_attributes: public Type_std_attributes
datatype indepented method.
*/
virtual uint uint_geometry_type() const= 0;
+ virtual TYPELIB *get_typelib() const { return NULL; }
};
@@ -390,6 +397,15 @@ class Type_handler
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 an 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 +442,14 @@ class Type_handler
*/
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 +1618,8 @@ class Type_handler_olddecimal: public Type_handler_decimal_result
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 +1653,8 @@ class Type_handler_null: public Type_handler_string_result
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 +1673,10 @@ class Type_handler_string: public Type_handler_string_result
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 +1695,14 @@ class Type_handler_var_string: public Type_handler_string
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 +1713,14 @@ class Type_handler_varchar: public Type_handler_string_result
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 +1735,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
{