1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge branch '10.6' into 10.7

This commit is contained in:
Oleksandr Byelkin
2023-01-31 09:33:58 +01:00
140 changed files with 4096 additions and 705 deletions

View File

@@ -4914,38 +4914,18 @@ Item_cond::fix_fields(THD *thd, Item **ref)
if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
return TRUE; // Fatal error flag is set!
/*
The following optimization reduces the depth of an AND-OR tree.
E.g. a WHERE clause like
F1 AND (F2 AND (F2 AND F4))
is parsed into a tree with the same nested structure as defined
by braces. This optimization will transform such tree into
AND (F1, F2, F3, F4).
Trees of OR items are flattened as well:
((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4)
Items for removed AND/OR levels will dangle until the death of the
entire statement.
The optimization is currently prepared statements and stored procedures
friendly as it doesn't allocate any memory and its effects are durable
(i.e. do not depend on PS/SP arguments).
*/
while ((item=li++))
while (li++)
{
while (item->type() == Item::COND_ITEM &&
((Item_cond*) item)->functype() == functype() &&
!((Item_cond*) item)->list.is_empty())
{ // Identical function
li.replace(((Item_cond*) item)->list);
((Item_cond*) item)->list.empty();
item= *li.ref(); // new current item
}
merge_sub_condition(li);
item= *li.ref();
if (is_top_level_item())
item->top_level_item();
/*
replace degraded condition:
was: <field>
become: <field> = 1
become: <field> != 0
*/
Item::Type type= item->type();
if (type == Item::FIELD_ITEM || type == Item::REF_ITEM)
@@ -4961,7 +4941,9 @@ Item_cond::fix_fields(THD *thd, Item **ref)
if (item->fix_fields_if_needed_for_bool(thd, li.ref()))
return TRUE; /* purecov: inspected */
item= *li.ref(); // item can be substituted in fix_fields
merge_sub_condition(li);
item= *li.ref(); // may be substituted in fix_fields/merge_item_if_possible
used_tables_cache|= item->used_tables();
if (item->can_eval_in_optimize() && !item->with_sp_var() &&
!cond_has_datetime_is_null(item))
@@ -5008,6 +4990,55 @@ Item_cond::fix_fields(THD *thd, Item **ref)
return FALSE;
}
/**
@brief
Merge a lower-level condition pointed by the iterator into this Item_cond
if possible
@param li list iterator pointing to condition that must be
examined and merged if possible.
@details
If an item pointed by the iterator is an instance of Item_cond with the
same functype() as this Item_cond (i.e. both are Item_cond_and or both are
Item_cond_or) then the arguments of that lower-level item can be merged
into the list of arguments of this upper-level Item_cond.
This optimization reduces the depth of an AND-OR tree.
E.g. a WHERE clause like
F1 AND (F2 AND (F2 AND F4))
is parsed into a tree with the same nested structure as defined
by braces. This optimization will transform such tree into
AND (F1, F2, F3, F4).
Trees of OR items are flattened as well:
((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4)
Items for removed AND/OR levels will dangle until the death of the
entire statement.
The optimization is currently prepared statements and stored procedures
friendly as it doesn't allocate any memory and its effects are durable
(i.e. do not depend on PS/SP arguments).
*/
void Item_cond::merge_sub_condition(List_iterator<Item>& li)
{
Item *item= *li.ref();
/*
The check for list.is_empty() is to catch empty Item_cond_and() items.
We may encounter Item_cond_and with an empty list, because optimizer code
strips multiple equalities, combines items, then adds multiple equalities
back
*/
while (item->type() == Item::COND_ITEM &&
((Item_cond*) item)->functype() == functype() &&
!((Item_cond*) item)->list.is_empty())
{
li.replace(((Item_cond*) item)->list);
((Item_cond*) item)->list.empty();
item= *li.ref();
}
}
bool
Item_cond::eval_not_null_tables(void *opt_arg)