diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/opt_range.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 72 |
2 files changed, 73 insertions, 1 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 32e6a767f15..bd5f25d67c2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8999,6 +8999,8 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, } if (key1->type == SEL_ARG::MAYBE_KEY) { + if (key2->type == SEL_ARG::KEY_RANGE) + return key2; key1->right= key1->left= &null_element; key1->next= key1->prev= 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 87a45a1baed..ae26458d451 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10543,6 +10543,74 @@ make_outerjoin_info(JOIN *join) } +/* + @brief + Build a temporary join prefix condition for JOIN_TABs up to the last tab + + @param ret OUT the condition is returned here + + @return + false OK + true Out of memory + + @detail + Walk through the join prefix (from the first table to the last_tab) and + build a condition: + + join_tab_1_cond AND join_tab_2_cond AND ... AND last_tab_conds + + The condition is only intended to be used by the range optimizer, so: + - it is not normalized (can have Item_cond_and inside another + Item_cond_and) + - it does not include join->exec_const_cond and other similar conditions. +*/ + +bool build_tmp_join_prefix_cond(JOIN *join, JOIN_TAB *last_tab, Item **ret) +{ + THD *const thd= join->thd; + Item_cond_and *all_conds= NULL; + + Item *res= NULL; + + // Pick the ON-expression. Use the same logic as in get_sargable_cond(): + if (last_tab->on_expr_ref) + res= *last_tab->on_expr_ref; + else if (last_tab->table->pos_in_table_list && + last_tab->table->pos_in_table_list->embedding && + !last_tab->table->pos_in_table_list->embedding->sj_on_expr) + { + res= last_tab->table->pos_in_table_list->embedding->on_expr; + } + + for (JOIN_TAB *tab= first_depth_first_tab(join); + tab; + tab= next_depth_first_tab(join, tab)) + { + if (tab->select_cond) + { + if (!res) + res= tab->select_cond; + else + { + if (!all_conds) + { + if (!(all_conds= new (thd->mem_root)Item_cond_and(thd, res, + tab->select_cond))) + return true; + res= all_conds; + } + else + all_conds->add(tab->select_cond, thd->mem_root); + } + } + if (tab == last_tab) + break; + } + *ret= all_conds? all_conds: res; + return false; +} + + static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { @@ -10890,7 +10958,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { /* Join with outer join condition */ COND *orig_cond=sel->cond; - sel->cond= and_conds(thd, sel->cond, *tab->on_expr_ref); + + if (build_tmp_join_prefix_cond(join, tab, &sel->cond)) + return true; /* We can't call sel->cond->fix_fields, |