Skip to content

Commit

Permalink
MDEV-12338 Split Item_type_holder::get_real_type() into virtual Item:…
Browse files Browse the repository at this point in the history
…:real_type_handler()
  • Loading branch information
Alexander Barkov committed Mar 24, 2017
1 parent 1b3bd00 commit 48c59f3
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 126 deletions.
134 changes: 36 additions & 98 deletions sql/item.cc
Expand Up @@ -5670,6 +5670,25 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
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
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand All @@ -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),
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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,
Expand Down Expand Up @@ -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 ||
Expand All @@ -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)
{
Expand Down
28 changes: 22 additions & 6 deletions sql/item.h
Expand Up @@ -699,6 +699,10 @@ class Item: public Value_source,
{
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();
Expand Down Expand Up @@ -2409,6 +2413,7 @@ class Item_field :public Item_ident
{
return field->type();
}
const Type_handler *real_type_handler() const;
enum_monotonicity_info get_monotonicity_info() const
{
return MONOTONIC_STRICT_INCREASING;
Expand Down Expand Up @@ -3355,6 +3360,12 @@ class Item_blob :public Item_partition_func_safe_string
{ 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); }
};
Expand Down Expand Up @@ -4072,6 +4083,8 @@ class Item_ref :public Item_ident
{ 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);
Expand Down Expand Up @@ -5602,7 +5615,7 @@ class Item_cache_row: public Item_cache
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;
Expand All @@ -5616,11 +5629,11 @@ class Item_type_holder: public Item,
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
{
/*
Expand All @@ -5635,7 +5648,11 @@ class Item_type_holder: public Item,
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; }
Expand All @@ -5645,7 +5662,6 @@ class Item_type_holder: public Item,
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; }
};
Expand Down
8 changes: 5 additions & 3 deletions sql/item_sum.h
Expand Up @@ -456,7 +456,6 @@ class Item_sum :public Item_func_or_sum
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);

Expand Down Expand Up @@ -520,7 +519,7 @@ class Item_sum :public Item_func_or_sum
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; }

Expand Down Expand Up @@ -1047,7 +1046,10 @@ class Item_sum_hybrid :public Item_sum, public Type_handler_hybrid_field_type
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
Expand Down
2 changes: 0 additions & 2 deletions sql/item_windowfunc.h
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions sql/sql_type.cc
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
18 changes: 4 additions & 14 deletions sql/sql_type.h
Expand Up @@ -1450,29 +1450,19 @@ class Type_handler_hybrid_field_type
};


/**
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
{
Expand Down

0 comments on commit 48c59f3

Please sign in to comment.