From 519c7305ac4e1e4bafe0acc56764fa40a0e621ab Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Thu, 23 Jan 2014 21:26:04 +0400 Subject: [PATCH 1/3] MDEV-5368: Server crashes in Item_in_subselect::optimize on ... - convert_subq_to_sj() must connect child select's tables into parent select's TABLE_LIST::next_local chain. - The problem was that it took child's leaf_tables.head() which is different. This could cause certain tables (in this bug's case, child select's non-merged semi-join) not to be present in TABLE_LIST::next_local chain. Which would cause non-merged semi-join not to be initialized in setup_tables(), which would lead to NULL pointer dereference. --- mysql-test/r/subselect_mat.result | 18 ++++++++++++++++++ mysql-test/r/subselect_sj_mat.result | 18 ++++++++++++++++++ mysql-test/t/subselect_sj_mat.test | 20 ++++++++++++++++++++ sql/opt_subselect.cc | 2 +- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index 66b94af5d44..c47881d5434 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -2023,6 +2023,24 @@ INSERT INTO t1 VALUES (1,3,5),(2,4,6); SELECT * FROM t1 WHERE 8 IN (SELECT MIN(pk) FROM t1) AND (pk = a OR pk = b); pk a b DROP TABLE t1; +# +# MDEV-5368: Server crashes in Item_in_subselect::optimize on 2nd +# execution of PS with IN subqueries, materialization+semijoin +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(3); +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +INSERT INTO t2 VALUES (8),(9); +PREPARE stmt FROM " +SELECT * FROM t1 WHERE 1 IN ( SELECT b FROM v2 WHERE 2 IN ( SELECT MAX(a) FROM t1 ) ) +"; +EXECUTE stmt; +a +EXECUTE stmt; +a +DROP TABLE t1, t2; +DROP VIEW v2; # End of 5.3 tests 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 61ebe3cf5c3..f267f32c887 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -2063,4 +2063,22 @@ INSERT INTO t1 VALUES (1,3,5),(2,4,6); SELECT * FROM t1 WHERE 8 IN (SELECT MIN(pk) FROM t1) AND (pk = a OR pk = b); pk a b DROP TABLE t1; +# +# MDEV-5368: Server crashes in Item_in_subselect::optimize on 2nd +# execution of PS with IN subqueries, materialization+semijoin +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(3); +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +INSERT INTO t2 VALUES (8),(9); +PREPARE stmt FROM " +SELECT * FROM t1 WHERE 1 IN ( SELECT b FROM v2 WHERE 2 IN ( SELECT MAX(a) FROM t1 ) ) +"; +EXECUTE stmt; +a +EXECUTE stmt; +a +DROP TABLE t1, t2; +DROP VIEW v2; # End of 5.3 tests diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index 840e5436a56..bf5360dd4a7 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -1706,4 +1706,24 @@ INSERT INTO t1 VALUES (1,3,5),(2,4,6); SELECT * FROM t1 WHERE 8 IN (SELECT MIN(pk) FROM t1) AND (pk = a OR pk = b); DROP TABLE t1; +--echo # +--echo # MDEV-5368: Server crashes in Item_in_subselect::optimize on 2nd +--echo # execution of PS with IN subqueries, materialization+semijoin +--echo # +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(3); + +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +INSERT INTO t2 VALUES (8),(9); + +PREPARE stmt FROM " +SELECT * FROM t1 WHERE 1 IN ( SELECT b FROM v2 WHERE 2 IN ( SELECT MAX(a) FROM t1 ) ) +"; + +EXECUTE stmt; +EXECUTE stmt; +DROP TABLE t1, t2; +DROP VIEW v2; + --echo # End of 5.3 tests diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index adb67e5169a..07dbb3991b0 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1509,7 +1509,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) for (tl= (TABLE_LIST*)(parent_lex->table_list.first); tl->next_local; tl= tl->next_local) {} - tl->next_local= subq_lex->leaf_tables.head(); + tl->next_local= subq_lex->join->tables_list; /* A theory: no need to re-connect the next_global chain */ From d106dc059746157239d951551093fec049a7b73a Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 Jan 2014 16:50:39 +0400 Subject: [PATCH 2/3] MDEV-5504 Server crashes in String::length on SELECT with MONTHNAME, GROUP BY, ROLLUP The crash happened because Item_func_monthname was derived from Item_func_month, so Item_func_monthname::is_null() did not work fine. Backporting a change from 5.5: Item_func_monthname is now derived from Item_str_func. --- mysql-test/r/func_time.result | 12 +++++++++++- mysql-test/t/func_time.test | 9 +++++++++ sql/item_timefunc.cc | 13 +++++-------- sql/item_timefunc.h | 5 ++--- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 7020007f940..ddbf42c8060 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -162,7 +162,7 @@ dayname("1962-03-03") dayname("1962-03-03")+0 Saturday 5 select monthname("1972-03-04"),monthname("1972-03-04")+0; monthname("1972-03-04") monthname("1972-03-04")+0 -March 3 +March 0 select time_format(000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T'),date_format(19980131000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T'); time_format(000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T') date_format(19980131000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T') 00|12|0|12|00|AM|12:00:00 AM|00|00:00:00 00|12|0|12|00|AM|12:00:00 AM|00|00:00:00 @@ -2347,3 +2347,13 @@ EXTRACT(HOUR FROM TIME('1 02:00:00')) EXTRACT(HOUR FROM TIME('26:00:00')) SELECT EXTRACT(DAY FROM TIME('1 02:00:00')), EXTRACT(DAY FROM TIME('26:00:00')); EXTRACT(DAY FROM TIME('1 02:00:00')) EXTRACT(DAY FROM TIME('26:00:00')) 1 1 +# +# MDEV-5504 Server crashes in String::length on SELECT with MONTHNAME, GROUP BY, ROLLUP +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT 1 FROM t1 GROUP BY MONTHNAME(0) WITH ROLLUP; +1 +1 +1 +DROP TABLE t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 91ccb06655e..2e8716f3297 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -1417,3 +1417,12 @@ SELECT EXTRACT(HOUR FROM '1 02:00:00'), EXTRACT(HOUR FROM '26:00:00'); SELECT EXTRACT(HOUR FROM TIME'1 02:00:00'), EXTRACT(HOUR FROM TIME'26:00:00'); SELECT EXTRACT(HOUR FROM TIME('1 02:00:00')), EXTRACT(HOUR FROM TIME('26:00:00')); SELECT EXTRACT(DAY FROM TIME('1 02:00:00')), EXTRACT(DAY FROM TIME('26:00:00')); + + +--echo # +--echo # MDEV-5504 Server crashes in String::length on SELECT with MONTHNAME, GROUP BY, ROLLUP +--echo # +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT 1 FROM t1 GROUP BY MONTHNAME(0) WITH ROLLUP; +DROP TABLE t1; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index b618ec038f2..b5d43786248 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -883,16 +883,13 @@ String* Item_func_monthname::val_str(String* str) { DBUG_ASSERT(fixed == 1); const char *month_name; - uint month= (uint) val_int(); uint err; + MYSQL_TIME ltime; - if (null_value || !month) - { - null_value=1; - return (String*) 0; - } - null_value=0; - month_name= locale->month_names->type_names[month-1]; + if ((null_value= (get_arg0_date(<ime, 0) || !ltime.month))) + return (String *) 0; + + month_name= locale->month_names->type_names[ltime.month - 1]; str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8_bin, collation.collation, &err); return str; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index d97a5fbc903..7d865df8fea 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -134,14 +134,13 @@ public: }; -class Item_func_monthname :public Item_func_month +class Item_func_monthname :public Item_str_func { MY_LOCALE *locale; public: - Item_func_monthname(Item *a) :Item_func_month(a) {} + Item_func_monthname(Item *a) :Item_str_func(a) {} const char *func_name() const { return "monthname"; } String *val_str(String *str); - enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec(); bool check_partition_func_processor(uchar *int_arg) {return TRUE;} bool check_vcol_func_processor(uchar *int_arg) {return FALSE;} From 669c6620af9a9996a66ca9b339d4fb05eb6bf944 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Sat, 25 Jan 2014 00:26:40 +0400 Subject: [PATCH 3/3] [Backport to 5.3] MDEV-5337: Wrong result in mariadb 5.5.32 with ORDER BY + LIMIT when index_condition_pushdown=on - in test_if_skip_sort_order(), correct the condition under which we have the code that restores the previously pushed index condition. --- mysql-test/r/innodb_icp.result | 25 +++++++++++++++++++++++++ mysql-test/t/innodb_icp.test | 28 ++++++++++++++++++++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_icp.result b/mysql-test/r/innodb_icp.result index 53a76b2a3f3..19c4ac25a88 100644 --- a/mysql-test/r/innodb_icp.result +++ b/mysql-test/r/innodb_icp.result @@ -851,5 +851,30 @@ insert into t1 values ('',1); select 1 from t1 where b <= 1 and a <> ''; 1 drop table t1; +# +# MDEV-5337: Wrong result in mariadb 5.5.32 with ORDER BY + LIMIT when index_condition_pushdown=on +# MDEV-5512: Wrong result (WHERE clause ignored) with multiple clauses using Percona-XtraDB engine +# +create table t1(a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (pk int primary key, +key1 char(32), +key2 char(32), +key(key1), +key(key2) +) engine=innodb; +insert into t2 select +A.a+10*B.a+100*C.a, +concat('rare-', A.a+10*B.a), +concat('rare-', A.a+10*B.a) +from +t1 A, t1 B, t1 C; +update t2 set key1='frequent-val' where pk between 100 and 350; +select * from t2 ignore key(PRIMARY) +where key1='frequent-val' and key2 between 'rare-400' and 'rare-450' order by pk limit 2; +pk key1 key2 +141 frequent-val rare-41 +142 frequent-val rare-42 +drop table t1, t2; set optimizer_switch=@innodb_icp_tmp; set storage_engine= @save_storage_engine; diff --git a/mysql-test/t/innodb_icp.test b/mysql-test/t/innodb_icp.test index 0fb42355f96..f7828ec7bb2 100644 --- a/mysql-test/t/innodb_icp.test +++ b/mysql-test/t/innodb_icp.test @@ -12,6 +12,34 @@ set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; --source include/icp_tests.inc +--echo # +--echo # MDEV-5337: Wrong result in mariadb 5.5.32 with ORDER BY + LIMIT when index_condition_pushdown=on +--echo # MDEV-5512: Wrong result (WHERE clause ignored) with multiple clauses using Percona-XtraDB engine +--echo # + +create table t1(a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t2 (pk int primary key, + key1 char(32), + key2 char(32), + key(key1), + key(key2) +) engine=innodb; + +insert into t2 select + A.a+10*B.a+100*C.a, + concat('rare-', A.a+10*B.a), + concat('rare-', A.a+10*B.a) +from + t1 A, t1 B, t1 C; +update t2 set key1='frequent-val' where pk between 100 and 350; +select * from t2 ignore key(PRIMARY) +where key1='frequent-val' and key2 between 'rare-400' and 'rare-450' order by pk limit 2; + +drop table t1, t2; + + set optimizer_switch=@innodb_icp_tmp; set storage_engine= @save_storage_engine; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 289b75b5804..3e5652f2a16 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -19091,7 +19091,7 @@ check_reverse_order: tab->limit= best_select_limit; } } - else if (tab->type != JT_ALL) + else if (tab->type != JT_ALL || tab->select->quick) { /* We're about to use a quick access to the table.