1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-11357 Split Item_cache::get_cache() into virtual methods in Type_handler

This patch:
- Adds a new virtual method Type_handler::Item_get_cache
- Splits moves Item_cache::get_cache() into the new method, every
  "case XXX_RESULT" to the corresponding Type_handler_xxx::Item_get_cache.
- Adds Item::get_cache as a convenience wrapper, to make the caller code
  shorter.
- Changes the last argument of Arg_comparator::cache_converted_constant()
  from Item_result to "const Type_handler *".
- Removes subselect_engine::cmp_type, subselect_engine::res_type,
  subselect_engine::res_field_type and derives subselect_engine
  from Type_handler_hybrid_field_type instead.
- Makes Type_handler_varchar public, as it's now needed as the
  default data type handler for subselect_engine.
This commit is contained in:
Alexander Barkov
2016-11-26 21:19:48 +04:00
parent 352ff9cc96
commit 749bbb3d7b
13 changed files with 100 additions and 84 deletions

View File

@ -6936,7 +6936,7 @@ Item* Item::cache_const_expr_transformer(THD *thd, uchar *arg)
if (*(bool*)arg)
{
*((bool*)arg)= FALSE;
Item_cache *cache= Item_cache::get_cache(thd, this);
Item_cache *cache= get_cache(thd);
if (!cache)
return NULL;
cache->setup(thd, this);
@ -7976,7 +7976,7 @@ Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg):
name_length= item_arg->name_length;
with_subselect= orig_item->with_subselect;
if ((expr_value= Item_cache::get_cache(thd, orig_item)))
if ((expr_value= orig_item->get_cache(thd)))
expr_value->setup(thd, orig_item);
fixed= 1;
@ -9281,41 +9281,6 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
return 0;
}
Item_cache* Item_cache::get_cache(THD *thd, const Item *item)
{
return get_cache(thd, item, item->cmp_type());
}
/**
Get a cache item of given type.
@param item value to be cached
@param type required type of cache
@return cache item
*/
Item_cache* Item_cache::get_cache(THD *thd, const Item *item,
const Item_result type)
{
MEM_ROOT *mem_root= thd->mem_root;
switch (type) {
case INT_RESULT:
return new (mem_root) Item_cache_int(thd, item->field_type());
case REAL_RESULT:
return new (mem_root) Item_cache_real(thd);
case DECIMAL_RESULT:
return new (mem_root) Item_cache_decimal(thd);
case STRING_RESULT:
return new (mem_root) Item_cache_str(thd, item);
case ROW_RESULT:
return new (mem_root) Item_cache_row(thd);
case TIME_RESULT:
return new (mem_root) Item_cache_temporal(thd, item->field_type());
}
return 0; // Impossible
}
void Item_cache::store(Item *item)
{
@ -9829,7 +9794,7 @@ bool Item_cache_row::setup(THD *thd, Item *item)
{
Item *el= item->element_index(i);
Item_cache *tmp;
if (!(tmp= values[i]= Item_cache::get_cache(thd, el)))
if (!(tmp= values[i]= el->get_cache(thd)))
return 1;
tmp->setup(thd, el);
}

View File

@ -721,6 +721,10 @@ public:
{
return Type_handler::string_type_handler(max_length)->field_type();
}
Item_cache* get_cache(THD *thd) const
{
return type_handler()->Item_get_cache(thd, this);
}
virtual enum Type type() const =0;
/*
real_type() is the type of base item. This is same as type() for
@ -5207,8 +5211,6 @@ public:
enum Item_result cmp_type () const
{ return Type_handler_hybrid_field_type::cmp_type(); }
static Item_cache* get_cache(THD *thd, const Item *item);
static Item_cache* get_cache(THD *thd, const Item* item, const Item_result type);
virtual void keep_array() {}
virtual void print(String *str, enum_query_type query_type);
bool eq_def(const Field *field)

View File

@ -598,8 +598,8 @@ bool Arg_comparator::set_cmp_func_string()
if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b))
return true;
}
a= cache_converted_constant(thd, a, &a_cache, compare_type());
b= cache_converted_constant(thd, b, &b_cache, compare_type());
a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
return false;
}
@ -646,8 +646,8 @@ bool Arg_comparator::set_cmp_func_int()
if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
func= &Arg_comparator::compare_e_int_diff_signedness;
}
a= cache_converted_constant(thd, a, &a_cache, compare_type());
b= cache_converted_constant(thd, b, &b_cache, compare_type());
a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
return false;
}
@ -664,8 +664,8 @@ bool Arg_comparator::set_cmp_func_real()
else if (func == &Arg_comparator::compare_e_real)
func= &Arg_comparator::compare_e_real_fixed;
}
a= cache_converted_constant(thd, a, &a_cache, compare_type());
b= cache_converted_constant(thd, b, &b_cache, compare_type());
a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
return false;
}
@ -674,8 +674,8 @@ bool Arg_comparator::set_cmp_func_decimal()
{
func= is_owner_equal_func() ? &Arg_comparator::compare_e_decimal :
&Arg_comparator::compare_decimal;
a= cache_converted_constant(thd, a, &a_cache, compare_type());
b= cache_converted_constant(thd, b, &b_cache, compare_type());
a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
return false;
}
@ -699,18 +699,22 @@ bool Arg_comparator::set_cmp_func_decimal()
Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
Item **cache_item,
Item_result type)
const Type_handler *handler)
{
/*
get_datetime_value creates Item_cache internally when comparing
values for the first row.
Arg_comparator::cache_converted_constant() is never called for TIME_RESULT.
*/
DBUG_ASSERT(handler->cmp_type() != TIME_RESULT);
/*
Don't need cache if doing context analysis only.
Also, get_datetime_value creates Item_cache internally.
Unless fixed, we should not do it here.
*/
if (!thd_arg->lex->is_ps_or_view_context_analysis() &&
(*value)->const_item() && type != (*value)->result_type() &&
type != TIME_RESULT)
(*value)->const_item() &&
handler->cmp_type() != (*value)->cmp_type())
{
Item_cache *cache= Item_cache::get_cache(thd_arg, *value, type);
Item_cache *cache= handler->Item_get_cache(thd_arg, *value);
cache->setup(thd_arg, *value);
*cache_item= cache;
return cache_item;
@ -1273,7 +1277,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
args[0]= ((Item_in_subselect *)args[1])->left_expr;
}
if ((!(*ref0)->fixed && (*ref0)->fix_fields(thd, ref0)) ||
(!cache && !(cache= Item_cache::get_cache(thd, *ref0))))
(!cache && !(cache= (*ref0)->get_cache(thd))))
DBUG_RETURN(1);
/*
During fix_field() expression could be substituted.
@ -2696,7 +2700,7 @@ Item_func_nullif::fix_length_and_dec()
*/
m_cache= args[0]->cmp_type() == STRING_RESULT ?
new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) :
Item_cache::get_cache(thd, args[0]);
args[0]->get_cache(thd);
m_cache->setup(thd, args[0]);
m_cache->store(args[0]);
m_cache->set_used_tables(args[0]->used_tables());

