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 <column> IS NULL',
where <column> 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).
| Thread |
|---|
| • bzr push into mysql-5.5 branch (tor.didriksen:3294 to 3295) Bug#52123 | Tor Didriksen | 2 Feb |