Skip to content
Permalink
Browse files
Memory allocation corrected. New tests added.
  • Loading branch information
Galina Shalygina committed Sep 1, 2017
1 parent 1efa9ed commit e701770
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 88 deletions.
@@ -468,5 +468,18 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `dr_table`.`max(a)` AS `max(a)`,`dr_table`.`b` AS `b` from (/* select#2 */ select max(`test`.`t1`.`a`) AS `max(a)`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(5)) `tvc_0`) where 1 group by `test`.`t1`.`b`) `dr_table`
# prepare statement
prepare stmt from "select * from t1 where a in (1,2)";
execute stmt;
a b
1 2
1 1
2 5
execute stmt;
a b
1 2
1 1
2 5
deallocate prepare stmt;
drop table t1, t2;
set @@in_subquery_conversion_threshold= default;
@@ -4330,9 +4330,16 @@ longlong Item_func_in::val_int()
void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
{
THD *thd= current_thd;

Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);

if (can_be_transformed_in_tvc(thd))
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);

if (arena)
thd->restore_active_arena(arena, &backup);

emb_on_expr_nest= embedding;
}

@@ -374,10 +374,10 @@ void table_value_constr::print(THD *thd_arg, String *str,

/**
@brief
Creates new SELECT defined by TVC as derived table
Transforms IN-predicate in IN-subselect
@param thd_arg The context of the statement
@param values List of values that defines TVC
@param arg Argument is 0 in this context
@details
The method creates this SELECT statement:
@@ -386,31 +386,64 @@ void table_value_constr::print(THD *thd_arg, String *str,
If during creation of SELECT statement some action is
unsuccesfull backup is made to the state in which system
was at the beginning of the method.
was at the beginning of the procedure.
@retval
pointer to the created SELECT statement
NULL - if creation was unsuccesfull
*/

st_select_lex *make_new_subselect_for_tvc(THD *thd_arg,
List<List_item> *values)
Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
uchar *arg)
{
LEX *lex= thd_arg->lex;
SELECT_LEX *old_select= thd->lex->current_select;

List<List_item> values;
Item *item;
SELECT_LEX *sel;
SELECT_LEX_UNIT *unit;
TABLE_LIST *new_tab;
Table_ident *ti;
Item_in_subselect *in_subs;

Query_arena backup;
Query_arena *arena= thd_arg->activate_stmt_arena_if_needed(&backup);
Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
LEX *lex= thd->lex;

char buff[6];
LEX_CSTRING alias;

/*
Creation of values list of lists
*/
bool list_of_lists= false;

if (args[1]->type() == Item::ROW_ITEM)
list_of_lists= true;

for (uint i=1; i < arg_count; i++)
{
List<Item> *new_value= new (thd->mem_root) List<Item>();

if (list_of_lists)
{
Item_row *in_list= (Item_row *)(args[i]);

for (uint j=0; j < in_list->cols(); i++)
new_value->push_back(in_list->element_index(j), thd->mem_root);
}
else
new_value->push_back(args[i]);

values.push_back(new_value, thd->mem_root);
}

/*
Creation of TVC name
*/
alias.length= my_snprintf(buff, sizeof(buff),
"tvc_%u", thd_arg->lex->current_select->cur_tvc);
alias.str= thd_arg->strmake(buff, alias.length);
"tvc_%u", old_select->cur_tvc);
alias.str= thd->strmake(buff, alias.length);
if (!alias.str)
goto err;

