Skip to content

Commit

Permalink
MDEV-11357 Split Item_cache::get_cache() into virtual methods in Type…
Browse files Browse the repository at this point in the history
…_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.
  • Loading branch information
Alexander Barkov committed Dec 6, 2016
1 parent 7ae95bd commit 81f448c
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 84 deletions.
41 changes: 3 additions & 38 deletions sql/item.cc
Expand Up @@ -6882,7 +6882,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);
Expand Down Expand Up @@ -7922,7 +7922,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;
Expand Down Expand Up @@ -9227,41 +9227,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)
{
Expand Down Expand Up @@ -9702,7 +9667,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);
}
Expand Down
6 changes: 4 additions & 2 deletions sql/item.h
Expand Up @@ -697,6 +697,10 @@ class Item: public Value_source,
{
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
Expand Down Expand Up @@ -5241,8 +5245,6 @@ class Item_cache: public Item_basic_constant,
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)
Expand Down
36 changes: 20 additions & 16 deletions sql/item_cmpfunc.cc
Expand Up @@ -608,8 +608,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;
}

Expand Down Expand Up @@ -656,8 +656,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;
}

Expand All @@ -674,8 +674,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;
}

Expand All @@ -684,8 +684,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;
}

Expand All @@ -709,18 +709,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;
Expand Down Expand Up @@ -1285,7 +1289,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.
Expand Down Expand Up @@ -2710,7 +2714,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());
Expand Down
2 changes: 1 addition & 1 deletion sql/item_cmpfunc.h
Expand Up @@ -118,7 +118,7 @@ class Arg_comparator: public Sql_alloc
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 &&
Expand Down
24 changes: 13 additions & 11 deletions sql/item_subselect.cc
Expand Up @@ -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();
Expand All @@ -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();
}
Expand Down Expand Up @@ -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();
}

/*
Expand Down Expand Up @@ -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)
Expand Down
13 changes: 4 additions & 9 deletions sql/item_subselect.h
Expand Up @@ -301,6 +301,7 @@ class Item_singlerow_subselect :public Item_subselect
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();
Expand Down Expand Up @@ -747,15 +748,13 @@ class Item_allany_subselect :public Item_in_subselect
};


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:

Expand All @@ -766,12 +765,11 @@ class subselect_engine: public Sql_alloc

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
Expand Down Expand Up @@ -808,9 +806,6 @@ class subselect_engine: public Sql_alloc
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;
Expand Down
4 changes: 2 additions & 2 deletions sql/item_sum.cc
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion sql/item_windowfunc.cc
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion sql/opt_subselect.cc
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion sql/sp_rcontext.cc
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion sql/sql_class.cc
Expand Up @@ -3514,7 +3514,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;
Expand Down

0 comments on commit 81f448c

Please sign in to comment.