diff options
author | unknown <timour@askmonty.org> | 2011-07-04 14:51:16 +0300 |
---|---|---|
committer | unknown <timour@askmonty.org> | 2011-07-04 14:51:16 +0300 |
commit | 59784abeadc4014f357e44ae507c62dc93c641b3 (patch) | |
tree | a8f6c46f48b05b15f8cfc0cca91778fd71e9130a /sql/opt_range.cc | |
parent | 55165f51747fc7d5f2b510d778fcdd8ffded808d (diff) | |
download | mariadb-git-59784abeadc4014f357e44ae507c62dc93c641b3.tar.gz |
Fix LP bug lp:802979
Analysis:
This bug consists of two related problems that are
result of too early evaluation of single-row subqueries
during the optimization phase of the outer query.
Several optimizer code paths try to evaluate single-row
subqueries in order to produce a constant and use that
constant for further optimzation.
When the execution of the subquery peforms destructive
changes to the representation of the subquery, and these
changes are not anticipated by the subsequent optimization
phases of the outer query, we tipically get a crash or
failed assert.
Specifically, in this bug the inner-most suqbuery with
DISTINCT triggers a substitution of the original JOIN
object by a single-table JOIN object with a temp table
needed to perform the DISTINCT operation (created by
JOIN::make_simple_join).
This substitution breaks EXPLAIN because:
a) in the first example JOIN::cleanup no longer can
reach the original table of the innermost subquery, and
close all indexes, and
b) in this second test query, EXPLAIN attempts to print
the name of the internal temp table, and crashes because
the temp table has no name (NULL pointer instead).
Solution:
a) fully disable subquery evaluation during optimization
in all cases - both for constant propagation and range
optimization, and
b) change JOIN::join_free() to perform cleanup irrespective
of EXPLAIN or not.
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r-- | sql/opt_range.cc | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3b672d6b704..88cd2a5e4cd 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7292,7 +7292,7 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond) case Item_func::MULT_EQUAL_FUNC: { Item_equal *item_equal= (Item_equal *) cond; - if (!(value= item_equal->get_const())) + if (!(value= item_equal->get_const()) || value->is_expensive()) DBUG_RETURN(0); Item_equal_fields_iterator it(*item_equal); ref_tables= value->used_tables(); @@ -7325,6 +7325,9 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond) } else DBUG_RETURN(0); + if (value && value->is_expensive()) + DBUG_RETURN(0); + ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv); } |