From ad88eabd35b34c557de1a4eede6c8fe9201dc01e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Jul 2006 00:34:37 +0400 Subject: [PATCH 1/2] Fixed bug#16302: Quantified subquery without any tables gives wrong results The ALL/ANY subqueries are the subject of MIN/MAX optimization. The matter of this optimization is to embed MIN() or MAX() function into the subquery in order to get only one row by which we can tell whether the expression with ALL/ANY subquery is true or false. But when it is applied to a subquery like 'select a_constant' the reported bug occurs. As no tables are specified in the subquery the do_select() function isn't called for the optimized subquery and thus no values have been added to a MIN()/MAX() function and it returns NULL instead of a_constant. This leads to a wrong query result. For the subquery like 'select a_constant' there is no reason to apply MIN/MAX optimization because the subquery anyway will return at most one row. Thus the Item_maxmin_subselect class is more appropriate for handling such subqueries. The Item_in_subselect::single_value_transformer() function now checks whether tables are specified for the subquery. If no then this subselect is handled like a UNION using an Item_maxmin_subselect object. mysql-test/t/subselect.test: Added test case for bug#16302: Quantified subquery without any tables gives wrong results mysql-test/r/subselect.result: Added test case for bug#16302: Quantified subquery without any tables gives wrong results sql/item_subselect.cc: Fixed bug#16302: Quantified subquery without any tables gives wrong results The Item_in_subselect::single_value_transformer() function now checks whether tables are specified for the subquery. If no then this subselect is handled like a UNION using an Item_maxmin_subselect object. --- mysql-test/r/subselect.result | 18 ++++++++++++++++++ mysql-test/t/subselect.test | 10 ++++++++++ sql/item_subselect.cc | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 7925715a8b7..108f5dd1973 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2835,3 +2835,21 @@ a 4 DROP TABLE t1,t2,t3; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +select 1 from dual where 1 < any (select 2); +1 +1 +select 1 from dual where 1 < all (select 2); +1 +1 +select 1 from dual where 2 > any (select 1); +1 +1 +select 1 from dual where 2 > all (select 1); +1 +1 +select 1 from dual where 1 < any (select 2 from dual); +1 +1 +select 1 from dual where 1 < all (select 2 from dual where 1!=1); +1 +1 diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index cbc7a3afb5f..f7d5e7f8713 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1820,4 +1820,14 @@ DROP TABLE t1,t2,t3; purge master logs before (select adddate(current_timestamp(), interval -4 day)); + +# +# Bug#16302: Quantified subquery without any tables gives wrong results +# +select 1 from dual where 1 < any (select 2); +select 1 from dual where 1 < all (select 2); +select 1 from dual where 2 > any (select 1); +select 1 from dual where 2 > all (select 1); +select 1 from dual where 1 < any (select 2 from dual); +select 1 from dual where 1 < all (select 2 from dual where 1!=1); # End of 4.1 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8241a8e0402..f6f8eec9af5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -705,7 +705,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, if (!select_lex->group_list.elements && !select_lex->having && !select_lex->with_sum_func && - !(select_lex->next_select())) + !(select_lex->next_select()) && + select_lex->table_list.elements) { Item_sum_hybrid *item; if (func->l_op()) From d2bbf288a93ee50829e09d8faaf26dc0d6125476 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Jul 2006 01:52:18 +0400 Subject: [PATCH 2/2] Fixed bug#18503: Queries with a quantified subquery returning empty set may return a wrong result. An Item_sum_hybrid object has the was_values flag which indicates whether any values were added to the sum function. By default it is set to true and reset to false on any no_rows_in_result() call. This method is called only in return_zero_rows() function. An ALL/ANY subquery can be optimized by MIN/MAX optimization. The was_values flag is used to indicate whether the subquery has returned at least one row. This bug occurs because return_zero_rows() is called only when we know that the select will return zero rows before starting any scans but often such information is not known. In the reported case the return_zero_rows() function is not called and the was_values flag is not reset to false and yet the subquery return no rows Item_func_not_all and Item_func_nop_all functions return a wrong comparison result. The end_send_group() function now calls no_rows_in_result() for each item in the fields_list if there is no rows were found for the (sub)query. mysql-test/t/subselect.test: Added test case for bug#18503: Queries with a quantified subquery returning empty set may return a wrong result. mysql-test/r/subselect.result: Added test case for bug#18503: Queries with a quantified subquery returning empty set may return a wrong result. sql/sql_select.cc: Fixed bug#18503: Queries with a quantified subquery returning empty set may return a wrong result. The end_send_group() function now calls no_rows_in_result() for each item in the fields_list if there is no matching rows were found. --- mysql-test/r/subselect.result | 15 +++++++++++++++ mysql-test/t/subselect.test | 14 ++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 34 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 7925715a8b7..2e2e28365d7 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2835,3 +2835,18 @@ a 4 DROP TABLE t1,t2,t3; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 INT); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2); +f1 +1 +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE 1=0); +f1 +1 +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE f2=0); +f1 +1 +DROP TABLE t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index cbc7a3afb5f..1012458a31b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1820,4 +1820,18 @@ DROP TABLE t1,t2,t3; purge master logs before (select adddate(current_timestamp(), interval -4 day)); + +# +# Bug#18503: Queries with a quantified subquery returning empty set may +# return a wrong result. +# +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 INT); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE 1=0); +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE f2=0); +DROP TABLE t1, t2; # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 709ff9726bb..8b3cfab8533 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6746,8 +6746,13 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (!join->first_record) { + List_iterator_fast it(*join->fields); + Item *item; /* No matching rows for group function */ join->clear(); + + while ((item= it++)) + item->no_rows_in_result(); } if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having