revision-id: 283b3275742ca22cd1f46a21b1a794f1b52039a9 (mariadb-10.3.4-59-g283b327) parent(s): 608d6773bff86b82d9fa35e77065cb0b6ed9e547 author: Galina Shalygina committer: Galina Shalygina timestamp: 2018-04-17 01:06:57 +0200 message: Changes for MDEV-12387 Procedures renamed, some missing definitions added. *Item_direct_view_ref::in_subq_field_transformer_for_having added --- sql/item.cc | 7 ++-- sql/item.h | 13 ++++--- sql/item_cmpfunc.h | 4 +- sql/opt_subselect.cc | 105 ++++++++++++++++++++++++++++++++++++--------------- sql/sql_derived.cc | 8 ++-- sql/sql_select.cc | 1 + 6 files changed, 92 insertions(+), 46 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index b1134d1..7a6879e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7904,8 +7904,7 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item, } -Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg) +Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg) { st_select_lex *sel= (st_select_lex *)arg; Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel); @@ -7916,8 +7915,8 @@ Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd, Item * -Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg) +Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd, + uchar *arg) { if (!item_equal) return this; diff --git a/sql/item.h b/sql/item.h index 2d8972f..faeb4ae 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1785,8 +1785,7 @@ class Item: public Value_source, { return this; } virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { return this; } - virtual Item *derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg) + virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) { return this; } virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { return this; } @@ -2959,7 +2958,7 @@ class Item_field :public Item_ident virtual Item *update_value_transformer(THD *thd, uchar *select_arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg); - Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg); + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg); Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg); virtual void print(String *str, enum_query_type query_type); bool excl_dep_on_table(table_map tab_map); @@ -5091,8 +5090,8 @@ class Item_direct_view_ref :public Item_direct_ref bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred); Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg); - Item *derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg); + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg); + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg); void save_val(Field *to) { @@ -5998,7 +5997,9 @@ class Item_cache: public Item_basic_constant, { return convert_to_basic_const_item(thd); } Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { return convert_to_basic_const_item(thd); } - Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) + { return convert_to_basic_const_item(thd); } + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { return convert_to_basic_const_item(thd); } }; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c2d7a4c..f565f3a 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1260,7 +1260,9 @@ class Item_func_nullif :public Item_func_case_expression { reset_first_arg_if_needed(); return this; } Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { reset_first_arg_if_needed(); return this; } - Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) + { reset_first_arg_if_needed(); return this; } + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { reset_first_arg_if_needed(); return this; } }; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 8f6483e..eac779c 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -5898,7 +5898,6 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, List_iterator<TABLE_LIST> li(*join_list); THD *thd= join->thd; DBUG_ENTER("setup_jtbm_semi_joins"); - eq_list.empty(); while ((table= li++)) { @@ -6432,14 +6431,39 @@ bool Item_equal::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) } -Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg) +/** + @brief + Transforms item so it can be pushed into the IN subquery HAVING clause + + @param thd the thread handle + @param in_item the item for which pushable item should be created + @param subq_pred the IN subquery predicate + + @details + This method traverses the fields of the select of the IN subquery predicate + subq_pred trying to find the corresponding item 'new_item' for in_item. + If in_item has equal items it traverses the fields of the select of + subq_pred for each equal item trying to find corresponding item 'new_item'. + If 'new_item' is found, a shell for this item is created. This shell can be + pushed into the HAVING part of subq_pred select. + + @retval <item*> reference to the created corresonding item shell for in_item + @retval NULL if mistake occurs +*/ + +static +Item *get_corresponding_item_for_in_subq_having(THD *thd, Item *in_item, + Item_in_subselect *subq_pred) { - Item_in_subselect *subq_pred= (Item_in_subselect *)arg; + DBUG_ASSERT(in_item->type() == Item::FIELD_ITEM || + (in_item->type() == Item::REF_ITEM && + ((Item_ref *) in_item)->ref_type() == Item_ref::VIEW_REF)); - List_iterator<In_subq_field> li(subq_pred->comparable_fields); In_subq_field *fi; - Item_field *field_item= (Item_field *) (real_item()); Item *new_item; + List_iterator<In_subq_field> li(subq_pred->comparable_fields); + Item_field *field_item= (Item_field *) (in_item->real_item()); + Item_equal *item_equal= in_item->get_item_equal(); if (item_equal) { @@ -6452,10 +6476,11 @@ Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg) while ((fi= li++)) { if (field_item->field == - ((Item_field *) (fi->left_it->real_item()))->field) - { - new_item= fi->right_it; - } + ((Item_field *) (fi->left_it->real_item()))->field) + { + new_item= fi->right_it; + break; + } } } } @@ -6465,39 +6490,56 @@ Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg) while ((fi= li++)) { if (field_item->field == - ((Item_field *) (fi->left_it->real_item()))->field) + ((Item_field *) (fi->left_it->real_item()))->field) + { new_item= fi->right_it; + break; + } } } - if (!new_item) - return this; - - Item_ref *ref= - new (thd->mem_root) Item_ref(thd, - &subq_pred->unit->first_select()->context, - NullS, NullS, - &new_item->name); + if (new_item) + { + Item_ref *ref= + new (thd->mem_root) Item_ref(thd, + &subq_pred->unit->first_select()->context, + NullS, NullS, + &new_item->name); return ref; - + } DBUG_ASSERT(0); return NULL; } +Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg) +{ + return get_corresponding_item_for_in_subq_having(thd, this, + (Item_in_subselect *)arg); +} + + +Item *Item_direct_view_ref::in_subq_field_transformer_for_having(THD *thd, + uchar *arg) +{ + return get_corresponding_item_for_in_subq_having(thd, this, + (Item_in_subselect *)arg); +} + + /** @brief Find fields that are used in the GROUP BY of the select @param thd the thread handle - @param sel select of the right part of IN subquery - @param fields fields list of the left part of IN subquery + @param sel the select of the IN subquery predicate select + @param fields fields of the left part of the IN subquery predicate @details - This method looks through the fields which are used in the GROUP BY of - sel and saves this fields with their prototypes from the fields list - of the left part of IN subquery + This method traverses fields which are used in the GROUP BY of + sel and saves them with their corresponding items from fields. */ + void grouping_fields_in_the_in_subq_left_part(THD *thd, st_select_lex *sel, List<In_subq_field> *fields, @@ -6568,6 +6610,7 @@ void grouping_fields_in_the_in_subq_left_part(THD *thd, @retval TRUE if an error occurs @retval FALSE otherwise */ + bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond) { DBUG_ENTER("Item_in_subselect::pushdown_cond_for_in_subquery"); @@ -6640,12 +6683,12 @@ bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond) if (cond_over_partition_fields) cond_over_partition_fields= cond_over_partition_fields->transform(thd, - &Item::derived_grouping_field_transformer_for_where, (uchar*) sel); + &Item::grouping_field_transformer_for_where, (uchar*) sel); if (cond_over_partition_fields) { cond_over_partition_fields->walk( - &Item::cleanup_excluding_const_fields_processor, 0, 0); + &Item::cleanup_excluding_const_fields_processor, 0, 0); sel->cond_pushed_into_where= cond_over_partition_fields; } goto exit; @@ -6667,9 +6710,10 @@ bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond) into the sel of the WHERE clause. */ if (cond_over_grouping_fields) - cond_over_grouping_fields= cond_over_grouping_fields->transform(thd, - &Item::derived_grouping_field_transformer_for_where, - (uchar*) sel); + cond_over_grouping_fields= + cond_over_grouping_fields->transform(thd, + &Item::grouping_field_transformer_for_where, + (uchar*) sel); if (cond_over_grouping_fields) { @@ -6695,8 +6739,7 @@ bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond) if (!extracted_cond) goto exit; - extracted_cond->walk(&Item::cleanup_excluding_const_fields_processor, - 0, 0); + extracted_cond->walk(&Item::cleanup_excluding_const_fields_processor, 0, 0); sel->cond_pushed_into_having= extracted_cond; exit: diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index f2179ae..1c62a38 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1310,8 +1310,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true); if (cond_over_partition_fields) cond_over_partition_fields= cond_over_partition_fields->transform(thd, - &Item::derived_grouping_field_transformer_for_where, - (uchar*) sl); + &Item::grouping_field_transformer_for_where, + (uchar*) sl); if (cond_over_partition_fields) { cond_over_partition_fields->walk( @@ -1364,8 +1364,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) */ if (cond_over_grouping_fields) cond_over_grouping_fields= cond_over_grouping_fields->transform(thd, - &Item::derived_grouping_field_transformer_for_where, - (uchar*) sl); + &Item::grouping_field_transformer_for_where, + (uchar*) sl); if (cond_over_grouping_fields) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5a342c8..e7bc68e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1750,6 +1750,7 @@ JOIN::optimize_inner() conds->fix_fields(thd, &conds))) DBUG_RETURN(TRUE); } + eq_list.empty(); if (select_lex->cond_pushed_into_where) {