diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 235d211840f..936ffac6828 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -6589,5 +6589,30 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL SELECT SUM(a) AS f1, a AS f2 FROM (t1, t2) HAVING f2 >= ALL (SELECT 4 UNION SELECT 5) AND f1 = 7; f1 f2 drop table t1,t2; +# +# LP BUG#1008686 Server crashes in subselect_union_engine::no_rows on SELECT with impossible +# WHERE and UNION in HAVING +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(7); +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +min_a a +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION t1 ALL NULL NULL NULL NULL 2 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +min_a a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 617d2e9e592..cb515b3c3d5 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2029,6 +2029,61 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where 2 SUBQUERY five ALL NULL NULL NULL NULL 5 Using where drop table ten, t1, five; +# +# LP BUG#1008773 Wrong result (NULL instead of a value) with no matching rows, subquery in FROM and HAVING +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +EXPLAIN +SELECT MAX(a), ( SELECT 1 FROM t2 ) AS bb FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY t2 system NULL NULL NULL NULL 1 +SELECT MAX(a), ( SELECT 1 FROM t2 ) AS bb FROM t1; +MAX(a) bb +NULL 1 +EXPLAIN +SELECT MAX(a), 1 in ( SELECT b FROM t2 ) AS bb FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY t2 system NULL NULL NULL NULL 1 +SELECT MAX(a), 1 in ( SELECT b FROM t2 ) AS bb FROM t1; +MAX(a) bb +NULL 1 +EXPLAIN +SELECT MAX(a), 1 >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +SELECT MAX(a), 1 >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; +MAX(a) bb +NULL 1 +EXPLAIN +SELECT MAX(a), ( SELECT 1 FROM t2 where b = a) AS bb FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +SELECT MAX(a), ( SELECT 1 FROM t2 where b = a) AS bb FROM t1; +MAX(a) bb +NULL NULL +EXPLAIN +SELECT MAX(a), a in ( SELECT b FROM t2 ) AS bb FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 +SELECT MAX(a), a in ( SELECT b FROM t2 ) AS bb FROM t1; +MAX(a) bb +NULL NULL +EXPLAIN +SELECT MAX(a), a >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 +SELECT MAX(a), a >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; +MAX(a) bb +NULL NULL +drop table t1, t2; set optimizer_switch=@subselect4_tmp; SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index b08148f8057..3ef60cdef85 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -6588,6 +6588,31 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL SELECT SUM(a) AS f1, a AS f2 FROM (t1, t2) HAVING f2 >= ALL (SELECT 4 UNION SELECT 5) AND f1 = 7; f1 f2 drop table t1,t2; +# +# LP BUG#1008686 Server crashes in subselect_union_engine::no_rows on SELECT with impossible +# WHERE and UNION in HAVING +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(7); +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +min_a a +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION t1 ALL NULL NULL NULL NULL 2 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +min_a a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 36d03d8db77..7d0aa2d8260 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -6584,6 +6584,31 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL SELECT SUM(a) AS f1, a AS f2 FROM (t1, t2) HAVING f2 >= ALL (SELECT 4 UNION SELECT 5) AND f1 = 7; f1 f2 drop table t1,t2; +# +# LP BUG#1008686 Server crashes in subselect_union_engine::no_rows on SELECT with impossible +# WHERE and UNION in HAVING +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(7); +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +min_a a +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION t1 ALL NULL NULL NULL NULL 2 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +min_a a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index 7fcacfda470..4c770063468 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -6595,6 +6595,31 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL SELECT SUM(a) AS f1, a AS f2 FROM (t1, t2) HAVING f2 >= ALL (SELECT 4 UNION SELECT 5) AND f1 = 7; f1 f2 drop table t1,t2; +# +# LP BUG#1008686 Server crashes in subselect_union_engine::no_rows on SELECT with impossible +# WHERE and UNION in HAVING +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(7); +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +min_a a +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION t1 ALL NULL NULL NULL NULL 2 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +min_a a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 405261c9ec6..6927abb21fd 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -6584,6 +6584,31 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL SELECT SUM(a) AS f1, a AS f2 FROM (t1, t2) HAVING f2 >= ALL (SELECT 4 UNION SELECT 5) AND f1 = 7; f1 f2 drop table t1,t2; +# +# LP BUG#1008686 Server crashes in subselect_union_engine::no_rows on SELECT with impossible +# WHERE and UNION in HAVING +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(7); +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +min_a a +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION t1 ALL NULL NULL NULL NULL 2 Using where +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +min_a a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index b02b1d4a4a0..0fb3ae9bb6a 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -5556,5 +5556,23 @@ SELECT SUM(a) AS f1, a AS f2 FROM (t1, t2) HAVING f2 >= ALL (SELECT 4 UNION SELE drop table t1,t2; +--echo # +--echo # LP BUG#1008686 Server crashes in subselect_union_engine::no_rows on SELECT with impossible +--echo # WHERE and UNION in HAVING +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(7); + +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; +SELECT MIN(a) AS min_a, a FROM t1 WHERE 0 HAVING a NOT IN ( SELECT 2 UNION SELECT 5 ) OR min_a != 1; + +EXPLAIN +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; +SELECT MIN(a) AS min_a, a FROM t1 WHERE 1=2 HAVING a NOT IN ( SELECT a from t1 UNION select a+1 from t1 ) OR min_a != 1; + +drop table t1; + --echo # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index e6ff625d3fe..832d6d85c21 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -1663,6 +1663,40 @@ explain select * from t1 where 33 in (select b from five) or c > 11; drop table ten, t1, five; +--echo # +--echo # LP BUG#1008773 Wrong result (NULL instead of a value) with no matching rows, subquery in FROM and HAVING +--echo # + +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); + +EXPLAIN +SELECT MAX(a), ( SELECT 1 FROM t2 ) AS bb FROM t1; +SELECT MAX(a), ( SELECT 1 FROM t2 ) AS bb FROM t1; + +EXPLAIN +SELECT MAX(a), 1 in ( SELECT b FROM t2 ) AS bb FROM t1; +SELECT MAX(a), 1 in ( SELECT b FROM t2 ) AS bb FROM t1; + +EXPLAIN +SELECT MAX(a), 1 >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; +SELECT MAX(a), 1 >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; + + +EXPLAIN +SELECT MAX(a), ( SELECT 1 FROM t2 where b = a) AS bb FROM t1; +SELECT MAX(a), ( SELECT 1 FROM t2 where b = a) AS bb FROM t1; + +EXPLAIN +SELECT MAX(a), a in ( SELECT b FROM t2 ) AS bb FROM t1; +SELECT MAX(a), a in ( SELECT b FROM t2 ) AS bb FROM t1; + +EXPLAIN +SELECT MAX(a), a >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; +SELECT MAX(a), a >= ALL ( SELECT b FROM t2 ) AS bb FROM t1; + +drop table t1, t2; set optimizer_switch=@subselect4_tmp; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 4acac68fe6b..9a3f5bd8a51 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -904,6 +904,15 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type) void Item_maxmin_subselect::no_rows_in_result() { + /* + Subquery predicates outside of the SELECT list must be evaluated in order + to possibly filter the special result row generated for implicit grouping + if the subquery is in the HAVING clause. + If the predicate is constant, we need its actual value in the only result + row for queries with implicit grouping. + */ + if (parsing_place != SELECT_LIST || const_item()) + return; value= Item_cache::get_cache(new Item_null()); null_value= 0; was_values= 0; @@ -913,6 +922,15 @@ void Item_maxmin_subselect::no_rows_in_result() void Item_singlerow_subselect::no_rows_in_result() { + /* + Subquery predicates outside of the SELECT list must be evaluated in order + to possibly filter the special result row generated for implicit grouping + if the subquery is in the HAVING clause. + If the predicate is constant, we need its actual value in the only result + row for queries with implicit grouping. + */ + if (parsing_place != SELECT_LIST || const_item()) + return; value= Item_cache::get_cache(new Item_null()); reset(); make_const(); @@ -1375,6 +1393,15 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg) void Item_exists_subselect::no_rows_in_result() { + /* + Subquery predicates outside of the SELECT list must be evaluated in order + to possibly filter the special result row generated for implicit grouping + if the subquery is in the HAVING clause. + If the predicate is constant, we need its actual value in the only result + row for queries with implicit grouping. + */ + if (parsing_place != SELECT_LIST || const_item()) + return; value= 0; null_value= 0; make_const(); @@ -2719,6 +2746,15 @@ void Item_allany_subselect::print(String *str, enum_query_type query_type) void Item_allany_subselect::no_rows_in_result() { + /* + Subquery predicates outside of the SELECT list must be evaluated in order + to possibly filter the special result row generated for implicit grouping + if the subquery is in the HAVING clause. + If the predicate is constant, we need its actual value in the only result + row for queries with implicit grouping. + */ + if (parsing_place != SELECT_LIST || const_item()) + return; value= 0; null_value= 0; was_null= 0; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 0e0f61aedd9..6b00cd18d6e 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -159,8 +159,8 @@ public: null_value= 1; } /** - Set the subquery result to the default value for the predicate when the - subquery is known to produce an empty result. + Set the subquery result to a default value consistent with the semantics of + the result row produced for queries with implicit grouping. */ void no_rows_in_result()= 0; virtual bool select_transformer(JOIN *join);