diff options
Diffstat (limited to 'sql/opt_sum.cc')
-rw-r--r-- | sql/opt_sum.cc | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index cfb5b3695a3..37acce2934b 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -59,9 +59,9 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond); SYNOPSIS opt_sum_query() - tables Tables in query - all_fields All fields to be returned - conds WHERE clause + tables list of leaves of join table tree + all_fields All fields to be returned + conds WHERE clause NOTE: This function is only called for queries with sum functions and no @@ -94,7 +94,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) Analyze outer join dependencies, and, if possible, compute the number of returned rows. */ - for (TABLE_LIST *tl=tables; tl ; tl= tl->next) + for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf) { /* Don't replace expression on a table that is part of an outer join */ if (tl->on_expr) @@ -150,8 +150,24 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null && !outer_tables && is_exact_count) { - ((Item_sum_count*) item)->make_const(count); - recalc_const_item= 1; + longlong count= 1; + TABLE_LIST *table; + for (table= tables; table; table= table->next_leaf) + { + if (outer_tables || (table->table->file->table_flags() & + HA_NOT_EXACT_COUNT) || table->schema_table) + { + const_result= 0; // Can't optimize left join + break; + } + tables->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + count*= table->table->file->records; + } + if (!table) + { + ((Item_sum_count*) item)->make_const(count); + recalc_const_item= 1; + } } else const_result= 0; @@ -351,7 +367,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) removed_tables is != 0 if we have used MIN() or MAX(). */ if (removed_tables && used_tables != removed_tables) - const_result= 0; // We didn't remove all tables + const_result= 0; // We didn't remove all tables return const_result; } @@ -361,20 +377,34 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) SYNOPSIS simple_pred() - func_item in: Predicate item + func_item Predicate item args out: Here we store the field followed by constants - inv_order out: Is set to 1 if the predicate is of the form 'const op field' + inv_order out: Is set to 1 if the predicate is of the form + 'const op field' RETURN - 0 func_item is a simple predicate: a field is compared with constants + 0 func_item is a simple predicate: a field is compared with + constants 1 Otherwise */ -static bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) +bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) { Item *item; *inv_order= 0; switch (func_item->argument_count()) { + case 0: + /* 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; + } + break; case 1: /* field IS NULL */ item= func_item->arguments()[0]; @@ -515,6 +545,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, case Item_func::BETWEEN: between= 1; break; + case Item_func::MULT_EQUAL_FUNC: + eq_type= 1; + break; default: return 0; // Can't optimize function } @@ -585,8 +618,7 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, store_val_in_field(part->field, args[between && max_fl ? 2 : 1]); if (part->null_bit) *key_ptr++= (byte) test(part->field->is_null()); - part->field->get_key_image((char*) key_ptr, part->length, - part->field->charset(), Field::itRAW); + part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW); } if (is_field_part) { @@ -667,7 +699,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, uint idx= 0; KEY *keyinfo,*keyinfo_end; - for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->keys ; + for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->s->keys ; keyinfo != keyinfo_end; keyinfo++,idx++) { |