From 88d3d853f4802ea48bcbe0b017d9e2403895632d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Jun 2012 17:03:09 +0300 Subject: [PATCH 1/2] Fix bug lp:1008773 Analysis: Queries with implicit grouping (there is aggregate, but no group by) follow some non-obvious semantics in the case of empty result set. Aggregate functions produce some special "natural" value depending on the function. For instance MIN/MAX return NULL, COUNT returns 0. The complexity comes from non-aggregate expressions in the select list. If the non-aggregate expression is a constant, it can be computed, so we should return its value, however if the expression is non-constant, and depends on columns from the empty result set, then the only meaningful value is NULL. The cause of the wrong result was that for subqueries the optimizer didn't make a difference between constant and non-constant ones in the case of empty result for implicit grouping. Solution: In all implementations of Item_subselect::no_rows_in_result() check if the subquery predicate is constant. If it is constant, do not set it to the default value for implicit grouping, instead let it be evaluated. --- mysql-test/r/subselect4.result | 55 ++++++++++++++++++++++++++++++++++ mysql-test/t/subselect4.test | 34 +++++++++++++++++++++ sql/item_subselect.cc | 8 +++++ 3 files changed, 97 insertions(+) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 5e2baf47aec..8573b5bb8c4 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2139,6 +2139,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/t/subselect4.test b/mysql-test/t/subselect4.test index 92b34db05e4..e978ebdbfcc 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -1777,6 +1777,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 cae1a9f7541..5af8eb9ebc9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -892,6 +892,8 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type) void Item_maxmin_subselect::no_rows_in_result() { + if (const_item()) + return; value= Item_cache::get_cache(new Item_null()); null_value= 0; was_values= 0; @@ -901,6 +903,8 @@ void Item_maxmin_subselect::no_rows_in_result() void Item_singlerow_subselect::no_rows_in_result() { + if (const_item()) + return; value= Item_cache::get_cache(new Item_null()); reset(); make_const(); @@ -1363,6 +1367,8 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg) void Item_exists_subselect::no_rows_in_result() { + if (const_item()) + return; value= 0; null_value= 0; make_const(); @@ -2707,6 +2713,8 @@ void Item_allany_subselect::print(String *str, enum_query_type query_type) void Item_allany_subselect::no_rows_in_result() { + if (const_item()) + return; value= 0; null_value= 0; was_null= 0; From db6dbadb5a9edd9e93398b6afe8e3196eb768e0a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jun 2012 11:33:24 +0300 Subject: [PATCH 2/2] Fix bug lp:1008686 Analysis: The fix for bug lp:985667 implements the method Item_subselect::no_rows_in_result() for all main kinds of subqueries. The purpose of this method is to be called from return_zero_rows() and set Items to some default value in the case when a query returns no rows. Aggregates and subqueries require special treatment in this case. Every implementation of Item_subselect::no_rows_in_result() called Item_subselect::make_const() to set the subquery predicate to its default value irrespective of where the predicate was located in the query. Once the predicate was set to a constant it was never executed. At the same time, the JOIN object of the fake select for UNIONs (the one used for the final result of the UNION), was set after all subqueries in the union were executed. Since we set the subquery as constant, it was never executed, and the corresponding JOIN was never created. In order to decide whether the result of NOT IN is NULL or FALSE, Item_in_optimizer needs to check if the subquery result was empty or not. This is where we got the crash, because subselect_union_engine::no_rows() checks for unit->fake_select_lex->join->send_records, and the join object was NULL. Solution: If a subquery is in the HAVING clause it must be evaluated in order to know its result, so that we can properly filter the result records. Once subqueries in the HAVING clause are executed even in the case of no result rows, this specific crash will be solved, because the UNION will be executed, and its JOIN will be constructed. Therefore the fix for this crash is to narrow the fix for lp:985667, and to apply Item_subselect::no_rows_in_result() only when the subquery predicate is in the SELECT clause. --- mysql-test/r/subselect.result | 25 ++++++++++++++++ mysql-test/r/subselect_no_mat.result | 25 ++++++++++++++++ mysql-test/r/subselect_no_opts.result | 25 ++++++++++++++++ mysql-test/r/subselect_no_scache.result | 25 ++++++++++++++++ mysql-test/r/subselect_no_semijoin.result | 25 ++++++++++++++++ mysql-test/t/subselect.test | 18 ++++++++++++ sql/item_subselect.cc | 36 ++++++++++++++++++++--- sql/item_subselect.h | 4 +-- 8 files changed, 177 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 70096a68a34..024dca5d1bb 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -6112,5 +6112,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/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 671a5df213b..e8c084f9700 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -6111,6 +6111,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 e70c07a5894..ace1f198853 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -6107,6 +6107,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 253be05cc5b..32f24f9cf14 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -6118,6 +6118,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 a6e87097c66..3860bb9fb18 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -6107,6 +6107,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 e2d829996b7..a476551ff08 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -5190,5 +5190,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/sql/item_subselect.cc b/sql/item_subselect.cc index 5af8eb9ebc9..16f754575f5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -892,7 +892,14 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type) void Item_maxmin_subselect::no_rows_in_result() { - if (const_item()) + /* + 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; @@ -903,7 +910,14 @@ void Item_maxmin_subselect::no_rows_in_result() void Item_singlerow_subselect::no_rows_in_result() { - if (const_item()) + /* + 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(); @@ -1367,7 +1381,14 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg) void Item_exists_subselect::no_rows_in_result() { - if (const_item()) + /* + 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; @@ -2713,7 +2734,14 @@ void Item_allany_subselect::print(String *str, enum_query_type query_type) void Item_allany_subselect::no_rows_in_result() { - if (const_item()) + /* + 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; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 7f2aa857459..0735df2fb5c 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -147,8 +147,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);