View File

@ -118,7 +118,7 @@ public:
int compare_e_time() { return compare_e_temporal(MYSQL_TYPE_TIME); }
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
Item_result type);
const Type_handler *type);
inline bool is_owner_equal_func()
{
return (owner->type() == Item::FUNC_ITEM &&

View File

@ -1057,7 +1057,7 @@ void Item_maxmin_subselect::no_rows_in_result()
*/
if (parsing_place != SELECT_LIST || const_item())
return;
value= Item_cache::get_cache(thd, new (thd->mem_root) Item_null(thd));
value= (new (thd->mem_root) Item_null(thd))->get_cache(thd);
null_value= 0;
was_values= 0;
make_const();
@ -1075,7 +1075,7 @@ void Item_singlerow_subselect::no_rows_in_result()
*/
if (parsing_place != SELECT_LIST || const_item())
return;
value= Item_cache::get_cache(thd, new (thd->mem_root) Item_null(thd));
value= (new (thd->mem_root) Item_null(thd))->get_cache(thd);
reset();
make_const();
}
@ -1165,12 +1165,17 @@ void Item_singlerow_subselect::store(uint i, Item *item)
enum Item_result Item_singlerow_subselect::result_type() const
{
return engine->type();
return engine->result_type();
}
enum Item_result Item_singlerow_subselect::cmp_type() const
{
return engine->cmptype();
return engine->cmp_type();
}
const Type_handler *Item_singlerow_subselect::type_handler() const
{
return engine->type_handler();
}
/*
@ -3635,24 +3640,21 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
Item *sel_item;
List_iterator_fast<Item> li(item_list);
cmp_type= res_type= STRING_RESULT;
res_field_type= MYSQL_TYPE_VAR_STRING;
set_handler(&type_handler_varchar);
for (uint i= 0; (sel_item= li++); i++)
{
item->max_length= sel_item->max_length;
res_type= sel_item->result_type();
cmp_type= sel_item->cmp_type();
res_field_type= sel_item->field_type();
set_handler(sel_item->type_handler());
item->decimals= sel_item->decimals;
item->unsigned_flag= sel_item->unsigned_flag;
maybe_null= sel_item->maybe_null;
if (!(row[i]= Item_cache::get_cache(thd, sel_item, sel_item->cmp_type())))
if (!(row[i]= sel_item->get_cache(thd)))
return;
row[i]->setup(thd, sel_item);
//psergey-backport-timours: row[i]->store(sel_item);
}
if (item_list.elements > 1)
cmp_type= res_type= ROW_RESULT;
set_handler(&type_handler_row);
}
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)

View File

@ -301,6 +301,7 @@ public:
enum Item_result result_type() const;
enum Item_result cmp_type() const;
enum_field_types field_type() const;
const Type_handler *type_handler() const;
void fix_length_and_dec();
uint cols();
@ -747,15 +748,13 @@ public:
};
class subselect_engine: public Sql_alloc
class subselect_engine: public Sql_alloc,
public Type_handler_hybrid_field_type
{
protected:
select_result_interceptor *result; /* results storage class */
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
enum Item_result res_type; /* type of results */
enum Item_result cmp_type; /* how to compare the results */
enum_field_types res_field_type; /* column type of the results */
bool maybe_null; /* may be null (first item in select) */
public:
@ -766,12 +765,11 @@ public:
subselect_engine(Item_subselect *si,
select_result_interceptor *res):
Type_handler_hybrid_field_type(&type_handler_varchar),
thd(NULL)
{
result= res;
item= si;
cmp_type= res_type= STRING_RESULT;
res_field_type= MYSQL_TYPE_VAR_STRING;
maybe_null= 0;
}
virtual ~subselect_engine() {}; // to satisfy compiler
@ -808,9 +806,6 @@ public:
virtual int exec()= 0;
virtual uint cols()= 0; /* return number of columns in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */
enum Item_result type() { return res_type; }
enum Item_result cmptype() { return cmp_type; }
enum_field_types field_type() { return res_field_type; }
virtual void exclude()= 0;
virtual bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0;

View File

@ -1185,14 +1185,14 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
void Item_sum_hybrid::setup_hybrid(THD *thd, Item *item, Item *value_arg)
{
if (!(value= Item_cache::get_cache(thd, item, item->cmp_type())))
if (!(value= item->get_cache(thd)))
return;
value->setup(thd, item);
value->store(value_arg);
/* Don't cache value, as it will change */
if (!item->const_item())
value->set_used_tables(RAND_TABLE_BIT);
if (!(arg_cache= Item_cache::get_cache(thd, item, item->cmp_type())))
if (!(arg_cache= item->get_cache(thd)))
return;
arg_cache->setup(thd, item);
/* Don't cache value, as it will change */

View File

@ -301,7 +301,7 @@ bool Item_sum_hybrid_simple::add()
void Item_sum_hybrid_simple::setup_hybrid(THD *thd, Item *item)
{
if (!(value= Item_cache::get_cache(thd, item, item->cmp_type())))
if (!(value= item->get_cache(thd)))
return;
value->setup(thd, item);
value->store(item);

View File

@ -5228,7 +5228,7 @@ int select_value_catcher::setup(List<Item> *items)
List_iterator<Item> li(*items);
for (uint i= 0; (sel_item= li++); i++)
{
if (!(row[i]= Item_cache::get_cache(thd, sel_item)))
if (!(row[i]= sel_item->get_cache(thd)))
return TRUE;
row[i]->setup(thd, sel_item);
}

View File

@ -387,7 +387,7 @@ Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
thd->set_n_backup_active_arena(thd->spcont->callers_arena, &current_arena);
holder= Item_cache::get_cache(thd, item);
holder= item->get_cache(thd);
thd->restore_active_arena(thd->spcont->callers_arena, &current_arena);

View File

@ -3336,7 +3336,7 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
{
if (!cache)
{
cache= Item_cache::get_cache(thd, val_item);
cache= val_item->get_cache(thd);
switch (val_item->result_type()) {
case REAL_RESULT:
op= &select_max_min_finder_subselect::cmp_real;

View File

@ -40,7 +40,6 @@ static Type_handler_timestamp2 type_handler_timestamp2;
static Type_handler_olddecimal type_handler_olddecimal;
static Type_handler_newdecimal type_handler_newdecimal;
static Type_handler_string type_handler_string;
static Type_handler_varchar type_handler_varchar;
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;
@ -54,6 +53,7 @@ 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;
/**
@ -722,3 +722,42 @@ bool Type_handler_temporal_result::set_comparator_func(Arg_comparator *cmp) cons
/*************************************************************************/
Item_cache *
Type_handler_row::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_row(thd);
}
Item_cache *
Type_handler_int_result::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_int(thd, item->field_type());
}
Item_cache *
Type_handler_real_result::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_real(thd);
}
Item_cache *
Type_handler_decimal_result::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_decimal(thd);
}
Item_cache *
Type_handler_string_result::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_str(thd, item);
}
Item_cache *
Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_temporal(thd, item->field_type());
}
/*************************************************************************/

View File

@ -25,6 +25,7 @@
class Field;
class Item;
class Item_cache;
class Type_std_attributes;
class Sort_param;
class Arg_comparator;
@ -286,6 +287,7 @@ public:
virtual int Item_save_in_field(Item *item, Field *field,
bool no_conversions) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
};
@ -338,6 +340,7 @@ public:
DBUG_ASSERT(0);
return 1;
}
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
};
@ -356,6 +359,7 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
};
@ -373,6 +377,7 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
};
@ -390,6 +395,7 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
};
@ -405,6 +411,7 @@ public:
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
};
@ -424,6 +431,7 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
};
@ -836,5 +844,6 @@ public:
extern Type_handler_row type_handler_row;
extern Type_handler_null type_handler_null;
extern Type_handler_varchar type_handler_varchar;
#endif /* SQL_TYPE_H_INCLUDED */