From 2c9844a438c5f0bddcb037a1e05978118f48abb6 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sun, 19 May 2019 11:44:34 -0700 Subject: MDEV-18896 Crash in convert_join_subqueries_to_semijoins : Correction This patch complements the original patch for MDEV-18896 that prevents conversions to semi-joins in tableless selects used in INSERT statements in post-5.5 versions of the server. The test case was corrected as well to ensure that potential conversion to jtbm semi-joins is also checked (the problem was that one of the preceeding testcases in subselect_sj.test did not restore the state of the optimizer switch leaving the 'materialization' in the state 'off' and so blocking this check). Noticed an inconsistency in the state of select_lex::table_list used in INSERT statements and left a comment about this. --- mysql-test/r/subselect_sj.result | 1 + mysql-test/r/subselect_sj_jcl6.result | 1 + mysql-test/t/subselect_sj.test | 2 ++ sql/opt_subselect.cc | 2 +- sql/sql_parse.cc | 7 +++++++ 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 73c620b2973..d0b8b626ba2 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -3181,6 +3181,7 @@ drop table t1,t2,t3; # # MDEV-18896: IN subquery in WHERE of a table-less query used for INSERT # +set @@optimizer_switch= @subselect_sj_tmp; create table t1 (a1 varchar(25)); create table t2 (a2 varchar(25)) ; insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2); diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 03cf368f32c..e9a8b7301f7 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -3195,6 +3195,7 @@ drop table t1,t2,t3; # # MDEV-18896: IN subquery in WHERE of a table-less query used for INSERT # +set @@optimizer_switch= @subselect_sj_tmp; create table t1 (a1 varchar(25)); create table t2 (a2 varchar(25)) ; insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2); diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index aabb21b4245..6b59049bc4f 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2873,6 +2873,8 @@ drop table t1,t2,t3; --echo # MDEV-18896: IN subquery in WHERE of a table-less query used for INSERT --echo # +set @@optimizer_switch= @subselect_sj_tmp; + create table t1 (a1 varchar(25)); create table t2 (a2 varchar(25)) ; insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index fee68d33c33..a0e19af3d4e 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -525,7 +525,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs, parent_unit->first_select()->leaf_tables.elements && // 2 (thd->lex->sql_command == SQLCOM_SELECT || // * thd->lex->sql_command == SQLCOM_CREATE_TABLE) && // * - child_select->outer_select()->leaf_tables.elements && // 2A + child_select->outer_select()->table_list.first && // 2A subquery_types_allow_materialization(in_subs) && (in_subs->is_top_level_item() || //3 optimizer_flag(thd, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4ed2bcaed38..1d5733a646b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3034,6 +3034,13 @@ end_with_restore_list: */ /* Skip first table, which is the table we are inserting in */ TABLE_LIST *second_table= first_table->next_local; + /* + This is a hack: this leaves select_lex->table_list in an inconsistent + state as 'elements' does not contain number of elements in the list. + Moreover, if second_table == NULL then 'next' becomes invalid. + TODO: fix it by removing the front element (restoring of it should + be done properly as well) + */ select_lex->table_list.first= second_table; select_lex->context.table_list= select_lex->context.first_name_resolution_table= second_table; -- cgit v1.2.1