summaryrefslogtreecommitdiff
path: root/sql/opt_sum.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/opt_sum.cc')
-rw-r--r--sql/opt_sum.cc60
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++)
{