From 55cde3b428a66808359f5dfd1458f84c26793bac Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Sun, 4 Sep 2011 16:35:37 +0400 Subject: [PATCH] BUG#836532: Crash in Item_equal_fields_iterator::get_curr_field with semijoin+materialization - Item_in_subselect::inject_in_to_exists_cond() should not call ((Item_cond*)join->conds)->argument_list()->concat(join->cond_equal->current_level) as that makes two lists share their tail, and the cond_equal list will end up containing non-Item_equal objects when substitute_for_best_equal_field() walks through join->conds and replaces all Item_equal objects with Item_func_eq objects. - So, instead of using List::concat(), manually copy entries from one list to another. --- mysql-test/r/subselect_mat.result | 31 ++++++++++++++++++++++++++- mysql-test/r/subselect_sj_mat.result | 31 ++++++++++++++++++++++++++- mysql-test/t/subselect_sj_mat.test | 32 +++++++++++++++++++++++++++- sql/item_subselect.cc | 7 +++++- sql/sql_list.h | 21 ++++++++++++++++++ 5 files changed, 118 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index 8829accb26c..4a38ccf75b9 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -3,7 +3,7 @@ set @subselect_sj_mat_tmp= @@optimizer_switch; set optimizer_switch=ifnull(@subselect_mat_test_optimizer_switch_value, 'semijoin=on,firstmatch=on,loosescan=on'); set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; set @optimizer_switch_local_default= @@optimizer_switch; -drop table if exists t1, t2, t3, t4, t1i, t2i, t3i; +drop table if exists t1, t2, t3, t4, t5, t1i, t2i, t3i; drop table if exists columns; drop table if exists t1_16, t2_16, t3_16; drop view if exists v1, v2, v1m, v2m; @@ -1627,6 +1627,35 @@ a 1 1 DROP TABLE t1,t2,t3,t4,t5; +# +# BUG#836532: Crash in Item_equal_fields_iterator::get_curr_field with semijoin+materialization +# +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES ('a'),('a'); +Warnings: +Warning 1366 Incorrect integer value: 'a' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'a' for column 'a' at row 2 +CREATE TABLE t4 (a varchar(1)); +INSERT INTO t4 VALUES ('m'),('o'); +CREATE TABLE t3 (a varchar(1) , b varchar(1) ) ; +INSERT INTO t3 VALUES ('b','b'); +CREATE TABLE t5 (a varchar(1), KEY (a)) ; +INSERT INTO t5 VALUES ('d'),('e'); +SELECT * +FROM t2 +WHERE t2.a = ALL ( +SELECT t4.a +FROM t4 +WHERE t4.a IN ( +SELECT t3.a +FROM t3 , t5 +WHERE ( t5.a = t3.b ) +) +); +a +0 +0 +DROP TABLE t2,t3,t4,t5; set optimizer_switch=@subselect_sj_mat_tmp; set @subselect_mat_test_optimizer_switch_value=null; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off'; diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index f3e22ae1794..cbfe5f22467 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -2,7 +2,7 @@ set @subselect_sj_mat_tmp= @@optimizer_switch; set optimizer_switch=ifnull(@subselect_mat_test_optimizer_switch_value, 'semijoin=on,firstmatch=on,loosescan=on'); set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; set @optimizer_switch_local_default= @@optimizer_switch; -drop table if exists t1, t2, t3, t4, t1i, t2i, t3i; +drop table if exists t1, t2, t3, t4, t5, t1i, t2i, t3i; drop table if exists columns; drop table if exists t1_16, t2_16, t3_16; drop view if exists v1, v2, v1m, v2m; @@ -1665,4 +1665,33 @@ a 1 1 DROP TABLE t1,t2,t3,t4,t5; +# +# BUG#836532: Crash in Item_equal_fields_iterator::get_curr_field with semijoin+materialization +# +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES ('a'),('a'); +Warnings: +Warning 1366 Incorrect integer value: 'a' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'a' for column 'a' at row 2 +CREATE TABLE t4 (a varchar(1)); +INSERT INTO t4 VALUES ('m'),('o'); +CREATE TABLE t3 (a varchar(1) , b varchar(1) ) ; +INSERT INTO t3 VALUES ('b','b'); +CREATE TABLE t5 (a varchar(1), KEY (a)) ; +INSERT INTO t5 VALUES ('d'),('e'); +SELECT * +FROM t2 +WHERE t2.a = ALL ( +SELECT t4.a +FROM t4 +WHERE t4.a IN ( +SELECT t3.a +FROM t3 , t5 +WHERE ( t5.a = t3.b ) +) +); +a +0 +0 +DROP TABLE t2,t3,t4,t5; set optimizer_switch=@subselect_sj_mat_tmp; diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index b2718e57624..95ef6a25df3 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -9,7 +9,7 @@ set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; set @optimizer_switch_local_default= @@optimizer_switch; --disable_warnings -drop table if exists t1, t2, t3, t4, t1i, t2i, t3i; +drop table if exists t1, t2, t3, t4, t5, t1i, t2i, t3i; drop table if exists columns; drop table if exists t1_16, t2_16, t3_16; drop view if exists v1, v2, v1m, v2m; @@ -1319,5 +1319,35 @@ WHERE (a) IN ( DROP TABLE t1,t2,t3,t4,t5; +--echo # +--echo # BUG#836532: Crash in Item_equal_fields_iterator::get_curr_field with semijoin+materialization +--echo # + +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES ('a'),('a'); + +CREATE TABLE t4 (a varchar(1)); +INSERT INTO t4 VALUES ('m'),('o'); + +CREATE TABLE t3 (a varchar(1) , b varchar(1) ) ; +INSERT INTO t3 VALUES ('b','b'); + +CREATE TABLE t5 (a varchar(1), KEY (a)) ; +INSERT INTO t5 VALUES ('d'),('e'); + +SELECT * +FROM t2 +WHERE t2.a = ALL ( + SELECT t4.a + FROM t4 + WHERE t4.a IN ( + SELECT t3.a + FROM t3 , t5 + WHERE ( t5.a = t3.b ) + ) +); + +DROP TABLE t2,t3,t4,t5; + set optimizer_switch=@subselect_sj_mat_tmp; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 92e311feb8d..0e23be77fbf 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2264,7 +2264,12 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) { /* The argument list of the top-level AND may change after fix fields. */ and_args= ((Item_cond*) join_arg->conds)->argument_list(); - and_args->concat((List *) &join_arg->cond_equal->current_level); + List_iterator li(join_arg->cond_equal->current_level); + Item_equal *elem; + while ((elem= li++)) + { + and_args->push_back(elem); + } } } diff --git a/sql/sql_list.h b/sql/sql_list.h index 50673921aeb..0189ad88597 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -310,6 +310,26 @@ public: friend class error_list; friend class error_list_iterator; + /* + Debugging help: return N-th element in the list, or NULL if the list has + less than N elements. + */ + inline void *nth_element(int n) + { + list_node *node= first; + void *data; + for (int i=0; i <= n; i++) + { + if (node == &end_of_list) + { + data= NULL; + break; + } + data= node->info; + node= node->next; + } + return data; + } #ifdef LIST_EXTRA_DEBUG /* Check list invariants and print results into trace. Invariants are: @@ -488,6 +508,7 @@ public: } empty(); } + inline T *nth_element(int n) { return (T*)base_list::nth_element(n); } };