diff options
author | unknown <timour@askmonty.org> | 2011-08-27 00:40:29 +0300 |
---|---|---|
committer | unknown <timour@askmonty.org> | 2011-08-27 00:40:29 +0300 |
commit | 2df1914791030714196c3d829187891a97be54dc (patch) | |
tree | d24362560b461dbf256a1b427c543610548b28f1 /sql | |
parent | ee28dec85885a1579758d9184ecb63ce810e738f (diff) | |
download | mariadb-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.cc | 7 |
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. |