diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d5a6fdd275f48..42437239f2bec 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5736,6 +5736,45 @@ bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel) return true; } +Item *Item_cond::simplify_cond(THD *thd) +{ + List_iterator li(list); + Item *child; + while ((child= li++)) + { + if (child->type() == Item::COND_ITEM) + { + Item *new_child= static_cast(child)->simplify_cond(thd); + if (new_child != child) + li.replace(new_child); + } + } + bool is_and= functype() == Item_func::COND_AND_FUNC; + bool is_or= functype() == Item_func::COND_OR_FUNC; + if (is_and || is_or) + { + List_iterator li2(list); + while ((child= li2++)) + { + Item *real= child->real_item(); + if (real->is_bool_literal()) + { + bool v= real->val_bool(); + if (is_and && v) + li2.remove(); + if (is_and && !v) + return new (thd->mem_root) Item_bool(thd, false); + if (is_or && v) + return new (thd->mem_root) Item_bool(thd, true); + if (is_or && !v) + li2.remove(); + } + } + if (list.is_empty()) + return new (thd->mem_root) Item_bool(thd, false); + } + return this; +} void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 4fa07ccc8c971..1353a086db541 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -3450,6 +3450,7 @@ class Item_cond :public Item_bool_func Item *deep_copy(THD *thd) const override; bool excl_dep_on_table(table_map tab_map) override; bool excl_dep_on_grouping_fields(st_select_lex *sel) override; + Item *simplify_cond(THD *thd); private: void merge_sub_condition(List_iterator& li); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 059cf17e75bf6..badf9a823818e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8223,6 +8223,23 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, DBUG_RETURN(TRUE); /* purecov: inspected */ } item= *(it.ref()); // Item might have changed in fix_fields() + /* + If item is a SELECT-list COND_ITEM, rewrite it on the first time this + query is optimized to fold boolean expressions + */ + if (thd->lex->current_select->context_analysis_place == SELECT_LIST && + item->type() == Item::COND_ITEM && + thd->lex->current_select->first_cond_optimization) + { + Query_arena_stmt on_stmt_arena(thd); + Item *new_item= static_cast(item)->simplify_cond(thd); + if (new_item != item) + { + new_item->share_name_with(item); + it.replace(new_item); + item= new_item; + } + } if (!ref.is_null()) { ref[0]= item;