Skip to content

Commit 8acdfc3

Browse files
committed
MDEV-37713/MDEV-37714 Fold boolean literals in SELECT-list
The order of evaluation of the expressions that appear in a SELECT-list is undefined. This change exploits this fact by recursively folding TRUE/FALSE literals in OR/AND expressions which may allow for skipping evaluation of some parts of the expression or even the whole expression.
1 parent ef4be39 commit 8acdfc3

3 files changed

Lines changed: 58 additions & 0 deletions

File tree

sql/item_cmpfunc.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5736,6 +5736,45 @@ bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel)
57365736
return true;
57375737
}
57385738

5739+
Item *Item_cond::simplify_cond(THD *thd)
5740+
{
5741+
List_iterator<Item> li(list);
5742+
Item *child;
5743+
while ((child= li++))
5744+
{
5745+
if (child->type() == Item::COND_ITEM)
5746+
{
5747+
Item *new_child= static_cast<Item_cond *>(child)->simplify_cond(thd);
5748+
if (new_child != child)
5749+
li.replace(new_child);
5750+
}
5751+
}
5752+
bool is_and= functype() == Item_func::COND_AND_FUNC;
5753+
bool is_or= functype() == Item_func::COND_OR_FUNC;
5754+
if (is_and || is_or)
5755+
{
5756+
List_iterator<Item> li2(list);
5757+
while ((child= li2++))
5758+
{
5759+
Item *real= child->real_item();
5760+
if (real->is_bool_literal())
5761+
{
5762+
bool v= real->val_bool();
5763+
if (is_and && v)
5764+
li2.remove();
5765+
if (is_and && !v)
5766+
return new (thd->mem_root) Item_bool(thd, false);
5767+
if (is_or && v)
5768+
return new (thd->mem_root) Item_bool(thd, true);
5769+
if (is_or && !v)
5770+
li2.remove();
5771+
}
5772+
}
5773+
if (list.is_empty())
5774+
return new (thd->mem_root) Item_bool(thd, false);
5775+
}
5776+
return this;
5777+
}
57395778

57405779
void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
57415780
{

sql/item_cmpfunc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3450,6 +3450,7 @@ class Item_cond :public Item_bool_func
34503450
Item *deep_copy(THD *thd) const override;
34513451
bool excl_dep_on_table(table_map tab_map) override;
34523452
bool excl_dep_on_grouping_fields(st_select_lex *sel) override;
3453+
Item *simplify_cond(THD *thd);
34533454

34543455
private:
34553456
void merge_sub_condition(List_iterator<Item>& li);

sql/sql_base.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8223,6 +8223,24 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
82238223
DBUG_RETURN(TRUE); /* purecov: inspected */
82248224
}
82258225
item= *(it.ref()); // Item might have changed in fix_fields()
8226+
8227+
/*
8228+
If item is a SELECT-list COND_ITEM, rewrite it on the first time this
8229+
query is optimized to fold boolean expressions
8230+
*/
8231+
if (thd->lex->current_select->context_analysis_place == SELECT_LIST &&
8232+
item->type() == Item::COND_ITEM &&
8233+
thd->lex->current_select->first_cond_optimization)
8234+
{
8235+
Query_arena_stmt on_stmt_arena(thd);
8236+
Item *new_item= static_cast<Item_cond *>(item)->simplify_cond(thd);
8237+
if (new_item != item)
8238+
{
8239+
new_item->share_name_with(item);
8240+
it.replace(new_item);
8241+
item= new_item;
8242+
}
8243+
}
82268244
if (!ref.is_null())
82278245
{
82288246
ref[0]= item;

0 commit comments

Comments
 (0)