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):
|
||||
Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
|
||||
Item_basic_value(thd),
|
||||
Rewritable_query_parameter(pos_in_query_arg, 1),
|
||||
Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
|
||||
state(NO_VALUE),
|
||||
/* Don't pretend to be a literal unless value for this item is set. */
|
||||
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(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);
|
||||
maybe_null= item->maybe_null;
|
||||
collation.set(item->collation);
|
||||
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 */
|
||||
if (Field::result_merge_type(fld_type) == INT_RESULT)
|
||||
if (Field::result_merge_type(real_field_type()) == INT_RESULT)
|
||||
decimals= 0;
|
||||
prev_decimal_int_part= item->decimal_int_part();
|
||||
#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.
|
||||
|
||||
@ -9268,7 +9269,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
|
||||
*/
|
||||
switch (item->result_type()) {
|
||||
case STRING_RESULT:
|
||||
return MYSQL_TYPE_VAR_STRING;
|
||||
return MYSQL_TYPE_VARCHAR;
|
||||
case INT_RESULT:
|
||||
return MYSQL_TYPE_LONGLONG;
|
||||
case REAL_RESULT:
|
||||
@ -9278,10 +9279,21 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
|
||||
case ROW_RESULT:
|
||||
case TIME_RESULT:
|
||||
DBUG_ASSERT(0);
|
||||
return MYSQL_TYPE_VAR_STRING;
|
||||
return MYSQL_TYPE_VARCHAR;
|
||||
}
|
||||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
@ -9307,25 +9319,26 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
uint decimals_orig= decimals;
|
||||
DBUG_ENTER("Item_type_holder::join_types");
|
||||
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>")));
|
||||
DBUG_PRINT("info:", ("in type %d len %d, dec %d",
|
||||
get_real_type(item),
|
||||
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;
|
||||
/* 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;
|
||||
decimals= MY_MAX(decimals, item_decimals);
|
||||
}
|
||||
|
||||
if (fld_type == FIELD_TYPE_GEOMETRY)
|
||||
if (Item_type_holder::field_type() == FIELD_TYPE_GEOMETRY)
|
||||
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);
|
||||
int item_int_part= item->decimal_int_part();
|
||||
@ -9337,7 +9350,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
unsigned_flag);
|
||||
}
|
||||
|
||||
switch (Field::result_merge_type(fld_type))
|
||||
switch (Field::result_merge_type(real_field_type()))
|
||||
{
|
||||
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 delta2= item->max_length - item->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;
|
||||
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;
|
||||
decimals= NOT_FIXED_DEC;
|
||||
@ -9397,7 +9412,8 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
prev_decimal_int_part= decimal_int_part();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -9490,7 +9506,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
|
||||
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
|
||||
Field *field;
|
||||
|
||||
switch (fld_type) {
|
||||
switch (Item_type_holder::real_field_type()) {
|
||||
case MYSQL_TYPE_ENUM:
|
||||
DBUG_ASSERT(enum_set_typelib);
|
||||
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)
|
||||
{
|
||||
if (fld_type == MYSQL_TYPE_ENUM ||
|
||||
fld_type == MYSQL_TYPE_SET)
|
||||
if (Item_type_holder::real_field_type() == MYSQL_TYPE_ENUM ||
|
||||
Item_type_holder::real_field_type() == MYSQL_TYPE_SET)
|
||||
{
|
||||
if (item->type() == Item::SUM_FUNC_ITEM &&
|
||||
(((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
|
||||
single SP/PS execution.
|
||||
*/
|
||||
class Item_type_holder: public Item
|
||||
class Item_type_holder: public Item,
|
||||
public Type_handler_hybrid_real_field_type
|
||||
{
|
||||
protected:
|
||||
TYPELIB *enum_set_typelib;
|
||||
enum_field_types fld_type;
|
||||
Field::geometry_type geometry_type;
|
||||
|
||||
void get_full_info(Item *item);
|
||||
@ -5279,8 +5279,27 @@ protected:
|
||||
public:
|
||||
Item_type_holder(THD*, Item*);
|
||||
|
||||
Item_result result_type() const;
|
||||
enum_field_types field_type() const { return fld_type; };
|
||||
enum_field_types field_type() const
|
||||
{ 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; }
|
||||
double val_real();
|
||||
longlong val_int();
|
||||
|
@ -27,9 +27,13 @@ static Type_handler_bit type_handler_bit;
|
||||
static Type_handler_float type_handler_float;
|
||||
static Type_handler_double type_handler_double;
|
||||
static Type_handler_time type_handler_time;
|
||||
static Type_handler_time2 type_handler_time2;
|
||||
static Type_handler_date type_handler_date;
|
||||
static Type_handler_newdate type_handler_newdate;
|
||||
static Type_handler_datetime type_handler_datetime;
|
||||
static Type_handler_datetime2 type_handler_datetime2;
|
||||
static Type_handler_timestamp type_handler_timestamp;
|
||||
static Type_handler_timestamp2 type_handler_timestamp2;
|
||||
static Type_handler_olddecimal type_handler_olddecimal;
|
||||
static Type_handler_newdecimal type_handler_newdecimal;
|
||||
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_long_blob type_handler_long_blob;
|
||||
static Type_handler_blob type_handler_blob;
|
||||
#ifdef HAVE_SPATIAL
|
||||
static Type_handler_geometry type_handler_geometry;
|
||||
#endif
|
||||
static Type_handler_enum type_handler_enum;
|
||||
static Type_handler_set type_handler_set;
|
||||
|
||||
|
||||
/**
|
||||
@ -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_ENUM: 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_TIMESTAMP: return &type_handler_timestamp;
|
||||
case MYSQL_TYPE_TIMESTAMP2: return &type_handler_timestamp;
|
||||
case MYSQL_TYPE_DATE: return &type_handler_date;
|
||||
case MYSQL_TYPE_TIME: return &type_handler_time;
|
||||
case MYSQL_TYPE_TIME2: return &type_handler_time;
|
||||
case MYSQL_TYPE_DATETIME: return &type_handler_datetime;
|
||||
case MYSQL_TYPE_DATETIME2: return &type_handler_datetime;
|
||||
case MYSQL_TYPE_NEWDATE: return &type_handler_date;
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
#ifdef HAVE_SPATIAL
|
||||
return &type_handler_geometry;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
case MYSQL_TYPE_TIMESTAMP: return &type_handler_timestamp2;// Map to timestamp2
|
||||
case MYSQL_TYPE_TIMESTAMP2: return &type_handler_timestamp2;
|
||||
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);
|
||||
return &type_handler_string;
|
||||
|
@ -29,7 +29,9 @@ protected:
|
||||
const Type_handler *string_type_handler(uint max_octet_length) const;
|
||||
public:
|
||||
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 real_field_type() const { return field_type(); }
|
||||
virtual Item_result result_type() const= 0;
|
||||
virtual Item_result cmp_type() const= 0;
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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.
|
||||
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;
|
||||
public:
|
||||
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)
|
||||
:m_type_handler(get_handler_by_field_type(type))
|
||||
{ }
|
||||
@ -316,6 +375,10 @@ public:
|
||||
:m_type_handler(other->m_type_handler)
|
||||
{ }
|
||||
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 cmp_type() const { return m_type_handler->cmp_type(); }
|
||||
void set_handler(const Type_handler *other)
|
||||
@ -339,6 +402,10 @@ public:
|
||||
{
|
||||
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 *
|
||||
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
|
||||
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 */
|
||||
|
@ -534,7 +534,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
||||
|
||||
while ((type= tp++))
|
||||
{
|
||||
if (type->result_type() == STRING_RESULT &&
|
||||
if (type->cmp_type() == STRING_RESULT &&
|
||||
type->collation.derivation == DERIVATION_NONE)
|
||||
{
|
||||
my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
|
||||
|
Reference in New Issue
Block a user