mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Memory allocation corrected. New tests added.
This commit is contained in:
@@ -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
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
Warnings:
|
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`
|
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;
|
drop table t1, t2;
|
||||||
set @@in_subquery_conversion_threshold= default;
|
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)
|
void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
|
||||||
{
|
{
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
|
|
||||||
|
Query_arena *arena, backup;
|
||||||
|
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||||
|
|
||||||
if (can_be_transformed_in_tvc(thd))
|
if (can_be_transformed_in_tvc(thd))
|
||||||
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
|
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;
|
emb_on_expr_nest= embedding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
240
sql/sql_tvc.cc
240
sql/sql_tvc.cc
@@ -372,121 +372,6 @@ void table_value_constr::print(THD *thd_arg, String *str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief
|
|
||||||
Creates new SELECT defined by TVC as derived table
|
|
||||||
|
|
||||||
@param thd_arg The context of the statement
|
|
||||||
@param values List of values that defines TVC
|
|
||||||
|
|
||||||
@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 method.
|
|
||||||
|
|
||||||
@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)
|
|
||||||
{
|
|
||||||
LEX *lex= thd_arg->lex;
|
|
||||||
Item *item;
|
|
||||||
SELECT_LEX *sel;
|
|
||||||
SELECT_LEX_UNIT *unit;
|
|
||||||
TABLE_LIST *new_tab;
|
|
||||||
Table_ident *ti;
|
|
||||||
|
|
||||||
Query_arena backup;
|
|
||||||
Query_arena *arena= thd_arg->activate_stmt_arena_if_needed(&backup);
|
|
||||||
|
|
||||||
char buff[6];
|
|
||||||
LEX_CSTRING alias;
|
|
||||||
alias.length= my_snprintf(buff, sizeof(buff),
|
|
||||||
"tvc_%u", thd_arg->lex->current_select->cur_tvc);
|
|
||||||
alias.str= thd_arg->strmake(buff, alias.length);
|
|
||||||
if (!alias.str)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Creation of SELECT statement: SELECT * FROM ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (mysql_new_select(lex, 1, NULL))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (item == NULL)
|
|
||||||
goto err;
|
|
||||||
if (add_item_to_list(thd_arg, item))
|
|
||||||
goto err;
|
|
||||||
(lex->current_select->with_wild)++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Creation of TVC as derived table
|
|
||||||
*/
|
|
||||||
|
|
||||||
lex->derived_tables|= DERIVED_SUBQUERY;
|
|
||||||
if (mysql_new_select(lex, 1, NULL))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
mysql_init_select(lex);
|
|
||||||
|
|
||||||
sel= lex->current_select;
|
|
||||||
unit= sel->master_unit();
|
|
||||||
sel->linkage= DERIVED_TABLE_TYPE;
|
|
||||||
|
|
||||||
if (!(sel->tvc=
|
|
||||||
new (thd_arg->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);
|
|
||||||
if (ti == NULL)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (!(new_tab= sel->add_table_to_list(thd_arg,
|
|
||||||
ti, &alias, 0,
|
|
||||||
TL_READ, MDL_SHARED_READ)))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
sel->add_joined_table(new_tab);
|
|
||||||
|
|
||||||
new_tab->select_lex->add_where_field(new_tab->derived->first_select());
|
|
||||||
|
|
||||||
sel->context.table_list=
|
|
||||||
sel->context.first_name_resolution_table=
|
|
||||||
sel->table_list.first;
|
|
||||||
|
|
||||||
sel->where= 0;
|
|
||||||
sel->set_braces(false);
|
|
||||||
unit->with_clause= 0;
|
|
||||||
|
|
||||||
return sel;
|
|
||||||
|
|
||||||
err:
|
|
||||||
if (arena)
|
|
||||||
thd_arg->restore_active_arena(arena, &backup);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief
|
@brief
|
||||||
Transforms IN-predicate in IN-subselect
|
Transforms IN-predicate in IN-subselect
|
||||||
@@ -512,7 +397,25 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
|
|||||||
uchar *arg)
|
uchar *arg)
|
||||||
{
|
{
|
||||||
SELECT_LEX *old_select= thd->lex->current_select;
|
SELECT_LEX *old_select= thd->lex->current_select;
|
||||||
|
|
||||||
List<List_item> values;
|
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->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;
|
bool list_of_lists= false;
|
||||||
|
|
||||||
if (args[1]->type() == Item::ROW_ITEM)
|
if (args[1]->type() == Item::ROW_ITEM)
|
||||||
@@ -535,26 +438,100 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
|
|||||||
values.push_back(new_value, thd->mem_root);
|
values.push_back(new_value, thd->mem_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
st_select_lex *new_subselect=
|
/*
|
||||||
make_new_subselect_for_tvc(thd, &values);
|
Creation of TVC name
|
||||||
|
*/
|
||||||
|
alias.length= my_snprintf(buff, sizeof(buff),
|
||||||
|
"tvc_%u", old_select->cur_tvc);
|
||||||
|
alias.str= thd->strmake(buff, alias.length);
|
||||||
|
if (!alias.str)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (new_subselect)
|
/*
|
||||||
{
|
Creation of SELECT statement: SELECT * FROM ...
|
||||||
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
|
if (mysql_new_select(lex, 1, NULL))
|
||||||
(thd, args[0], new_subselect);
|
goto err;
|
||||||
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++;
|
mysql_init_select(lex);
|
||||||
thd->lex->current_select= old_select;
|
lex->current_select->parsing_place= SELECT_LIST;
|
||||||
return in_subs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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, item))
|
||||||
|
goto err;
|
||||||
|
(lex->current_select->with_wild)++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Creation of TVC as derived table
|
||||||
|
*/
|
||||||
|
|
||||||
|
lex->derived_tables|= DERIVED_SUBQUERY;
|
||||||
|
if (mysql_new_select(lex, 1, NULL))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mysql_init_select(lex);
|
||||||
|
|
||||||
|
sel= lex->current_select;
|
||||||
|
unit= sel->master_unit();
|
||||||
|
sel->linkage= DERIVED_TABLE_TYPE;
|
||||||
|
|
||||||
|
if (!(sel->tvc=
|
||||||
|
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->mem_root) Table_ident(unit);
|
||||||
|
if (ti == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!(new_tab= sel->add_table_to_list(thd,
|
||||||
|
ti, &alias, 0,
|
||||||
|
TL_READ, MDL_SHARED_READ)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
sel->add_joined_table(new_tab);
|
||||||
|
|
||||||
|
new_tab->select_lex->add_where_field(new_tab->derived->first_select());
|
||||||
|
|
||||||
|
sel->context.table_list=
|
||||||
|
sel->context.first_name_resolution_table=
|
||||||
|
sel->table_list.first;
|
||||||
|
|
||||||
|
sel->where= 0;
|
||||||
|
sel->set_braces(false);
|
||||||
|
unit->with_clause= 0;
|
||||||
|
|
||||||
|
if (!sel)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
sel->parsing_place= old_select->parsing_place;
|
||||||
|
sel->table_list.first->derived_type= 10;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
old_select->cur_tvc++;
|
||||||
thd->lex->current_select= old_select;
|
thd->lex->current_select= old_select;
|
||||||
|
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
|
|
||||||
|
in_subs->fix_fields(thd, (Item **)&in_subs);
|
||||||
|
return in_subs;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,9 +610,12 @@ bool JOIN::transform_in_predicate_into_tvc(THD *thd_arg)
|
|||||||
table->on_expr->transform(thd_arg,
|
table->on_expr->transform(thd_arg,
|
||||||
&Item::in_predicate_to_in_subs_transformer,
|
&Item::in_predicate_to_in_subs_transformer,
|
||||||
(uchar*) 0);
|
(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;
|
select_lex->parsing_place= old_parsing_place;
|
||||||
thd_arg->lex->current_select= old_select;
|
thd_arg->lex->current_select= old_select;
|
||||||
return false;
|
return false;
|
||||||
|
Reference in New Issue
Block a user