diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 98 |
1 files changed, 48 insertions, 50 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2572c8bd56d..bf0e435a6c5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6017,7 +6017,7 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint, { TABLE *table= s->table; double sel= table->cond_selectivity; - double table_records= (double)table->stat_records(); + double table_records= table->stat_records(); dbl_records= table_records * sel; return dbl_records; } @@ -6043,7 +6043,7 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint, if (s->table->quick_condition_rows != s->found_records) records= s->table->quick_condition_rows; - dbl_records= (double)records; + dbl_records= records; return dbl_records; } @@ -8799,8 +8799,6 @@ bool JOIN::get_best_combination() form= table[tablenr]= j->table; used_tables|= form->map; form->reginfo.join_tab=j; - if (!*j->on_expr_ref) - form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN DBUG_PRINT("info",("type: %d", j->type)); if (j->type == JT_CONST) goto loop_end; // Handled in make_join_stat.. @@ -9363,8 +9361,6 @@ static void add_not_null_conds(JOIN *join) UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1); not_null_item is the t1.f1, but it's referred_tab is 0. */ - if (!referred_tab) - continue; if (!(notnull= new (join->thd->mem_root) Item_func_isnotnull(join->thd, item))) DBUG_VOID_RETURN; @@ -9376,16 +9372,19 @@ static void add_not_null_conds(JOIN *join) */ if (notnull->fix_fields(join->thd, ¬null)) DBUG_VOID_RETURN; + DBUG_EXECUTE("where",print_where(notnull, - referred_tab->table->alias.c_ptr(), - QT_ORDINARY);); + (referred_tab ? + referred_tab->table->alias.c_ptr() : + "outer_ref_cond"), + QT_ORDINARY);); if (!tab->first_inner) - { - COND *new_cond= referred_tab->join == join ? + { + COND *new_cond= (referred_tab && referred_tab->join == join) ? referred_tab->select_cond : join->outer_ref_cond; add_cond_and_fix(join->thd, &new_cond, notnull); - if (referred_tab->join == join) + if (referred_tab && referred_tab->join == join) referred_tab->set_select_cond(new_cond, __LINE__); else join->outer_ref_cond= new_cond; @@ -9537,7 +9536,10 @@ make_outerjoin_info(JOIN *join) tab->cond_equal= tbl->cond_equal; if (embedding && !embedding->is_active_sjm()) tab->first_upper= embedding->nested_join->first_nested; - } + } + else if (!embedding) + tab->table->reginfo.not_exists_optimize= 0; + for ( ; embedding ; embedding= embedding->embedding) { if (embedding->is_active_sjm()) @@ -9547,7 +9549,10 @@ make_outerjoin_info(JOIN *join) } /* Ignore sj-nests: */ if (!(embedding->on_expr && embedding->outer_join)) + { + tab->table->reginfo.not_exists_optimize= 0; continue; + } NESTED_JOIN *nested_join= embedding->nested_join; if (!nested_join->counter) { @@ -9563,17 +9568,10 @@ make_outerjoin_info(JOIN *join) } if (!tab->first_inner) tab->first_inner= nested_join->first_nested; - if (tab->table->reginfo.not_exists_optimize) - tab->first_inner->table->reginfo.not_exists_optimize= 1; if (++nested_join->counter < nested_join->n_tables) break; /* Table tab is the last inner table for nested join. */ nested_join->first_nested->last_inner= tab; - if (tab->first_inner->table->reginfo.not_exists_optimize) - { - for (JOIN_TAB *join_tab= tab->first_inner; join_tab <= tab; join_tab++) - join_tab->table->reginfo.not_exists_optimize= 1; - } } } DBUG_RETURN(FALSE); @@ -10348,7 +10346,7 @@ void JOIN::drop_unused_derived_keys() continue; if (!tmp_tbl->pos_in_table_list->is_materialized_derived()) continue; - if (tmp_tbl->max_keys > 1) + if (tmp_tbl->max_keys > 1 && !tab->is_ref_for_hash_join()) tmp_tbl->use_index(tab->ref.key); if (tmp_tbl->s->keys) { @@ -15874,7 +15872,9 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, DBUG_ASSERT(thd == table->in_use); new_field= item->Item::create_tmp_field(false, table); - if (copy_func && item->real_item()->is_result_field()) + if (copy_func && + (item->is_result_field() || + (item->real_item()->is_result_field()))) *((*copy_func)++) = item; // Save for copy_funcs if (modify_item) item->set_result_field(new_field); @@ -18480,32 +18480,41 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, first_unmatched->found= 1; for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++) { + /* + Check whether 'not exists' optimization can be used here. + If tab->table->reginfo.not_exists_optimize is set to true + then WHERE contains a conjunctive predicate IS NULL over + a non-nullable field of tab. When activated this predicate + will filter out all records with matches for the left part + of the outer join whose inner tables start from the + first_unmatched table and include table tab. To safely use + 'not exists' optimization we have to check that the + IS NULL predicate is really activated, i.e. all guards + that wrap it are in the 'open' state. + */ + bool not_exists_opt_is_applicable= + tab->table->reginfo.not_exists_optimize; + for (JOIN_TAB *first_upper= first_unmatched->first_upper; + not_exists_opt_is_applicable && first_upper; + first_upper= first_upper->first_upper) + { + if (!first_upper->found) + not_exists_opt_is_applicable= false; + } /* Check all predicates that has just been activated. */ /* Actually all predicates non-guarded by first_unmatched->found will be re-evaluated again. It could be fixed, but, probably, it's not worth doing now. */ - /* - not_exists_optimize has been created from a - select_cond containing 'is_null'. This 'is_null' - predicate is still present on any 'tab' with - 'not_exists_optimize'. Furthermore, the usual rules - for condition guards also applies for - 'not_exists_optimize' -> When 'is_null==false' we - know all cond. guards are open and we can apply - the 'not_exists_optimize'. - */ - DBUG_ASSERT(!(tab->table->reginfo.not_exists_optimize && - !tab->select_cond)); - if (tab->select_cond && !tab->select_cond->val_int()) { /* The condition attached to table tab is false */ - if (tab == join_tab) { found= 0; + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); } else { @@ -18514,21 +18523,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, not to the last table of the current nest level. */ join->return_tab= tab; - } - - if (tab->table->reginfo.not_exists_optimize) - { - /* - When not_exists_optimize is set: No need to further - explore more rows of 'tab' for this partial result. - Any found 'tab' matches are known to evaluate to 'false'. - Returning .._NO_MORE_ROWS will skip rem. 'tab' rows. - */ - DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); - } - else if (tab != join_tab) - { - DBUG_RETURN(NESTED_LOOP_OK); + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + else + DBUG_RETURN(NESTED_LOOP_OK); } } } |