Commit e7017707 authored by Galina Shalygina's avatar Galina Shalygina

Memory allocation corrected. New tests added.

parent 1efa9ed8
......@@ -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,8 +480,8 @@ 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;
......@@ -457,11 +489,11 @@ st_select_lex *make_new_subselect_for_tvc(THD *thd_arg,
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment