summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <timour@askmonty.org>2011-08-27 00:40:29 +0300
committerunknown <timour@askmonty.org>2011-08-27 00:40:29 +0300
commit2df1914791030714196c3d829187891a97be54dc (patch)
treed24362560b461dbf256a1b427c543610548b28f1 /sql
parentee28dec85885a1579758d9184ecb63ce810e738f (diff)
downloadmariadb-git-2df1914791030714196c3d829187891a97be54dc.tar.gz
Fix bug lp:827416
Analysis: Constant table optimization of the outer query finds that the right side of the equality is a constant that can be used for an eq_ref access to fetch one row from t1, and substitute t1 with a constant. Thus constant optimization triggers evaluation of the subquery during the optimize phase of the outer query. The innermost subquery requires a plan with a temporary table because with InnoDB tables the exact count of rows is not known, and the empty tables cannot be optimzied way. JOIN::exec for the innermost subquery substitutes the subquery tables with a temporary table. When EXPLAIN gets to print the tables in the innermost subquery, EXPLAIN needs to print the name of each table through the corresponding TABLE_LIST object. However, the temporary table created during execution doesn't have a corresponding TABLE_LIST, so we get a null pointer exception. Solution: The solution is to forbid using expensive constant expressions for eq_ref access for contant table optimization. Notice that eq_ref with a subquery providing the value is still possible during regular execution.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_select.cc7
1 files changed, 7 insertions, 0 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6d2c7400d3d..54c1215164e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2993,6 +2993,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
uint i,table_count,const_count,key;
table_map found_const_table_map, all_table_map, found_ref, refs;
key_map const_ref, eq_part;
+ bool has_expensive_keyparts;
TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
KEYUSE *keyuse,*start_keyuse;
@@ -3314,12 +3315,17 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
refs=0;
const_ref.clear_all();
eq_part.clear_all();
+ has_expensive_keyparts= false;
do
{
if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
{
if (!((~found_const_table_map) & keyuse->used_tables))
+ {
const_ref.set_bit(keyuse->keypart);
+ if (keyuse->val->is_expensive())
+ has_expensive_keyparts= true;
+ }
else
refs|=keyuse->used_tables;
eq_part.set_bit(keyuse->keypart);
@@ -3341,6 +3347,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (table->key_info[key].flags & HA_NOSAME)
{
if (const_ref == eq_part &&
+ !has_expensive_keyparts &&
!((outer_join & table->map) &&
(*s->on_expr_ref)->is_expensive()))
{ // Found everything for ref.