diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2011-05-29 12:58:44 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2011-05-29 12:58:44 +0400 |
commit | 5cd18326c2167ddf1fe989154c519809cd26f175 (patch) | |
tree | 0166109cba0ae1b9b6bfa81d8c38ecd1a0fe2276 /sql/item_cmpfunc.cc | |
parent | 8ce2e1bcbe1f00b6030b1c82ea62b3a64b1d0de9 (diff) | |
parent | 4efe046352f61cc7b8a44a604f96f8b68cf155c0 (diff) | |
download | mariadb-git-5cd18326c2167ddf1fe989154c519809cd26f175.tar.gz |
Merge 5.3->main -> 5.3-mwl90
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 57 |
1 files changed, 18 insertions, 39 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f631fc141de..bae8c4308e1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5813,28 +5813,12 @@ Item* Item_equal::get_first(Item *field_item) { /* It's a field from an materialized semi-join. We can substitute it only - for a field from the same semi-join. + for a field from the same semi-join. Find the first of such items. */ - JOIN_TAB *first= field_tab; - JOIN *join= field_tab->join; - int tab_idx= field_tab - field_tab->join->join_tab; - DBUG_ASSERT(join->join_tab[tab_idx].table->map & - emb_nest->sj_inner_tables); - - /* Find the first table of this semi-join nest */ - for (int i= tab_idx-1; i >= (int)join->const_tables; i--) - { - if (join->join_tab[i].table->map & emb_nest->sj_inner_tables) - first= join->join_tab + i; - else - // Found first tab that doesn't belong to current SJ. - break; - } - /* Find an item to substitute for. */ while ((item= it++)) { - if (it.get_curr_field()->table->reginfo.join_tab >= first) + if (it.get_curr_field()->table->pos_in_table_list->embedding == emb_nest) { /* If we found given field then return NULL to avoid unnecessary @@ -5846,33 +5830,28 @@ Item* Item_equal::get_first(Item *field_item) } else { -#if TO_BE_DELETED /* The field is not in SJ-Materialization nest. We must return the first - field that's not embedded in a SJ-Materialization nest. - Example: suppose we have a join order: + field in the join order. The field may be inside a semi-join nest, i.e + a join order may look like this: SJ-Mat(it1 it2) ot1 ot2 - and equality ot2.col = ot1.col = it2.col - If we're looking for best substitute for 'ot2.col', we should pick - ot1.col and not it2.col, because when we run a join between ot1 and ot2 - execution of SJ-Mat(...) has already finished and we can't rely on the - value of it*.*. - psergey-fix-fix: ^^ THAT IS INCORRECT ^^. Pick the first, whatever that - is. + where we're looking what to substitute ot2.col for. In this case we must + still return it1.col, here's a proof why: + + First let's note that either it1.col or it2.col participates in + subquery's IN-equality. It can't be otherwise, because materialization is + only applicable to uncorrelated subqueries, so the only way we could + infer "it1.col=ot1.col" is from the IN-equality. Ok, so IN-eqality has + it1.col or it2.col on its inner side. it1.col is first such item in the + join order, so it's not possible for SJ-Mat to be + SJ-Materialization-lookup, it is SJ-Materialization-Scan. The scan part + of this strategy will unpack value of it1.col=it2.col into it1.col + (that's the first equal item inside the subquery), and we'll be able to + get it from there. qed. */ - while ((item= it++)) - { - Item_field *fld_item= (Item_field *) (item->real_item()); - TABLE_LIST *emb_nest= fld_item->field->table->pos_in_table_list->embedding; - if (!emb_nest || !emb_nest->sj_mat_info || - !emb_nest->sj_mat_info->is_used) - { - return item; - } - } -#endif + return equal_items.head(); } // Shouldn't get here. |