diff options
Diffstat (limited to 'sql/opt_sum.cc')
-rw-r--r-- | sql/opt_sum.cc | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 92a286a3b1c..9e097af1e6e 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -76,10 +76,12 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond); # Multiplication of number of rows in all tables */ -static ulonglong get_exact_record_count(TABLE_LIST *tables) +static ulonglong get_exact_record_count(List<TABLE_LIST> &tables) { ulonglong count= 1; - for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf) + TABLE_LIST *tl; + List_iterator<TABLE_LIST> ti(tables); + while ((tl= ti++)) { ha_rows tmp= tl->table->file->records(); if ((tmp == HA_POS_ERROR)) @@ -236,9 +238,11 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl) */ int opt_sum_query(THD *thd, - TABLE_LIST *tables, List<Item> &all_fields, COND *conds) + List<TABLE_LIST> &tables, List<Item> &all_fields, COND *conds) { List_iterator_fast<Item> it(all_fields); + List_iterator<TABLE_LIST> ti(tables); + TABLE_LIST *tl; int const_result= 1; bool recalc_const_item= 0; ulonglong count= 1; @@ -246,7 +250,7 @@ int opt_sum_query(THD *thd, table_map removed_tables= 0, outer_tables= 0, used_tables= 0; table_map where_tables= 0; Item *item; - int error; + int error= 0; DBUG_ENTER("opt_sum_query"); if (conds) @@ -256,7 +260,7 @@ int opt_sum_query(THD *thd, Analyze outer join dependencies, and, if possible, compute the number of returned rows. */ - for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf) + while ((tl= ti++)) { TABLE_LIST *embedded; for (embedded= tl ; embedded; embedded= embedded->embedding) @@ -297,6 +301,15 @@ int opt_sum_query(THD *thd, is_exact_count= FALSE; count= 1; // ensure count != 0 } + else if (tl->is_materialized_derived() || + tl->jtbm_subselect) + { + /* + Can't remove a derived table as it's number of rows is just an + estimate. + */ + DBUG_RETURN(0); + } else { error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); @@ -484,30 +497,32 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) /* MULT_EQUAL_FUNC */ { Item_equal *item_equal= (Item_equal *) func_item; - Item_equal_iterator it(*item_equal); - args[0]= it++; - if (it++) - return 0; if (!(args[1]= item_equal->get_const())) return 0; + Item_equal_fields_iterator it(*item_equal); + if (!(item= it++)) + return 0; + args[0]= item->real_item(); if (args[0]->max_length < args[1]->max_length) return 0; + if (it++) + return 0; } break; case 1: /* field IS NULL */ - item= func_item->arguments()[0]; + item= func_item->arguments()[0]->real_item(); if (item->type() != Item::FIELD_ITEM) return 0; args[0]= item; break; case 2: /* 'field op const' or 'const op field' */ - item= func_item->arguments()[0]; + item= func_item->arguments()[0]->real_item(); if (item->type() == Item::FIELD_ITEM) { args[0]= item; - item= func_item->arguments()[1]; + item= func_item->arguments()[1]->real_item(); if (!item->const_item()) return 0; args[1]= item; @@ -515,7 +530,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) else if (item->const_item()) { args[1]= item; - item= func_item->arguments()[1]; + item= func_item->arguments()[1]->real_item(); if (item->type() != Item::FIELD_ITEM) return 0; args[0]= item; @@ -528,13 +543,13 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) break; case 3: /* field BETWEEN const AND const */ - item= func_item->arguments()[0]; + item= func_item->arguments()[0]->real_item(); if (item->type() == Item::FIELD_ITEM) { args[0]= item; for (int i= 1 ; i <= 2; i++) { - item= func_item->arguments()[i]; + item= func_item->arguments()[i]->real_item(); if (!item->const_item()) return 0; args[i]= item; @@ -622,8 +637,10 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, test(cond->used_tables() & ~PSEUDO_TABLE_BITS)) { /* Condition doesn't restrict the used table */ - DBUG_RETURN(TRUE); + DBUG_RETURN(!cond->const_item()); } + else if (cond->is_expensive()) + DBUG_RETURN(FALSE); if (cond->type() == Item::COND_ITEM) { if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC) |