From db4738a18a141955465b7a7e139fe25c832d6c44 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Oct 2010 23:48:43 +0300 Subject: [PATCH] Fixed LP bug #609121 The bug was a result of missing logic to handle the case when there are 'expensive' predicates that are not evaluated during constant table optimization. Such is the case for the IN predicate, which is considered expensive if it is computed via materialization. In general this bug can be triggered with any expensive predicate instead of IN. When FALSE constant predicates are not evaluated during constant optimization, the execution path changes so that instead of setting JOIN::zero_result_cause after make_join_select, and exiting JOIN::exec via the call to return_zero_rows(), execution ends in JOIN::exec in the branch: if (join->tables == join->const_tables) { ... else if (join->send_row_on_empty_set()) ... rc= join->result->send_data(*columns_list); } Unlike return_zero_rows(), this branch didn't evaluate the having clause of the query. The patch adds a call to evaluate the HAVING clause of a query even when all tables are constant, because even for an empty result set some aggregate functions may produce a NULL value. --- mysql-test/r/subselect_mat.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect_mat.test | 22 ++++++++++++++++++++++ sql/sql_select.h | 3 ++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index 52795ec0f60..38cb13a26bc 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -1272,3 +1272,28 @@ a a in (select a from t1) 1 0 2 0 drop table t0, t1; +# +# LPBUG#609121: RQG: wrong result on aggregate + NOT IN + HAVING and +# partial_match_table_scan=on +# +create table t1 (c1 int); +create table t2 (c2 int); +insert into t1 values (1); +insert into t2 values (2); +set @@optimizer_switch='semijoin=off'; +EXPLAIN +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +2 SUBQUERY t2 system NULL NULL NULL NULL 1 +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2); +c1_sum +NULL +EXPLAIN +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +2 SUBQUERY t2 system NULL NULL NULL NULL 1 +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum; +c1_sum +drop table t1, t2; diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test index 1c2869c628a..0209bf66a57 100644 --- a/mysql-test/t/subselect_mat.test +++ b/mysql-test/t/subselect_mat.test @@ -921,3 +921,25 @@ execute s; update t1 set a=123; execute s; drop table t0, t1; + + +--echo # +--echo # LPBUG#609121: RQG: wrong result on aggregate + NOT IN + HAVING and +--echo # partial_match_table_scan=on +--echo # + +create table t1 (c1 int); +create table t2 (c2 int); +insert into t1 values (1); +insert into t2 values (2); + +set @@optimizer_switch='semijoin=off'; + +EXPLAIN +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2); +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2); +EXPLAIN +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum; +SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum; + +drop table t1, t2; diff --git a/sql/sql_select.h b/sql/sql_select.h index e095974d008..ac115cea4e6 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1722,7 +1722,8 @@ public: bool send_row_on_empty_set() { return (do_send_rows && tmp_table_param.sum_func_count != 0 && - !group_list && having_value != Item::COND_FALSE); + !group_list && having_value != Item::COND_FALSE && + (!having || having->val_int())); } bool change_result(select_result *result); bool is_top_level_join() const