MDEV-12338 Split Item_type_holder::get_real_type() into virtual Item::real_type_handler()
This commit is contained in:
parent
1b3bd00c6b
commit
48c59f394b
134
sql/item.cc
134
sql/item.cc
@ -5670,6 +5670,25 @@ error:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Item_field::real_type_handler() const
|
||||
{
|
||||
/*
|
||||
Item_field::field_type ask Field_type() but sometimes field return
|
||||
a different type, like for enum/set, so we need to ask real type.
|
||||
*/
|
||||
if (field->is_created_from_null_item)
|
||||
return &type_handler_null;
|
||||
/* work around about varchar type field detection */
|
||||
enum_field_types type= field->real_type();
|
||||
// TODO: We should add Field::real_type_handler() eventually
|
||||
if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
|
||||
type= MYSQL_TYPE_VAR_STRING;
|
||||
return Type_handler::get_handler_by_real_type(type);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Mark virtual columns as used in a partitioning expression
|
||||
@ -10009,7 +10028,7 @@ void Item_cache_row::set_null()
|
||||
|
||||
Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
||||
:Item(thd, item),
|
||||
Type_handler_hybrid_real_field_type(get_real_type(item)),
|
||||
Type_handler_hybrid_field_type(item->real_type_handler()),
|
||||
enum_set_typelib(0)
|
||||
{
|
||||
DBUG_ASSERT(item->fixed);
|
||||
@ -10024,87 +10043,6 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find real field type of item.
|
||||
|
||||
@return
|
||||
type of field which should be created to store item value
|
||||
*/
|
||||
|
||||
enum_field_types Item_type_holder::get_real_type(Item *item)
|
||||
{
|
||||
if (item->type() == REF_ITEM)
|
||||
item= item->real_item();
|
||||
switch(item->type())
|
||||
{
|
||||
case FIELD_ITEM:
|
||||
{
|
||||
/*
|
||||
Item_field::field_type ask Field_type() but sometimes field return
|
||||
a different type, like for enum/set, so we need to ask real type.
|
||||
*/
|
||||
Field *field= ((Item_field *) item)->field;
|
||||
enum_field_types type= field->real_type();
|
||||
if (field->is_created_from_null_item)
|
||||
return MYSQL_TYPE_NULL;
|
||||
/* work around about varchar type field detection */
|
||||
if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
|
||||
return MYSQL_TYPE_VAR_STRING;
|
||||
return type;
|
||||
}
|
||||
case SUM_FUNC_ITEM:
|
||||
{
|
||||
/*
|
||||
Argument of aggregate function sometimes should be asked about field
|
||||
type
|
||||
*/
|
||||
Item_sum *item_sum= (Item_sum *) item;
|
||||
if (item_sum->keep_field_type())
|
||||
return get_real_type(item_sum->get_arg(0));
|
||||
break;
|
||||
}
|
||||
case FUNC_ITEM:
|
||||
if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
|
||||
{
|
||||
/*
|
||||
There are work around of problem with changing variable type on the
|
||||
fly and variable always report "string" as field type to get
|
||||
acceptable information for client in send_field, so we make field
|
||||
type from expression type.
|
||||
*/
|
||||
switch (item->result_type()) {
|
||||
case STRING_RESULT:
|
||||
return MYSQL_TYPE_VARCHAR;
|
||||
case INT_RESULT:
|
||||
return MYSQL_TYPE_LONGLONG;
|
||||
case REAL_RESULT:
|
||||
return MYSQL_TYPE_DOUBLE;
|
||||
case DECIMAL_RESULT:
|
||||
return MYSQL_TYPE_NEWDECIMAL;
|
||||
case ROW_RESULT:
|
||||
case TIME_RESULT:
|
||||
DBUG_ASSERT(0);
|
||||
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;
|
||||
}
|
||||
return item->field_type();
|
||||
}
|
||||
|
||||
/**
|
||||
Find field type which can carry current Item_type_holder type and
|
||||
type of given Item.
|
||||
@ -10123,14 +10061,13 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
uint max_length_orig= max_length;
|
||||
uint decimals_orig= decimals;
|
||||
DBUG_ENTER("Item_type_holder::join_types");
|
||||
DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s",
|
||||
real_field_type(), max_length, decimals,
|
||||
DBUG_PRINT("info:", ("was type %s len %d, dec %d name %s",
|
||||
real_type_handler()->name().ptr(), max_length, decimals,
|
||||
(name ? name : "<NULL>")));
|
||||
DBUG_PRINT("info:", ("in type %d len %d, dec %d",
|
||||
get_real_type(item),
|
||||
DBUG_PRINT("info:", ("in type %s len %d, dec %d",
|
||||
item->real_type_handler()->name().ptr(),
|
||||
item->max_length, item->decimals));
|
||||
const Type_handler *item_type_handler=
|
||||
Type_handler::get_handler_by_real_type(get_real_type(item));
|
||||
const Type_handler *item_type_handler= item->real_type_handler();
|
||||
if (aggregate_for_result(item_type_handler))
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||
@ -10218,13 +10155,13 @@ 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 (Item_type_holder::real_field_type() == MYSQL_TYPE_FLOAT &&
|
||||
if (Item_type_holder::real_type_handler() == &type_handler_float &&
|
||||
max_length > FLT_DIG + 2)
|
||||
{
|
||||
max_length= MAX_FLOAT_STR_LENGTH;
|
||||
decimals= NOT_FIXED_DEC;
|
||||
}
|
||||
else if (Item_type_holder::real_field_type() == MYSQL_TYPE_DOUBLE &&
|
||||
else if (Item_type_holder::real_type_handler() == &type_handler_double &&
|
||||
max_length > DBL_DIG + 2)
|
||||
{
|
||||
max_length= MAX_DOUBLE_STR_LENGTH;
|
||||
@ -10245,8 +10182,9 @@ 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) real_field_type(), max_length, (uint) decimals));
|
||||
DBUG_PRINT("info", ("become type: %s len: %u dec: %u",
|
||||
real_type_handler()->name().ptr(),
|
||||
max_length, (uint) decimals));
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
@ -10269,7 +10207,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
|
||||
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
|
||||
Field *field;
|
||||
|
||||
switch (Item_type_holder::real_field_type()) {
|
||||
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,
|
||||
@ -10305,8 +10243,8 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
|
||||
*/
|
||||
void Item_type_holder::get_full_info(Item *item)
|
||||
{
|
||||
if (Item_type_holder::real_field_type() == MYSQL_TYPE_ENUM ||
|
||||
Item_type_holder::real_field_type() == MYSQL_TYPE_SET)
|
||||
if (Item_type_holder::real_type_handler() == &type_handler_enum ||
|
||||
Item_type_holder::real_type_handler() == &type_handler_set)
|
||||
{
|
||||
if (item->type() == Item::SUM_FUNC_ITEM &&
|
||||
(((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
|
||||
@ -10317,11 +10255,11 @@ void Item_type_holder::get_full_info(Item *item)
|
||||
field (or MIN|MAX(enum|set field)) and number of NULL fields
|
||||
*/
|
||||
DBUG_ASSERT((enum_set_typelib &&
|
||||
get_real_type(item) == MYSQL_TYPE_NULL) ||
|
||||
item->real_type_handler() == &type_handler_null) ||
|
||||
(!enum_set_typelib &&
|
||||
item->real_item()->type() == Item::FIELD_ITEM &&
|
||||
(get_real_type(item->real_item()) == MYSQL_TYPE_ENUM ||
|
||||
get_real_type(item->real_item()) == MYSQL_TYPE_SET) &&
|
||||
(item->real_type_handler() == &type_handler_enum ||
|
||||
item->real_type_handler() == &type_handler_set) &&
|
||||
((Field_enum*)((Item_field *) item->real_item())->field)->typelib));
|
||||
if (!enum_set_typelib)
|
||||
{
|
||||
|
28
sql/item.h
28
sql/item.h
@ -699,6 +699,10 @@ public:
|
||||
{
|
||||
return Type_handler::get_handler_by_field_type(field_type());
|
||||
}
|
||||
virtual const Type_handler *real_type_handler() const
|
||||
{
|
||||
return type_handler();
|
||||
}
|
||||
virtual const Type_handler *cast_to_int_type_handler() const
|
||||
{
|
||||
return type_handler();
|
||||
@ -2409,6 +2413,7 @@ public:
|
||||
{
|
||||
return field->type();
|
||||
}
|
||||
const Type_handler *real_type_handler() const;
|
||||
enum_monotonicity_info get_monotonicity_info() const
|
||||
{
|
||||
return MONOTONIC_STRICT_INCREASING;
|
||||
@ -3355,6 +3360,12 @@ public:
|
||||
{ max_length= length; }
|
||||
enum Type type() const { return TYPE_HOLDER; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
||||
const Type_handler *real_type_handler() const
|
||||
{
|
||||
// Should not be called, Item_blob is used for SHOW purposes only.
|
||||
DBUG_ASSERT(0);
|
||||
return &type_handler_varchar;
|
||||
}
|
||||
Field *create_field_for_schema(THD *thd, TABLE *table)
|
||||
{ return tmp_table_field_from_field_type(table, false, true); }
|
||||
};
|
||||
@ -4072,6 +4083,8 @@ public:
|
||||
{ return (*ref)->setup_fast_field_copier(field); }
|
||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||
enum_field_types field_type() const { return (*ref)->field_type(); }
|
||||
const Type_handler *real_type_handler() const
|
||||
{ return (*ref)->real_type_handler(); }
|
||||
Field *get_tmp_table_field()
|
||||
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
|
||||
Item *get_tmp_table_item(THD *thd);
|
||||
@ -5602,7 +5615,7 @@ public:
|
||||
single SP/PS execution.
|
||||
*/
|
||||
class Item_type_holder: public Item,
|
||||
public Type_handler_hybrid_real_field_type
|
||||
public Type_handler_hybrid_field_type
|
||||
{
|
||||
protected:
|
||||
TYPELIB *enum_set_typelib;
|
||||
@ -5616,11 +5629,11 @@ public:
|
||||
Item_type_holder(THD*, Item*);
|
||||
|
||||
const Type_handler *type_handler() const
|
||||
{ return Type_handler_hybrid_real_field_type::type_handler(); }
|
||||
{ return Type_handler_hybrid_field_type::type_handler(); }
|
||||
enum_field_types field_type() const
|
||||
{ return Type_handler_hybrid_real_field_type::field_type(); }
|
||||
{ return Type_handler_hybrid_field_type::field_type(); }
|
||||
enum_field_types real_field_type() const
|
||||
{ return Type_handler_hybrid_real_field_type::real_field_type(); }
|
||||
{ return Type_handler_hybrid_field_type::real_field_type(); }
|
||||
enum Item_result result_type () const
|
||||
{
|
||||
/*
|
||||
@ -5635,7 +5648,11 @@ public:
|
||||
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();
|
||||
return Type_handler_hybrid_field_type::result_type();
|
||||
}
|
||||
const Type_handler *real_type_handler() const
|
||||
{
|
||||
return Item_type_holder::type_handler();
|
||||
}
|
||||
|
||||
enum Type type() const { return TYPE_HOLDER; }
|
||||
@ -5645,7 +5662,6 @@ public:
|
||||
String *val_str(String*);
|
||||
bool join_types(THD *thd, Item *);
|
||||
Field *make_field_by_type(TABLE *table);
|
||||
static enum_field_types get_real_type(Item *);
|
||||
Field::geometry_type get_geometry_type() const { return geometry_type; };
|
||||
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
||||
};
|
||||
|
@ -456,7 +456,6 @@ public:
|
||||
Updated value is then saved in the field.
|
||||
*/
|
||||
virtual void update_field()=0;
|
||||
virtual bool keep_field_type(void) const { return 0; }
|
||||
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
|
||||
virtual Item *result_item(THD *thd, Field *field);
|
||||
|
||||
@ -520,7 +519,7 @@ public:
|
||||
st_select_lex *depended_from()
|
||||
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
|
||||
|
||||
Item *get_arg(uint i) { return args[i]; }
|
||||
Item *get_arg(uint i) const { return args[i]; }
|
||||
Item *set_arg(uint i, THD *thd, Item *new_val);
|
||||
uint get_arg_count() const { return arg_count; }
|
||||
|
||||
@ -1047,7 +1046,10 @@ protected:
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
void reset_field();
|
||||
String *val_str(String *);
|
||||
bool keep_field_type(void) const { return 1; }
|
||||
const Type_handler *real_type_handler() const
|
||||
{
|
||||
return get_arg(0)->real_type_handler();
|
||||
}
|
||||
const Type_handler *type_handler() const
|
||||
{ return Type_handler_hybrid_field_type::type_handler(); }
|
||||
enum Item_result result_type () const
|
||||
|
@ -303,8 +303,6 @@ class Item_sum_hybrid_simple : public Item_sum,
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
void reset_field();
|
||||
String *val_str(String *);
|
||||
/* TODO(cvicentiu) copied from Item_sum_hybrid, what does it do? */
|
||||
bool keep_field_type(void) const { return 1; }
|
||||
enum Item_result result_type() const
|
||||
{ return Type_handler_hybrid_field_type::result_type(); }
|
||||
enum Item_result cmp_type() const
|
||||
|
@ -25,7 +25,6 @@ static Type_handler_short type_handler_short;
|
||||
static Type_handler_long type_handler_long;
|
||||
static Type_handler_int24 type_handler_int24;
|
||||
static Type_handler_year type_handler_year;
|
||||
static Type_handler_float type_handler_float;
|
||||
static Type_handler_time type_handler_time;
|
||||
static Type_handler_time2 type_handler_time2;
|
||||
static Type_handler_date type_handler_date;
|
||||
@ -39,18 +38,19 @@ 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;
|
||||
static Type_handler_enum type_handler_enum;
|
||||
static Type_handler_set type_handler_set;
|
||||
|
||||
|
||||
Type_handler_null type_handler_null;
|
||||
Type_handler_row type_handler_row;
|
||||
Type_handler_varchar type_handler_varchar;
|
||||
Type_handler_longlong type_handler_longlong;
|
||||
Type_handler_float type_handler_float;
|
||||
Type_handler_double type_handler_double;
|
||||
Type_handler_newdecimal type_handler_newdecimal;
|
||||
Type_handler_datetime type_handler_datetime;
|
||||
Type_handler_bit type_handler_bit;
|
||||
Type_handler_enum type_handler_enum;
|
||||
Type_handler_set type_handler_set;
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Type_handler_geometry type_handler_geometry;
|
||||
|
@ -1450,29 +1450,19 @@ 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(Type_handler::
|
||||
get_handler_by_real_type(type))
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
extern Type_handler_row type_handler_row;
|
||||
extern Type_handler_null type_handler_null;
|
||||
extern Type_handler_varchar type_handler_varchar;
|
||||
extern Type_handler_longlong type_handler_longlong;
|
||||
extern Type_handler_float type_handler_float;
|
||||
extern Type_handler_double type_handler_double;
|
||||
extern Type_handler_newdecimal type_handler_newdecimal;
|
||||
extern Type_handler_datetime type_handler_datetime;
|
||||
extern Type_handler_longlong type_handler_longlong;
|
||||
extern Type_handler_bit type_handler_bit;
|
||||
extern Type_handler_enum type_handler_enum;
|
||||
extern Type_handler_set type_handler_set;
|
||||
|
||||
|
||||
class Type_aggregator
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user