mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-9215 Detect cmp_type() and result_type() from field_type()
Part6: Deriving Item_type_holder from Type_handler_hybrid_real_field_type
This commit is contained in:
78
sql/item.cc
78
sql/item.cc
@ -2977,9 +2977,9 @@ default_set_param_func(Item_param *param,
|
|||||||
|
|
||||||
|
|
||||||
Item_param::Item_param(THD *thd, uint pos_in_query_arg):
|
Item_param::Item_param(THD *thd, uint pos_in_query_arg):
|
||||||
Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
|
|
||||||
Item_basic_value(thd),
|
Item_basic_value(thd),
|
||||||
Rewritable_query_parameter(pos_in_query_arg, 1),
|
Rewritable_query_parameter(pos_in_query_arg, 1),
|
||||||
|
Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
|
||||||
state(NO_VALUE),
|
state(NO_VALUE),
|
||||||
/* Don't pretend to be a literal unless value for this item is set. */
|
/* Don't pretend to be a literal unless value for this item is set. */
|
||||||
item_type(PARAM_ITEM),
|
item_type(PARAM_ITEM),
|
||||||
@ -9188,14 +9188,28 @@ void Item_cache_row::set_null()
|
|||||||
|
|
||||||
|
|
||||||
Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
||||||
:Item(thd, item), enum_set_typelib(0), fld_type(get_real_type(item))
|
:Item(thd, item),
|
||||||
|
Type_handler_hybrid_real_field_type(get_real_type(item)),
|
||||||
|
enum_set_typelib(0)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(item->fixed);
|
DBUG_ASSERT(item->fixed);
|
||||||
maybe_null= item->maybe_null;
|
maybe_null= item->maybe_null;
|
||||||
collation.set(item->collation);
|
collation.set(item->collation);
|
||||||
get_full_info(item);
|
get_full_info(item);
|
||||||
|
/**
|
||||||
|
Field::result_merge_type(real_field_type()) should be equal to
|
||||||
|
result_type(), with one exception when "this" is a Item_field for
|
||||||
|
a BIT field:
|
||||||
|
- Field_bit::result_type() returns INT_RESULT, so does its Item_field.
|
||||||
|
- Field::result_merge_type(MYSQL_TYPE_BIT) returns STRING_RESULT.
|
||||||
|
Perhaps we need a new method in Type_handler to cover these type
|
||||||
|
merging rules for UNION.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(real_field_type() == MYSQL_TYPE_BIT ||
|
||||||
|
Item_type_holder::result_type() ==
|
||||||
|
Field::result_merge_type(Item_type_holder::real_field_type()));
|
||||||
/* fix variable decimals which always is NOT_FIXED_DEC */
|
/* fix variable decimals which always is NOT_FIXED_DEC */
|
||||||
if (Field::result_merge_type(fld_type) == INT_RESULT)
|
if (Field::result_merge_type(real_field_type()) == INT_RESULT)
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
prev_decimal_int_part= item->decimal_int_part();
|
prev_decimal_int_part= item->decimal_int_part();
|
||||||
#ifdef HAVE_SPATIAL
|
#ifdef HAVE_SPATIAL
|
||||||
@ -9205,19 +9219,6 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Return expression type of Item_type_holder.
|
|
||||||
|
|
||||||
@return
|
|
||||||
Item_result (type of internal MySQL expression result)
|
|
||||||
*/
|
|
||||||
|
|
||||||
Item_result Item_type_holder::result_type() const
|
|
||||||
{
|
|
||||||
return Field::result_merge_type(fld_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Find real field type of item.
|
Find real field type of item.
|
||||||
|
|
||||||
@ -9268,7 +9269,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
|
|||||||
*/
|
*/
|
||||||
switch (item->result_type()) {
|
switch (item->result_type()) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
return MYSQL_TYPE_VAR_STRING;
|
return MYSQL_TYPE_VARCHAR;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
return MYSQL_TYPE_LONGLONG;
|
return MYSQL_TYPE_LONGLONG;
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
@ -9278,10 +9279,21 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
|
|||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
case TIME_RESULT:
|
case TIME_RESULT:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return MYSQL_TYPE_VAR_STRING;
|
return MYSQL_TYPE_VARCHAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TYPE_HOLDER:
|
||||||
|
/*
|
||||||
|
Item_type_holder and Item_blob should not appear in this context.
|
||||||
|
In case they for some reasons do, returning field_type() is wrong anyway.
|
||||||
|
They must return Item_type_holder::real_field_type() instead, to make
|
||||||
|
the code in sql_type.cc and sql_type.h happy, as it expectes
|
||||||
|
Field::real_type()-compatible rather than Field::field_type()-compatible
|
||||||
|
valies in some places, and may in the future add some asserts preventing
|
||||||
|
use of field_type() instead of real_type() and the other way around.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(0);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -9307,25 +9319,26 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
|||||||
uint decimals_orig= decimals;
|
uint decimals_orig= decimals;
|
||||||
DBUG_ENTER("Item_type_holder::join_types");
|
DBUG_ENTER("Item_type_holder::join_types");
|
||||||
DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s",
|
DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s",
|
||||||
fld_type, max_length, decimals,
|
real_field_type(), max_length, decimals,
|
||||||
(name ? name : "<NULL>")));
|
(name ? name : "<NULL>")));
|
||||||
DBUG_PRINT("info:", ("in type %d len %d, dec %d",
|
DBUG_PRINT("info:", ("in type %d len %d, dec %d",
|
||||||
get_real_type(item),
|
get_real_type(item),
|
||||||
item->max_length, item->decimals));
|
item->max_length, item->decimals));
|
||||||
fld_type= Field::field_type_merge(fld_type, get_real_type(item));
|
set_handler_by_real_type(Field::field_type_merge(real_field_type(),
|
||||||
|
get_real_type(item)));
|
||||||
{
|
{
|
||||||
uint item_decimals= item->decimals;
|
uint item_decimals= item->decimals;
|
||||||
/* fix variable decimals which always is NOT_FIXED_DEC */
|
/* fix variable decimals which always is NOT_FIXED_DEC */
|
||||||
if (Field::result_merge_type(fld_type) == INT_RESULT)
|
if (Field::result_merge_type(real_field_type()) == INT_RESULT)
|
||||||
item_decimals= 0;
|
item_decimals= 0;
|
||||||
decimals= MY_MAX(decimals, item_decimals);
|
decimals= MY_MAX(decimals, item_decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fld_type == FIELD_TYPE_GEOMETRY)
|
if (Item_type_holder::field_type() == FIELD_TYPE_GEOMETRY)
|
||||||
geometry_type=
|
geometry_type=
|
||||||
Field_geom::geometry_type_merge(geometry_type, item->get_geometry_type());
|
Field_geom::geometry_type_merge(geometry_type, item->get_geometry_type());
|
||||||
|
|
||||||
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
|
if (Field::result_merge_type(real_field_type()) == DECIMAL_RESULT)
|
||||||
{
|
{
|
||||||
decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE);
|
decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE);
|
||||||
int item_int_part= item->decimal_int_part();
|
int item_int_part= item->decimal_int_part();
|
||||||
@ -9337,7 +9350,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
|||||||
unsigned_flag);
|
unsigned_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Field::result_merge_type(fld_type))
|
switch (Field::result_merge_type(real_field_type()))
|
||||||
{
|
{
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
@ -9384,12 +9397,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
|||||||
int delta1= max_length_orig - decimals_orig;
|
int delta1= max_length_orig - decimals_orig;
|
||||||
int delta2= item->max_length - item->decimals;
|
int delta2= item->max_length - item->decimals;
|
||||||
max_length= MY_MAX(delta1, delta2) + decimals;
|
max_length= MY_MAX(delta1, delta2) + decimals;
|
||||||
if (fld_type == MYSQL_TYPE_FLOAT && max_length > FLT_DIG + 2)
|
if (Item_type_holder::real_field_type() == MYSQL_TYPE_FLOAT &&
|
||||||
|
max_length > FLT_DIG + 2)
|
||||||
{
|
{
|
||||||
max_length= MAX_FLOAT_STR_LENGTH;
|
max_length= MAX_FLOAT_STR_LENGTH;
|
||||||
decimals= NOT_FIXED_DEC;
|
decimals= NOT_FIXED_DEC;
|
||||||
}
|
}
|
||||||
else if (fld_type == MYSQL_TYPE_DOUBLE && max_length > DBL_DIG + 2)
|
else if (Item_type_holder::real_field_type() == MYSQL_TYPE_DOUBLE &&
|
||||||
|
max_length > DBL_DIG + 2)
|
||||||
{
|
{
|
||||||
max_length= MAX_DOUBLE_STR_LENGTH;
|
max_length= MAX_DOUBLE_STR_LENGTH;
|
||||||
decimals= NOT_FIXED_DEC;
|
decimals= NOT_FIXED_DEC;
|
||||||
@ -9397,7 +9412,8 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7;
|
max_length= (Item_type_holder::field_type() == MYSQL_TYPE_FLOAT) ?
|
||||||
|
FLT_DIG+6 : DBL_DIG+7;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -9409,7 +9425,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
|||||||
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
|
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
|
||||||
prev_decimal_int_part= decimal_int_part();
|
prev_decimal_int_part= decimal_int_part();
|
||||||
DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
|
DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
|
||||||
(int) fld_type, max_length, (uint) decimals));
|
(int) real_field_type(), max_length, (uint) decimals));
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9490,7 +9506,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
|
|||||||
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
|
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
|
||||||
Field *field;
|
Field *field;
|
||||||
|
|
||||||
switch (fld_type) {
|
switch (Item_type_holder::real_field_type()) {
|
||||||
case MYSQL_TYPE_ENUM:
|
case MYSQL_TYPE_ENUM:
|
||||||
DBUG_ASSERT(enum_set_typelib);
|
DBUG_ASSERT(enum_set_typelib);
|
||||||
field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
|
field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
|
||||||
@ -9526,8 +9542,8 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
|
|||||||
*/
|
*/
|
||||||
void Item_type_holder::get_full_info(Item *item)
|
void Item_type_holder::get_full_info(Item *item)
|
||||||
{
|
{
|
||||||
if (fld_type == MYSQL_TYPE_ENUM ||
|
if (Item_type_holder::real_field_type() == MYSQL_TYPE_ENUM ||
|
||||||
fld_type == MYSQL_TYPE_SET)
|
Item_type_holder::real_field_type() == MYSQL_TYPE_SET)
|
||||||
{
|
{
|
||||||
if (item->type() == Item::SUM_FUNC_ITEM &&
|
if (item->type() == Item::SUM_FUNC_ITEM &&
|
||||||
(((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
|
(((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
|
||||||
|
27
sql/item.h
27
sql/item.h
@ -5265,11 +5265,11 @@ public:
|
|||||||
Item_type_holder do not need cleanup() because its time of live limited by
|
Item_type_holder do not need cleanup() because its time of live limited by
|
||||||
single SP/PS execution.
|
single SP/PS execution.
|
||||||
*/
|
*/
|
||||||
class Item_type_holder: public Item
|
class Item_type_holder: public Item,
|
||||||
|
public Type_handler_hybrid_real_field_type
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
TYPELIB *enum_set_typelib;
|
TYPELIB *enum_set_typelib;
|
||||||
enum_field_types fld_type;
|
|
||||||
Field::geometry_type geometry_type;
|
Field::geometry_type geometry_type;
|
||||||
|
|
||||||
void get_full_info(Item *item);
|
void get_full_info(Item *item);
|
||||||
@ -5279,8 +5279,27 @@ protected:
|
|||||||
public:
|
public:
|
||||||
Item_type_holder(THD*, Item*);
|
Item_type_holder(THD*, Item*);
|
||||||
|
|
||||||
Item_result result_type() const;
|
enum_field_types field_type() const
|
||||||
enum_field_types field_type() const { return fld_type; };
|
{ return Type_handler_hybrid_real_field_type::field_type(); }
|
||||||
|
enum_field_types real_field_type() const
|
||||||
|
{ return Type_handler_hybrid_real_field_type::real_field_type(); }
|
||||||
|
enum Item_result result_type () const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
In 10.1 Item_type_holder::result_type() returned
|
||||||
|
Field::result_merge_type(field_type()), which returned STRING_RESULT
|
||||||
|
for the BIT data type. In 10.2 it returns INT_RESULT, similar
|
||||||
|
to what Field_bit::result_type() does. This should not be
|
||||||
|
important because Item_type_holder is a limited purpose Item
|
||||||
|
and its result_type() should not be called from outside of
|
||||||
|
Item_type_holder. It's called only internally from decimal_int_part()
|
||||||
|
from join_types(), to calculate "decimals" of the result data type.
|
||||||
|
As soon as we get BIT as one of the joined types, the result field
|
||||||
|
type cannot be numeric: it's either BIT, or VARBINARY.
|
||||||
|
*/
|
||||||
|
return Type_handler_hybrid_real_field_type::result_type();
|
||||||
|
}
|
||||||
|
|
||||||
enum Type type() const { return TYPE_HOLDER; }
|
enum Type type() const { return TYPE_HOLDER; }
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
|
@ -27,9 +27,13 @@ static Type_handler_bit type_handler_bit;
|
|||||||
static Type_handler_float type_handler_float;
|
static Type_handler_float type_handler_float;
|
||||||
static Type_handler_double type_handler_double;
|
static Type_handler_double type_handler_double;
|
||||||
static Type_handler_time type_handler_time;
|
static Type_handler_time type_handler_time;
|
||||||
|
static Type_handler_time2 type_handler_time2;
|
||||||
static Type_handler_date type_handler_date;
|
static Type_handler_date type_handler_date;
|
||||||
|
static Type_handler_newdate type_handler_newdate;
|
||||||
static Type_handler_datetime type_handler_datetime;
|
static Type_handler_datetime type_handler_datetime;
|
||||||
|
static Type_handler_datetime2 type_handler_datetime2;
|
||||||
static Type_handler_timestamp type_handler_timestamp;
|
static Type_handler_timestamp type_handler_timestamp;
|
||||||
|
static Type_handler_timestamp2 type_handler_timestamp2;
|
||||||
static Type_handler_olddecimal type_handler_olddecimal;
|
static Type_handler_olddecimal type_handler_olddecimal;
|
||||||
static Type_handler_newdecimal type_handler_newdecimal;
|
static Type_handler_newdecimal type_handler_newdecimal;
|
||||||
static Type_handler_null type_handler_null;
|
static Type_handler_null type_handler_null;
|
||||||
@ -39,7 +43,11 @@ static Type_handler_tiny_blob type_handler_tiny_blob;
|
|||||||
static Type_handler_medium_blob type_handler_medium_blob;
|
static Type_handler_medium_blob type_handler_medium_blob;
|
||||||
static Type_handler_long_blob type_handler_long_blob;
|
static Type_handler_long_blob type_handler_long_blob;
|
||||||
static Type_handler_blob type_handler_blob;
|
static Type_handler_blob type_handler_blob;
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
static Type_handler_geometry type_handler_geometry;
|
static Type_handler_geometry type_handler_geometry;
|
||||||
|
#endif
|
||||||
|
static Type_handler_enum type_handler_enum;
|
||||||
|
static Type_handler_set type_handler_set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,7 +134,7 @@ Type_handler::get_handler_by_field_type(enum_field_types type)
|
|||||||
case MYSQL_TYPE_FLOAT: return &type_handler_float;
|
case MYSQL_TYPE_FLOAT: return &type_handler_float;
|
||||||
case MYSQL_TYPE_DOUBLE: return &type_handler_double;
|
case MYSQL_TYPE_DOUBLE: return &type_handler_double;
|
||||||
case MYSQL_TYPE_NULL: return &type_handler_null;
|
case MYSQL_TYPE_NULL: return &type_handler_null;
|
||||||
case MYSQL_TYPE_VARCHAR: return &type_handler_varchar;
|
case MYSQL_TYPE_VARCHAR: return &type_handler_varchar;
|
||||||
case MYSQL_TYPE_TINY_BLOB: return &type_handler_tiny_blob;
|
case MYSQL_TYPE_TINY_BLOB: return &type_handler_tiny_blob;
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB: return &type_handler_medium_blob;
|
case MYSQL_TYPE_MEDIUM_BLOB: return &type_handler_medium_blob;
|
||||||
case MYSQL_TYPE_LONG_BLOB: return &type_handler_long_blob;
|
case MYSQL_TYPE_LONG_BLOB: return &type_handler_long_blob;
|
||||||
@ -135,15 +143,78 @@ Type_handler::get_handler_by_field_type(enum_field_types type)
|
|||||||
case MYSQL_TYPE_STRING: return &type_handler_string;
|
case MYSQL_TYPE_STRING: return &type_handler_string;
|
||||||
case MYSQL_TYPE_ENUM: return &type_handler_varchar; // Map to VARCHAR
|
case MYSQL_TYPE_ENUM: return &type_handler_varchar; // Map to VARCHAR
|
||||||
case MYSQL_TYPE_SET: return &type_handler_varchar; // Map to VARCHAR
|
case MYSQL_TYPE_SET: return &type_handler_varchar; // Map to VARCHAR
|
||||||
case MYSQL_TYPE_GEOMETRY: return &type_handler_geometry;
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
case MYSQL_TYPE_TIMESTAMP: return &type_handler_timestamp;
|
#ifdef HAVE_SPATIAL
|
||||||
case MYSQL_TYPE_TIMESTAMP2: return &type_handler_timestamp;
|
return &type_handler_geometry;
|
||||||
case MYSQL_TYPE_DATE: return &type_handler_date;
|
#else
|
||||||
case MYSQL_TYPE_TIME: return &type_handler_time;
|
return NULL;
|
||||||
case MYSQL_TYPE_TIME2: return &type_handler_time;
|
#endif
|
||||||
case MYSQL_TYPE_DATETIME: return &type_handler_datetime;
|
case MYSQL_TYPE_TIMESTAMP: return &type_handler_timestamp2;// Map to timestamp2
|
||||||
case MYSQL_TYPE_DATETIME2: return &type_handler_datetime;
|
case MYSQL_TYPE_TIMESTAMP2: return &type_handler_timestamp2;
|
||||||
case MYSQL_TYPE_NEWDATE: return &type_handler_date;
|
case MYSQL_TYPE_DATE: return &type_handler_newdate; // Map to newdate
|
||||||
|
case MYSQL_TYPE_TIME: return &type_handler_time2; // Map to time2
|
||||||
|
case MYSQL_TYPE_TIME2: return &type_handler_time2;
|
||||||
|
case MYSQL_TYPE_DATETIME: return &type_handler_datetime2; // Map to datetime2
|
||||||
|
case MYSQL_TYPE_DATETIME2: return &type_handler_datetime2;
|
||||||
|
case MYSQL_TYPE_NEWDATE:
|
||||||
|
/*
|
||||||
|
NEWDATE is actually a real_type(), not a field_type(),
|
||||||
|
but it's used around the code in field_type() context.
|
||||||
|
We should probably clean up the code not to use MYSQL_TYPE_NEWDATE
|
||||||
|
in field_type() context and add DBUG_ASSERT(0) here.
|
||||||
|
*/
|
||||||
|
return &type_handler_newdate;
|
||||||
|
};
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return &type_handler_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Type_handler *
|
||||||
|
Type_handler::get_handler_by_real_type(enum_field_types type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case MYSQL_TYPE_DECIMAL: return &type_handler_olddecimal;
|
||||||
|
case MYSQL_TYPE_NEWDECIMAL: return &type_handler_newdecimal;
|
||||||
|
case MYSQL_TYPE_TINY: return &type_handler_tiny;
|
||||||
|
case MYSQL_TYPE_SHORT: return &type_handler_short;
|
||||||
|
case MYSQL_TYPE_LONG: return &type_handler_long;
|
||||||
|
case MYSQL_TYPE_LONGLONG: return &type_handler_longlong;
|
||||||
|
case MYSQL_TYPE_INT24: return &type_handler_int24;
|
||||||
|
case MYSQL_TYPE_YEAR: return &type_handler_year;
|
||||||
|
case MYSQL_TYPE_BIT: return &type_handler_bit;
|
||||||
|
case MYSQL_TYPE_FLOAT: return &type_handler_float;
|
||||||
|
case MYSQL_TYPE_DOUBLE: return &type_handler_double;
|
||||||
|
case MYSQL_TYPE_NULL: return &type_handler_null;
|
||||||
|
case MYSQL_TYPE_VARCHAR: return &type_handler_varchar;
|
||||||
|
case MYSQL_TYPE_TINY_BLOB: return &type_handler_tiny_blob;
|
||||||
|
case MYSQL_TYPE_MEDIUM_BLOB: return &type_handler_medium_blob;
|
||||||
|
case MYSQL_TYPE_LONG_BLOB: return &type_handler_long_blob;
|
||||||
|
case MYSQL_TYPE_BLOB: return &type_handler_blob;
|
||||||
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
|
/*
|
||||||
|
VAR_STRING is actually a field_type(), not a real_type(),
|
||||||
|
but it's used around the code in real_type() context.
|
||||||
|
We should clean up the code and add DBUG_ASSERT(0) here.
|
||||||
|
*/
|
||||||
|
return &type_handler_string;
|
||||||
|
case MYSQL_TYPE_STRING: return &type_handler_string;
|
||||||
|
case MYSQL_TYPE_ENUM: return &type_handler_enum;
|
||||||
|
case MYSQL_TYPE_SET: return &type_handler_set;
|
||||||
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
|
return &type_handler_geometry;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
case MYSQL_TYPE_TIMESTAMP: return &type_handler_timestamp;
|
||||||
|
case MYSQL_TYPE_TIMESTAMP2: return &type_handler_timestamp2;
|
||||||
|
case MYSQL_TYPE_DATE: return &type_handler_date;
|
||||||
|
case MYSQL_TYPE_TIME: return &type_handler_time;
|
||||||
|
case MYSQL_TYPE_TIME2: return &type_handler_time2;
|
||||||
|
case MYSQL_TYPE_DATETIME: return &type_handler_datetime;
|
||||||
|
case MYSQL_TYPE_DATETIME2: return &type_handler_datetime2;
|
||||||
|
case MYSQL_TYPE_NEWDATE: return &type_handler_newdate;
|
||||||
};
|
};
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return &type_handler_string;
|
return &type_handler_string;
|
||||||
|
@ -29,7 +29,9 @@ protected:
|
|||||||
const Type_handler *string_type_handler(uint max_octet_length) const;
|
const Type_handler *string_type_handler(uint max_octet_length) const;
|
||||||
public:
|
public:
|
||||||
static const Type_handler *get_handler_by_field_type(enum_field_types type);
|
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);
|
||||||
virtual enum_field_types field_type() const= 0;
|
virtual enum_field_types field_type() const= 0;
|
||||||
|
virtual enum_field_types real_field_type() const { return field_type(); }
|
||||||
virtual Item_result result_type() const= 0;
|
virtual Item_result result_type() const= 0;
|
||||||
virtual Item_result cmp_type() const= 0;
|
virtual Item_result cmp_type() const= 0;
|
||||||
virtual const Type_handler*
|
virtual const Type_handler*
|
||||||
@ -190,6 +192,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_time2: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_handler_time2() {}
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
|
||||||
|
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Type_handler_date: public Type_handler_temporal_result
|
class Type_handler_date: public Type_handler_temporal_result
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -198,6 +209,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_newdate: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_handler_newdate() {}
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||||
|
enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Type_handler_datetime: public Type_handler_temporal_result
|
class Type_handler_datetime: public Type_handler_temporal_result
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -206,6 +226,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_datetime2: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_handler_datetime2() {}
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
||||||
|
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Type_handler_timestamp: public Type_handler_temporal_result
|
class Type_handler_timestamp: public Type_handler_temporal_result
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -214,6 +243,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_timestamp2: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_handler_timestamp2() {}
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
||||||
|
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Type_handler_olddecimal: public Type_handler_decimal_result
|
class Type_handler_olddecimal: public Type_handler_decimal_result
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -294,6 +332,24 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_enum: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_handler_enum() {}
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
|
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_set: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_handler_set() {}
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
|
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A handler for hybrid type functions, e.g.
|
A handler for hybrid type functions, e.g.
|
||||||
COALESCE(), IF(), IFNULL(), NULLIF(), CASE,
|
COALESCE(), IF(), IFNULL(), NULLIF(), CASE,
|
||||||
@ -309,6 +365,9 @@ class Type_handler_hybrid_field_type: public Type_handler
|
|||||||
const Type_handler *get_handler_by_result_type(Item_result type) const;
|
const Type_handler *get_handler_by_result_type(Item_result type) const;
|
||||||
public:
|
public:
|
||||||
Type_handler_hybrid_field_type();
|
Type_handler_hybrid_field_type();
|
||||||
|
Type_handler_hybrid_field_type(const Type_handler *handler)
|
||||||
|
:m_type_handler(handler)
|
||||||
|
{ }
|
||||||
Type_handler_hybrid_field_type(enum_field_types type)
|
Type_handler_hybrid_field_type(enum_field_types type)
|
||||||
:m_type_handler(get_handler_by_field_type(type))
|
:m_type_handler(get_handler_by_field_type(type))
|
||||||
{ }
|
{ }
|
||||||
@ -316,6 +375,10 @@ public:
|
|||||||
:m_type_handler(other->m_type_handler)
|
:m_type_handler(other->m_type_handler)
|
||||||
{ }
|
{ }
|
||||||
enum_field_types field_type() const { return m_type_handler->field_type(); }
|
enum_field_types field_type() const { return m_type_handler->field_type(); }
|
||||||
|
enum_field_types real_field_type() const
|
||||||
|
{
|
||||||
|
return m_type_handler->real_field_type();
|
||||||
|
}
|
||||||
Item_result result_type() const { return m_type_handler->result_type(); }
|
Item_result result_type() const { return m_type_handler->result_type(); }
|
||||||
Item_result cmp_type() const { return m_type_handler->cmp_type(); }
|
Item_result cmp_type() const { return m_type_handler->cmp_type(); }
|
||||||
void set_handler(const Type_handler *other)
|
void set_handler(const Type_handler *other)
|
||||||
@ -339,6 +402,10 @@ public:
|
|||||||
{
|
{
|
||||||
return (m_type_handler= get_handler_by_field_type(type));
|
return (m_type_handler= get_handler_by_field_type(type));
|
||||||
}
|
}
|
||||||
|
const Type_handler *set_handler_by_real_type(enum_field_types type)
|
||||||
|
{
|
||||||
|
return (m_type_handler= get_handler_by_real_type(type));
|
||||||
|
}
|
||||||
const Type_handler *
|
const Type_handler *
|
||||||
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
|
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
|
||||||
CHARSET_INFO *cs) const
|
CHARSET_INFO *cs) const
|
||||||
@ -349,4 +416,18 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This class is used for Item_type_holder, which preserves real_type.
|
||||||
|
*/
|
||||||
|
class Type_handler_hybrid_real_field_type:
|
||||||
|
public Type_handler_hybrid_field_type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Type_handler_hybrid_real_field_type(enum_field_types type)
|
||||||
|
:Type_handler_hybrid_field_type(get_handler_by_real_type(type))
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* SQL_TYPE_H_INCLUDED */
|
#endif /* SQL_TYPE_H_INCLUDED */
|
||||||
|
@ -534,7 +534,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
while ((type= tp++))
|
while ((type= tp++))
|
||||||
{
|
{
|
||||||
if (type->result_type() == STRING_RESULT &&
|
if (type->cmp_type() == STRING_RESULT &&
|
||||||
type->collation.derivation == DERIVATION_NONE)
|
type->collation.derivation == DERIVATION_NONE)
|
||||||
{
|
{
|
||||||
my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
|
my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
|
||||||
|
Reference in New Issue
Block a user