From: Tor Didriksen Date: February 2 2011 9:22am Subject: bzr push into mysql-5.5 branch (tor.didriksen:3294 to 3295) Bug#52123 List-Archive: http://lists.mysql.com/commits/130191 X-Bug: 52123 Message-Id: <20110202092229.0A0FE3768@atum07.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3295 Tor Didriksen 2011-02-02 Backport of fix for Bug#52123 modified: mysql-test/r/func_group.result mysql-test/t/func_group.test sql/item_sum.cc sql/item_sum.h 3294 Ole John Aske 2011-02-01 Fix for bug#58490, 'Incorrect result in multi level OUTER JOIN in combination with IS NULL' As this bug is a duplicate of bug#49322, it also includes test cases covering this bugreport Qualifying an OUTER JOIN with the condition 'WHERE IS NULL', where is declared as 'NOT NULL' causes the 'not_exists_optimize' to be enabled by the optimizer. In evaluate_join_record() the 'not_exists_optimize' caused 'NESTED_LOOP_NO_MORE_ROWS' to be returned immediately when a matching row was found. However, as the 'not_exists_optimize' is derived from 'JOIN_TAB::select_cond', the usual rules for condition guards also applies for 'not_exist_optimize'. It is therefore incorrect to check 'not_exists_optimize' without ensuring that all guards protecting it is 'open'. This fix uses the fact that 'not_exists_optimize' is derived from a 'is_null' predicate term in 'tab->select_cond'. Furthermore, 'is_null' will evaluate to 'false' for any 'non-null' rows once all guards protecting the is_null is open. We can use this knowledge as an implicit guard check for the 'not_exists_optimize' by moving 'if (...not_exists_optimize)' inside the handling of 'select_cond==false'. It will then not take effect before its guards are open. We also add an assert which requires that a 'not_exists_optimize' always comes together with a select_cond. (containing 'is_null'). modified: mysql-test/r/join_outer.result mysql-test/t/join_outer.test sql/sql_select.cc === modified file 'mysql-test/r/func_group.result' --- a/mysql-test/r/func_group.result 2010-12-21 12:32:15 +0000 +++ b/mysql-test/r/func_group.result 2011-02-02 09:18:44 +0000 @@ -1739,6 +1739,16 @@ SELECT RELEASE_LOCK('aaaaaaaaaaaaaaaaa') # End of 5.1 tests # +# Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(), +# file .\item_sum.cc, line 587 +# +CREATE TABLE t1(a int, KEY(a)); +INSERT INTO t1 VALUES (1), (2); +SELECT 1 FROM t1 ORDER BY AVG(DISTINCT a); +1 +1 +DROP TABLE t1; +# # Bug#55648: Server crash on MIN/MAX on maximum time value # CREATE TABLE t1(c1 TIME NOT NULL); === modified file 'mysql-test/t/func_group.test' --- a/mysql-test/t/func_group.test 2010-12-21 12:32:15 +0000 +++ b/mysql-test/t/func_group.test 2011-02-02 09:18:44 +0000 @@ -1120,6 +1120,17 @@ SELECT RELEASE_LOCK('aaaaaaaaaaaaaaaaa') --echo # --echo End of 5.1 tests +### +--echo # +--echo # Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(), +--echo # file .\item_sum.cc, line 587 +--echo # + +CREATE TABLE t1(a int, KEY(a)); +INSERT INTO t1 VALUES (1), (2); +SELECT 1 FROM t1 ORDER BY AVG(DISTINCT a); +DROP TABLE t1; + --echo # --echo # Bug#55648: Server crash on MIN/MAX on maximum time value --echo # === modified file 'sql/item_sum.cc' --- a/sql/item_sum.cc 2010-12-29 00:26:31 +0000 +++ b/sql/item_sum.cc 2011-02-02 09:18:44 +0000 @@ -556,24 +556,27 @@ Item *Item_sum::set_arg(uint i, THD *thd int Item_sum::set_aggregator(Aggregator::Aggregator_type aggregator) { - if (aggr) + /* + Dependent subselects may be executed multiple times, making + set_aggregator to be called multiple times. The aggregator type + will be the same, but it needs to be reset so that it is + reevaluated with the new dependent data. + This function may also be called multiple times during query optimization. + In this case, the type may change, so we delete the old aggregator, + and create a new one. + */ + if (aggr && aggregator == aggr->Aggrtype()) { - /* - Dependent subselects may be executed multiple times, making - set_aggregator to be called multiple times. The aggregator type - will be the same, but it needs to be reset so that it is - reevaluated with the new dependent data. - */ - DBUG_ASSERT(aggregator == aggr->Aggrtype()); aggr->clear(); return FALSE; } + + delete aggr; switch (aggregator) { case Aggregator::DISTINCT_AGGREGATOR: aggr= new Aggregator_distinct(this); break; - case Aggregator::SIMPLE_AGGREGATOR: aggr= new Aggregator_simple(this); break; === modified file 'sql/item_sum.h' --- a/sql/item_sum.h 2011-01-17 09:39:59 +0000 +++ b/sql/item_sum.h 2011-02-02 09:18:44 +0000 @@ -461,10 +461,9 @@ public: */ virtual void no_rows_in_result() { - if (!aggr) - set_aggregator(with_distinct ? - Aggregator::DISTINCT_AGGREGATOR : - Aggregator::SIMPLE_AGGREGATOR); + set_aggregator(with_distinct ? + Aggregator::DISTINCT_AGGREGATOR : + Aggregator::SIMPLE_AGGREGATOR); aggregator_clear(); } virtual void make_unique() { force_copy_fields= TRUE; } @@ -515,11 +514,10 @@ public: quick_group= with_distinct ? 0 : 1; } - /** + /* Set the type of aggregation : DISTINCT or not. - Called when the final determination is done about the aggregation - type and the object is about to be used. + May be called multiple times. */ int set_aggregator(Aggregator::Aggregator_type aggregator); No bundle (reason: useless for push emails).