@@ -424,12 +457,11 @@ st_select_lex *make_new_subselect_for_tvc(THD *thd_arg,
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;

item= new (thd_arg->mem_root)
Item_field(thd_arg, &lex->current_select->context,
NULL, NULL, &star_clex_str);
item= new (thd->mem_root) Item_field(thd, &lex->current_select->context,
NULL, NULL, &star_clex_str);
if (item == NULL)
goto err;
if (add_item_to_list(thd_arg, item))
if (add_item_to_list(thd, item))
goto err;
(lex->current_select->with_wild)++;

@@ -448,20 +480,20 @@ st_select_lex *make_new_subselect_for_tvc(THD *thd_arg,
sel->linkage= DERIVED_TABLE_TYPE;

if (!(sel->tvc=
new (thd_arg->mem_root)
table_value_constr(*values,
new (thd->mem_root)
table_value_constr(values,
sel,
sel->options)))
goto err;

lex->check_automatic_up(UNSPECIFIED_TYPE);
lex->current_select= sel= unit->outer_select();

ti= new (thd_arg->mem_root) Table_ident(unit);
ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL)
goto err;

if (!(new_tab= sel->add_table_to_list(thd_arg,
if (!(new_tab= sel->add_table_to_list(thd,
ti, &alias, 0,
TL_READ, MDL_SHARED_READ)))
goto err;
@@ -478,83 +510,28 @@ st_select_lex *make_new_subselect_for_tvc(THD *thd_arg,
sel->set_braces(false);
unit->with_clause= 0;

return sel;

err:
if (arena)
thd_arg->restore_active_arena(arena, &backup);
return NULL;
}


/**
@brief
Transforms IN-predicate in IN-subselect
@param thd_arg The context of the statement
@param arg Argument is 0 in this context
@details
The method creates this SELECT statement:
SELECT * FROM (VALUES values) AS new_tvc
If during creation of SELECT statement some action is
unsuccesfull backup is made to the state in which system
was at the beginning of the procedure.
@retval
pointer to the created SELECT statement
NULL - if creation was unsuccesfull
*/

Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
uchar *arg)
{
SELECT_LEX *old_select= thd->lex->current_select;
List<List_item> values;
bool list_of_lists= false;

if (args[1]->type() == Item::ROW_ITEM)
list_of_lists= true;
if (!sel)
goto err;

for (uint i=1; i < arg_count; i++)
{
List<Item> *new_value= new (thd->mem_root) List<Item>();
sel->parsing_place= old_select->parsing_place;
sel->table_list.first->derived_type= 10;

if (list_of_lists)
{
Item_row *in_list= (Item_row *)(args[i]);
in_subs= new (thd->mem_root) Item_in_subselect(thd, args[0], sel);
thd->lex->derived_tables |= DERIVED_SUBQUERY;
in_subs->emb_on_expr_nest= emb_on_expr_nest;

for (uint j=0; j < in_list->cols(); i++)
new_value->push_back(in_list->element_index(j), thd->mem_root);
}
else
new_value->push_back(args[i]);
old_select->cur_tvc++;
thd->lex->current_select= old_select;

values.push_back(new_value, thd->mem_root);
}
if (arena)
thd->restore_active_arena(arena, &backup);

st_select_lex *new_subselect=
make_new_subselect_for_tvc(thd, &values);
in_subs->fix_fields(thd, (Item **)&in_subs);
return in_subs;

if (new_subselect)
{
new_subselect->parsing_place= old_select->parsing_place;
new_subselect->table_list.first->derived_type= 10;

Item_in_subselect *in_subs= new (thd->mem_root) Item_in_subselect
(thd, args[0], new_subselect);
thd->lex->derived_tables |= DERIVED_SUBQUERY;
in_subs->emb_on_expr_nest= emb_on_expr_nest;
in_subs->fix_fields(thd, (Item **)&in_subs);

old_select->cur_tvc++;
thd->lex->current_select= old_select;
return in_subs;
}

thd->lex->current_select= old_select;
err:
if (arena)
thd->restore_active_arena(arena, &backup);
return this;
}

@@ -633,9 +610,12 @@ bool JOIN::transform_in_predicate_into_tvc(THD *thd_arg)
table->on_expr->transform(thd_arg,
&Item::in_predicate_to_in_subs_transformer,
(uchar*) 0);
table->prep_on_expr= table->on_expr ?
table->on_expr->copy_andor_structure(thd) : 0;
}
}
}
select_lex->in_funcs.empty();
select_lex->parsing_place= old_parsing_place;
thd_arg->lex->current_select= old_select;
return false;

0 comments on commit e701770

Please sign in to comment.