diff --git a/sql/item.h b/sql/item.h index 043605a6c7c..017d3489de9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1128,9 +1128,11 @@ public: void print_value(String *); virtual void update_used_tables() {} virtual COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { update_used_tables(); + DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); return this; } /* @@ -2335,7 +2337,8 @@ public: update_table_bitmaps(); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { /* normilize_cond() replaced all conditions of type @@ -2351,7 +2354,8 @@ public: SELECT * FROM t1 WHERE DEFAULT(a); */ DBUG_ASSERT(type() != FIELD_ITEM); - return Item_ident::build_equal_items(thd, inherited, link_item_fields); + return Item_ident::build_equal_items(thd, inherited, link_item_fields, + cond_equal_ref); } bool is_result_field() { return false; } void set_result_field(Field *field) {} @@ -3593,7 +3597,8 @@ public: table_map used_tables() const; void update_used_tables(); COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { /* normilize_cond() replaced all conditions of type @@ -3604,7 +3609,8 @@ public: already be replaced. No Item_ref referencing to Item_field are possible. */ DBUG_ASSERT(real_type() != FIELD_ITEM); - return Item_ident::build_equal_items(thd, inherited, link_item_fields); + return Item_ident::build_equal_items(thd, inherited, link_item_fields, + cond_equal_ref); } bool const_item() const { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 694b5c180de..5064521c1a1 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -563,7 +563,8 @@ public: const char *func_name() const { return "="; } Item *negated_item(); COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields); + bool link_item_fields, + COND_EQUAL **cond_equal_ref); bool check_equality(THD *thd, COND_EQUAL *cond, List *eq_list); /* - If this equality is created from the subquery's IN-equality: @@ -1772,7 +1773,8 @@ public: used_tables_and_const_cache_update_and_join(list); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields); + bool link_item_fields, + COND_EQUAL **cond_equal_ref); virtual void print(String *str, enum_query_type query_type); void split_sum_func(THD *thd, Item **ref_pointer_array, List &fields); friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, @@ -1960,6 +1962,9 @@ public: void fix_length_and_dec(); bool fix_fields(THD *thd, Item **ref); void update_used_tables(); + COND *build_equal_items(THD *thd, COND_EQUAL *inherited, + bool link_item_fields, + COND_EQUAL **cond_equal_ref); bool walk(Item_processor processor, bool walk_subquery, uchar *arg); Item *transform(Item_transformer transformer, uchar *arg); virtual void print(String *str, enum_query_type query_type); @@ -1989,6 +1994,11 @@ public: { upper_levels= 0; } + COND_EQUAL(Item_equal *item, MEM_ROOT *mem_root) + :upper_levels(0) + { + current_level.push_back(item, mem_root); + } void copy(COND_EQUAL &cond_equal) { max_members= cond_equal.max_members; @@ -2107,7 +2117,8 @@ public: virtual uint exists2in_reserved_items() { return list.elements; }; bool walk_top_and(Item_processor processor, uchar *arg); COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields); + bool link_item_fields, + COND_EQUAL **cond_equal_ref); }; inline bool is_cond_and(Item *item) diff --git a/sql/item_func.h b/sql/item_func.h index 0d57c2b779b..a5ddb248e8f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -132,7 +132,8 @@ public: used_tables_and_const_cache_update_and_join(arg_count, args); } COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields); + bool link_item_fields, + COND_EQUAL **cond_equal_ref); bool eq(const Item *item, bool binary_cmp) const; virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; } virtual bool have_rev_func() const { return 0; } diff --git a/sql/item_sum.h b/sql/item_sum.h index b540b44a31e..056c62355fb 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -445,7 +445,8 @@ public: table_map used_tables() const { return used_tables_cache; } void update_used_tables (); COND *build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { /* Item_sum (and derivants) of the original WHERE/HAVING clauses @@ -453,7 +454,8 @@ public: build_equal_items() is called. See Item::split_sum_func2(). */ DBUG_ASSERT(0); - return Item::build_equal_items(thd, inherited, link_item_fields); + return Item::build_equal_items(thd, inherited, link_item_fields, + cond_equal_ref); } bool is_null() { return null_value; } void make_const () diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4f2b8ebb824..d26e5026c85 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12776,7 +12776,8 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal, COND *Item_cond_and::build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { Item_equal *item_equal; COND_EQUAL cond_equal; @@ -12788,6 +12789,7 @@ COND *Item_cond_and::build_equal_items(THD *thd, List_iterator li(*args); Item *item; + DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); /* Retrieve all conjuncts of this level detecting the equality that are subject to substitution by multiple equality items and @@ -12812,7 +12814,7 @@ COND *Item_cond_and::build_equal_items(THD *thd, if (!args->elements && !cond_equal.current_level.elements && !eq_list.elements) - return new Item_int((longlong) 1, 1); + return new (thd->mem_root) Item_int((longlong) 1, 1); List_iterator_fast it(cond_equal.current_level); while ((item_equal= it++)) @@ -12836,7 +12838,7 @@ COND *Item_cond_and::build_equal_items(THD *thd, while ((item= li++)) { Item *new_item; - if ((new_item= item->build_equal_items(thd, inherited, FALSE)) + if ((new_item= item->build_equal_items(thd, inherited, false, NULL)) != item) { /* This replacement happens only for standalone equalities */ @@ -12851,19 +12853,23 @@ COND *Item_cond_and::build_equal_items(THD *thd, args->append(&eq_list); args->append((List *)&cond_equal.current_level); update_used_tables(); + if (cond_equal_ref) + *cond_equal_ref= &m_cond_equal; return this; } COND *Item_cond::build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { List *args= argument_list(); List_iterator li(*args); Item *item; + DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); /* Make replacement of equality predicates for lower levels of the condition expression. @@ -12873,7 +12879,7 @@ COND *Item_cond::build_equal_items(THD *thd, while ((item= li++)) { Item *new_item; - if ((new_item= item->build_equal_items(thd, inherited, FALSE)) + if ((new_item= item->build_equal_items(thd, inherited, false, NULL)) != item) { /* This replacement happens only for standalone equalities */ @@ -12892,11 +12898,14 @@ COND *Item_cond::build_equal_items(THD *thd, COND *Item_func_eq::build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { COND_EQUAL cond_equal; cond_equal.upper_levels= inherited; List eq_list; + + DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); /* If an equality predicate forms the whole and level, we call it standalone equality and it's processed here. @@ -12912,7 +12921,7 @@ COND *Item_func_eq::build_equal_items(THD *thd, Item_equal *item_equal; int n= cond_equal.current_level.elements + eq_list.elements; if (n == 0) - return new Item_int((longlong) 1,1); + return new (thd->mem_root) Item_int((longlong) 1,1); else if (n == 1) { if ((item_equal= cond_equal.current_level.pop())) @@ -12922,10 +12931,14 @@ COND *Item_func_eq::build_equal_items(THD *thd, set_if_bigger(thd->lex->current_select->max_equal_elems, item_equal->n_field_items()); item_equal->upper_levels= inherited; + if (cond_equal_ref) + *cond_equal_ref= new (thd->mem_root) COND_EQUAL(item_equal, + thd->mem_root); return item_equal; } Item *res= eq_list.pop(); res->update_used_tables(); + DBUG_ASSERT(res->type() == FUNC_ITEM); return res; } else @@ -12949,15 +12962,19 @@ COND *Item_func_eq::build_equal_items(THD *thd, cond_equal.current_level= and_cond->m_cond_equal.current_level; args->append((List *)&cond_equal.current_level); and_cond->update_used_tables(); + if (cond_equal_ref) + *cond_equal_ref= &and_cond->m_cond_equal; return and_cond; } } - return Item_func::build_equal_items(thd, inherited, link_item_fields); + return Item_func::build_equal_items(thd, inherited, link_item_fields, + cond_equal_ref); } COND *Item_func::build_equal_items(THD *thd, COND_EQUAL *inherited, - bool link_item_fields) + bool link_item_fields, + COND_EQUAL **cond_equal_ref) { /* For each field reference in cond, not from equal item predicates, @@ -12971,6 +12988,20 @@ COND *Item_func::build_equal_items(THD *thd, COND_EQUAL *inherited, &Item::equal_fields_propagator, (uchar *) inherited); cond->update_used_tables(); + DBUG_ASSERT(cond == this); + DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); + return cond; +} + + +COND *Item_equal::build_equal_items(THD *thd, COND_EQUAL *inherited, + bool link_item_fields, + COND_EQUAL **cond_equal_ref) +{ + COND *cond= Item_func::build_equal_items(thd, inherited, link_item_fields, + cond_equal_ref); + if (cond_equal_ref) + *cond_equal_ref= new (thd->mem_root) COND_EQUAL(this, thd->mem_root); return cond; } @@ -13052,28 +13083,19 @@ static COND *build_equal_items(JOIN *join, COND *cond, bool link_equal_fields) { THD *thd= join->thd; - COND_EQUAL *cond_equal= 0; + + *cond_equal_ref= NULL; if (cond) { - cond= cond->build_equal_items(thd, inherited, link_equal_fields); - if (cond->type() == Item::COND_ITEM && - ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) - cond_equal= &((Item_cond_and*) cond)->m_cond_equal; - - else if (cond->type() == Item::FUNC_ITEM && - ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC) + cond= cond->build_equal_items(thd, inherited, link_equal_fields, + cond_equal_ref); + if (*cond_equal_ref) { - cond_equal= new (thd->mem_root) COND_EQUAL; - cond_equal->current_level.push_back((Item_equal *) cond, thd->mem_root); + (*cond_equal_ref)->upper_levels= inherited; + inherited= *cond_equal_ref; } } - if (cond_equal) - { - cond_equal->upper_levels= inherited; - inherited= cond_equal; - } - *cond_equal_ref= cond_equal; if (join_list && !ignore_on_conds) {