diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_cmpfunc.cc | 39 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/opt_sum.cc | 13 |
3 files changed, 54 insertions, 0 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b53d596da08..07704e3385f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1219,6 +1219,45 @@ longlong Item_cond_or::val_int() return 0; } +/* + Create an AND expression from two expressions + + SYNOPSIS + and_expressions() + a expression or NULL + b expression. + org_item Don't modify a if a == *org_item + If a == NULL, org_item is set to point at b, + to ensure that future calls will not modify b. + + NOTES + This will not modify item pointed to by org_item or b + The idea is that one can call this in a loop and create and + 'and' over all items without modifying any of the original items. + + RETURN + NULL Error + Item +*/ + +Item *and_expressions(Item *a, Item *b, Item **org_item) +{ + if (!a) + return (*org_item= (Item*) b); + if (a == *org_item) + { + Item_cond *res; + if ((res= new Item_cond_and(a, (Item*) b))) + res->used_tables_cache= a->used_tables() | b->used_tables(); + return res; + } + if (((Item_cond_and*) a)->add((Item*) b)) + return 0; + ((Item_cond_and*) a)->used_tables_cache|= b->used_tables(); + return a; +} + + longlong Item_func_isnull::val_int() { /* diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7827cf9a78b..b82f4eade73 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -576,3 +576,5 @@ inline Item *and_conds(Item *a,Item *b) cond->update_used_tables(); return cond; } + +Item *and_expressions(Item *a, Item *b, Item **org_item); diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index df49d52d54a..b88cfb4e073 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) bool recalc_const_item=0; table_map removed_tables=0; Item *item; + COND *org_conds= conds; + + /* Add all ON conditions to WHERE condition */ + for (TABLE_LIST *tl=tables; tl ; tl= tl->next) + { + if (tl->on_expr) + conds= and_expressions(conds, tl->on_expr, &org_conds); + } + + /* + Iterate through item is select part and replace COUNT(), MIN() and MAX() + with constants (if possible) + */ while ((item= it++)) { |