[Commits] 65d950d: MDEV-24910 Crash with SELECT that uses table value constructor as a subselect
revision-id: 65d950d48fc37989bbd5213f083a1f3cb3bd53fb (mariadb-10.3.26-79-g65d950d) parent(s): da88e1ec12b0ba39552bf54367c1bb3b89eac4a8 author: Igor Babaev committer: Igor Babaev timestamp: 2021-02-22 14:21:42 -0800 message: MDEV-24910 Crash with SELECT that uses table value constructor as a subselect A preliminary commit (not to be pushed). --- mysql-test/main/table_value_constr.result | 4 +-- sql/sql_lex.cc | 12 +++++++ sql/sql_lex.h | 1 + sql/sql_tvc.cc | 53 ++++++++++++++++++++----------- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index d7b3286..cd839ae 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -748,7 +748,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00 2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1 +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1 explain extended select * from t1 where a in (select * from (values (1)) as tvc_0); id select_type table type possible_keys key key_len ref rows filtered Extra @@ -983,7 +983,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00 2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1 +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1 explain extended select * from t1 where a = any (select * from (values (1),(2)) as tvc_0); id select_type table type possible_keys key key_len ref rows filtered Extra diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b8f6610..d287466 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2464,10 +2464,22 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg) { slave= slave_arg; slave_arg->master= this; + slave->prev= &master->slave; + slave->next= 0; } } +void st_select_lex_node::substitute_in_tree(st_select_lex_node *subst) +{ + if ((subst->next= next)) + next->prev= &subst->next; + subst->prev= prev; + (*prev)= subst; + subst->master= master; +} + + /* include on level down (but do not link) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 55929ed..bed2b39 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -711,6 +711,7 @@ class st_select_lex_node { void include_global(st_select_lex_node **plink); void exclude(); void exclude_from_tree(); + void substitute_in_tree(st_select_lex_node *subst); void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; } void move_node(st_select_lex_node *where_to_move) diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 78607b6..8c54741 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -643,38 +643,53 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl, Query_arena backup; Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup); /* - Create SELECT_LEX of the select used in the result of transformation + Create SELECT_LEX wrapper_sl of the select used in the result + of the transformation */ - lex->current_select= tvc_sl; - if (mysql_new_select(lex, 0, NULL)) - goto err; - mysql_init_select(lex); - /* Create item list as '*' for the subquery SQ */ Item *item; SELECT_LEX *wrapper_sl; - wrapper_sl= lex->current_select; + SELECT_LEX_UNIT *derived_unit; + if (!(wrapper_sl= new (thd->mem_root) SELECT_LEX())) + goto err; + wrapper_sl->select_number= ++thd->lex->stmt_lex->current_select_number; + wrapper_sl->parent_lex= lex; /* Used in init_query. */ + wrapper_sl->init_query(); + wrapper_sl->init_select(); + + wrapper_sl->nest_level= tvc_sl->nest_level; + wrapper_sl->parsing_place= tvc_sl->parsing_place; wrapper_sl->linkage= tvc_sl->linkage; - wrapper_sl->parsing_place= SELECT_LIST; + + lex->current_select= wrapper_sl; item= new (thd->mem_root) Item_field(thd, &wrapper_sl->context, NULL, NULL, &star_clex_str); if (item == NULL || add_item_to_list(thd, item)) goto err; (wrapper_sl->with_wild)++; - - /* Exclude SELECT with TVC */ - tvc_sl->exclude(); + + /* Include the newly created select into the global list of selects */ + wrapper_sl->include_global((st_select_lex_node**)&lex->all_selects_list); + + /* Substitute select node used for TVC for the newly created select */ + tvc_sl->substitute_in_tree(wrapper_sl); + /* - Create derived table DT that will wrap TVC in the result of transformation + Create a unit for the substituted select used for TVC and attach it + as the only unit to the the wrapper select_wrapper sl. The created + unit is the unit for the derived table tvc_x of the transformation. */ - SELECT_LEX *tvc_select; // select for tvc - SELECT_LEX_UNIT *derived_unit; // unit for tvc_select - if (mysql_new_select(lex, 1, tvc_sl)) + if (!(derived_unit= new (thd->mem_root) SELECT_LEX_UNIT())) goto err; - tvc_select= lex->current_select; - derived_unit= tvc_select->master_unit(); - tvc_select->linkage= DERIVED_TABLE_TYPE; + derived_unit->init_query(); + derived_unit->thd= thd; + derived_unit->include_down(wrapper_sl); - lex->current_select= wrapper_sl; + /* + Attach the select used for TVC as the only slave to the unit for + the derived table tvc_x of the transformation + */ + derived_unit->add_slave(tvc_sl); + tvc_sl->linkage= DERIVED_TABLE_TYPE; /* Create the name of the wrapping derived table and
participants (1)
-
IgorBabaev