From: Roy Lyseng Date: March 10 2010 11:14am Subject: bzr commit into mysql-6.0-codebase-bugfixing branch (roy.lyseng:3804) Bug#50089 List-Archive: http://lists.mysql.com/commits/102862 X-Bug: 50089 Message-Id: <20100310111450.9B4DE1DE@tyr67.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8231915630529332491==" --===============8231915630529332491== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/rl136806/mysql/repo/mysql-6.0-work1/ based on revid:marc.alff@stripped 3804 Roy Lyseng 2010-03-10 Bug#50089: Second call of procedure with view in subselect crashes server The bug case contains a query that references a view. Here is the view definition: SELECT t1field AS v1_field FROM t1 AS A WHERE A.t1field IN (SELECT t1field FROM t1); When expanding the view at prepare time, this select_lex graph is created: VS1(A) \ VS2(t1) This is the query that is executed: SELECT t1field FROM t1 WHERE t1field IN (SELECT * FROM v1); At prepare time, the query is conceptually expanded to the following query: SELECT t1field FROM t1 WHERE t1field IN (SELECT t1field AS v1_field FROM t1 AS A WHERE A.t1field IN (SELECT t1field FROM t1)); Here is the select_lex graph after view expansion: S1(t1) \ S2(A) \ VS2(t1) The contents of select_lex VS1 is merged with the query graph and VS1 is discarded after merging. At first execution, semijoin conversion is performed, and the query is transformed to: SELECT t1_field FROM t1 semijoin t1 AS A ON t1.t1_field = A.t1_field WHERE A.t1_field IN (SELECT t1_field FROM t1)); Now, the select_lex object S2 is optimized away and the table A is added to S1. Here is the select_lex graph after transformation: S1(t1) \ VS2(t1) The master field of VS2 points to S1 after conversion. However, the return_to field of VS2 still points to VS1. First execution proceeds normally after this. At second execution, all items in the transformed query are first re-resolved. When re-resolving A.t1_field, function mark_select_range_as_dependent() is called with VS1 as current_sel and S1 as last_select arguments. Now, the master unit of VS1 does not have an "item", and we segfault. Problem occurs when mark_select_range_as_dependent() is called with two select_lex pointers that point into different query trees, one tree being the main query tree, the other being the tree representing the view. This problem is due to the fact that the function return_after_parsing() is used to provide pointer to the select_lex object representing the outer query specification of a subquery. However, the return_to field was not properly updated in all situations. But it was also noticed that outer_select() gives the same information as return_after_parsing(), and the data used by this function is always kept up-to-date. The bug was thus fixed by removing return_after_parsing() and associated data, and replacing calls with outer_select(). Notice also that queries within procedures internally create prepared statements, so the solution works equally well for procedures as well as for prepared statements. mysql-test/r/subselect_sj.result Test result for Bug#50089 mysql-test/r/subselect_sj_jcl6.result Test result for Bug#50089 mysql-test/t/subselect_sj.test Test case for Bug#50089 sql/item_subselect.cc Replaced references to return_after_parsing() with outer_select(). sql/sql_lex.cc Removed function return_after_parsing() and data field return_to. sql/sql_lex.h Removed function return_after_parsing() and data field return_to. sql/sql_parse.cc Replaced reference to return_after_parsing() with outer_select(). sql/sql_select.cc Replaced reference to return_after_parsing() with outer_select(). sql/sql_yacc.yy Replaced reference to return_after_parsing() with outer_select(). modified: mysql-test/r/subselect_sj.result mysql-test/r/subselect_sj_jcl6.result mysql-test/t/subselect_sj.test sql/item_subselect.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_parse.cc sql/sql_select.cc sql/sql_yacc.yy === modified file 'mysql-test/r/subselect_sj.result' --- a/mysql-test/r/subselect_sj.result 2010-03-08 09:19:01 +0000 +++ b/mysql-test/r/subselect_sj.result 2010-03-10 11:14:25 +0000 @@ -1740,3 +1740,58 @@ DROP TABLE ot; DROP TABLE it1; DROP TABLE it2; # End of Bug#48623 +# +# BUG#50089: Second call of procedure with view in subselect crashes server +# +CREATE TABLE t1(t1field INTEGER, PRIMARY KEY(t1field)); +CREATE VIEW v1 AS +SELECT t1field AS v1field +FROM t1 A +WHERE A.t1field IN (SELECT t1field FROM t1); +INSERT INTO t1 VALUES(1),(2); +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +t1field +1 +2 +EXPLAIN +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index +1 PRIMARY A eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index +4 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index +CREATE PROCEDURE p1() +BEGIN +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +END| +CALL p1; +t1field +1 +2 +CALL p1; +t1field +1 +2 +PREPARE stmt FROM +" +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +"; +EXECUTE stmt; +t1field +1 +2 +EXECUTE stmt; +t1field +1 +2 +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; +# End of BUG#50089 === modified file 'mysql-test/r/subselect_sj_jcl6.result' --- a/mysql-test/r/subselect_sj_jcl6.result 2010-03-08 09:19:01 +0000 +++ b/mysql-test/r/subselect_sj_jcl6.result 2010-03-10 11:14:25 +0000 @@ -1744,6 +1744,61 @@ DROP TABLE ot; DROP TABLE it1; DROP TABLE it2; # End of Bug#48623 +# +# BUG#50089: Second call of procedure with view in subselect crashes server +# +CREATE TABLE t1(t1field INTEGER, PRIMARY KEY(t1field)); +CREATE VIEW v1 AS +SELECT t1field AS v1field +FROM t1 A +WHERE A.t1field IN (SELECT t1field FROM t1); +INSERT INTO t1 VALUES(1),(2); +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +t1field +1 +2 +EXPLAIN +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index +1 PRIMARY A eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index +4 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index +CREATE PROCEDURE p1() +BEGIN +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +END| +CALL p1; +t1field +1 +2 +CALL p1; +t1field +1 +2 +PREPARE stmt FROM +" +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +"; +EXECUTE stmt; +t1field +1 +2 +EXECUTE stmt; +t1field +1 +2 +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; +# End of BUG#50089 set optimizer_join_cache_level=default; show variables like 'optimizer_join_cache_level'; Variable_name Value === modified file 'mysql-test/t/subselect_sj.test' --- a/mysql-test/t/subselect_sj.test 2010-03-08 09:19:01 +0000 +++ b/mysql-test/t/subselect_sj.test 2010-03-10 11:14:25 +0000 @@ -964,3 +964,53 @@ DROP TABLE it1; DROP TABLE it2; --echo # End of Bug#48623 + +--echo # +--echo # BUG#50089: Second call of procedure with view in subselect crashes server +--echo # + +CREATE TABLE t1(t1field INTEGER, PRIMARY KEY(t1field)); + +CREATE VIEW v1 AS + SELECT t1field AS v1field + FROM t1 A + WHERE A.t1field IN (SELECT t1field FROM t1); + +INSERT INTO t1 VALUES(1),(2); + +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); + +EXPLAIN +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); + +delimiter |; +CREATE PROCEDURE p1() + BEGIN + SELECT t1field + FROM t1 + WHERE t1field IN (SELECT v1field FROM v1); + END| +delimiter ;| + +CALL p1; +CALL p1; + +PREPARE stmt FROM +" +SELECT t1field +FROM t1 +WHERE t1field IN (SELECT v1field FROM v1); +"; + +EXECUTE stmt; +EXECUTE stmt; + +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; + +--echo # End of BUG#50089 === modified file 'sql/item_subselect.cc' --- a/sql/item_subselect.cc 2010-03-01 10:04:07 +0000 +++ b/sql/item_subselect.cc 2010-03-10 11:14:25 +0000 @@ -1106,7 +1106,7 @@ Item_in_subselect::single_value_transfor SELECT_LEX *current= thd->lex->current_select; - thd->lex->current_select= current->return_after_parsing(); + thd->lex->current_select= current->outer_select(); //optimizer never use Item **ref => we can pass 0 as parameter if (!optimizer || optimizer->fix_left(thd, 0)) { @@ -1392,7 +1392,7 @@ Item_in_subselect::row_value_transformer substitution= optimizer; SELECT_LEX *current= thd->lex->current_select; - thd->lex->current_select= current->return_after_parsing(); + thd->lex->current_select= current->outer_select(); //optimizer never use Item **ref => we can pass 0 as parameter if (!optimizer || optimizer->fix_left(thd, 0)) { @@ -1722,7 +1722,7 @@ Item_in_subselect::select_in_like_transf goto err; } - thd->lex->current_select= current->return_after_parsing(); + thd->lex->current_select= current->outer_select(); result= (!left_expr->fixed && left_expr->fix_fields(thd, optimizer->arguments())); /* fix_fields can change reference to left_expr, we need reassign it */ === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2010-02-25 13:55:28 +0000 +++ b/sql/sql_lex.cc 2010-03-10 11:14:25 +0000 @@ -327,8 +327,7 @@ void lex_start(THD *thd) lex->view_list.empty(); lex->prepared_stmt_params.empty(); lex->auxiliary_table_list.empty(); - lex->unit.next= lex->unit.master= - lex->unit.link_next= lex->unit.return_to= 0; + lex->unit.next= lex->unit.master= lex->unit.link_next= 0; lex->unit.prev= lex->unit.link_prev= 0; lex->unit.slave= lex->unit.global_parameters= lex->current_select= lex->all_selects_list= &lex->select_lex; === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2010-02-25 13:55:28 +0000 +++ b/sql/sql_lex.h 2010-03-10 11:14:25 +0000 @@ -398,7 +398,6 @@ public: virtual st_select_lex_unit* master_unit()= 0; virtual st_select_lex* outer_select()= 0; - virtual st_select_lex* return_after_parsing()= 0; virtual bool set_braces(bool value); virtual bool inc_in_sum_expr(); @@ -477,8 +476,6 @@ public: global parameters for union */ st_select_lex *global_parameters; - //node on wich we should return current_select pointer after parsing subquery - st_select_lex *return_to; /* LIMIT clause runtime counters */ ha_rows select_limit_cnt, offset_limit_cnt; /* not NULL if unit used in subselect, point to subselect item */ @@ -506,7 +503,6 @@ public: { return my_reinterpret_cast(st_select_lex_unit*)(next); } - st_select_lex* return_after_parsing() { return return_to; } void exclude_level(); void exclude_tree(); @@ -700,11 +696,6 @@ public: { return &link_next; } - st_select_lex* return_after_parsing() - { - return master_unit()->return_after_parsing(); - } - void mark_as_dependent(st_select_lex *last); bool set_braces(bool value); === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2010-03-04 15:37:02 +0000 +++ b/sql/sql_parse.cc 2010-03-10 11:14:25 +0000 @@ -5856,7 +5856,6 @@ mysql_new_select(LEX *lex, bool move_dow unit->include_down(lex->current_select); unit->link_next= 0; unit->link_prev= 0; - unit->return_to= lex->current_select; select_lex->include_down(unit); /* By default we assume that it is usual subselect and we have outer name === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2010-03-08 09:19:01 +0000 +++ b/sql/sql_select.cc 2010-03-10 11:14:25 +0000 @@ -627,7 +627,7 @@ JOIN::prepare(Item ***rref_pointer_array } SELECT_LEX *current= thd->lex->current_select; - thd->lex->current_select= current->return_after_parsing(); + thd->lex->current_select= current->outer_select(); char const *save_where= thd->where; thd->where= "IN/ALL/ANY subquery"; === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2010-03-02 14:39:15 +0000 +++ b/sql/sql_yacc.yy 2010-03-10 11:14:25 +0000 @@ -14140,7 +14140,7 @@ subselect_end: lex->pop_context(); SELECT_LEX *child= lex->current_select; - lex->current_select = lex->current_select->return_after_parsing(); + lex->current_select = lex->current_select->outer_select(); lex->nest_level--; lex->current_select->n_child_sum_items += child->n_sum_items; /* --===============8231915630529332491== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/roy.lyseng@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: roy.lyseng@stripped # target_branch: file:///home/rl136806/mysql/repo/mysql-6.0-work1/ # testament_sha1: ebd4ba9a2688473d09bb7711874ce7f375b1b5f2 # timestamp: 2010-03-10 12:14:50 +0100 # base_revision_id: marc.alff@stripped # # Begin bundle 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 /F3JFOFCQb7rvig= --===============8231915630529332491==--