1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-29662 Replace same values in 'IN' list with an equality

If all elements in the list of 'IN' or 'NOT IN' clause are equal
and there are no NULLs then clause
-  "a IN (e1,..,en)" can be converted to "a = e1"
-  "a NOT IN (e1,..,en)" can be converted to "a <> e1".
This means an object of Item_func_in can be replaced with an object
of Item_func_eq for IN (e1,..,en) clause and Item_func_ne for
NOT IN (e1,...,en). Such a replacement allows the optimizer to choose
a better execution plan
This commit is contained in:
Oleg Smirnov
2022-10-04 16:45:51 +07:00
parent b7fe6179e8
commit 5027cb2b74
8 changed files with 484 additions and 4 deletions

View File

@ -2218,6 +2218,9 @@ JOIN::optimize_inner()
ignore_on_expr= true;
break;
}
transform_in_predicates_into_equalities(thd);
conds= optimize_cond(this, conds, join_list, ignore_on_expr,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
@ -30468,6 +30471,95 @@ static bool process_direct_rownum_comparison(THD *thd, SELECT_LEX_UNIT *unit,
DBUG_RETURN(false);
}
/**
@brief
Transform IN predicates having equal constant elements to equalities
@param thd The context of the statement
@details
If all elements in an IN predicate are constant and equal to each other
then clause
- "a IN (e1,..,en)" can be transformed to "a = e1"
- "a NOT IN (e1,..,en)" can be transformed to "a != e1".
This means an object of Item_func_in can be replaced with an object of
Item_func_eq for IN (e1,..,en) clause or Item_func_ne for
NOT IN (e1,...,en).
Such a replacement allows the optimizer to choose a better execution plan.
This methods applies such transformation for each IN predicate of the WHERE
condition and ON expressions of this join where possible
@retval
false success
true failure
*/
bool JOIN::transform_in_predicates_into_equalities(THD *thd)
{
DBUG_ENTER("JOIN::transform_in_predicates_into_equalities");
DBUG_RETURN(transform_all_conds_and_on_exprs(
thd, &Item::in_predicate_to_equality_transformer));
}
/**
@brief
Transform all items in WHERE and ON expressions using a given transformer
@param thd The context of the statement
transformer Pointer to the transformation function
@details
For each item of the WHERE condition and ON expressions of the SELECT
for this join the method performs the intransformation using the given
transformation function
@retval
false success
true failure
*/
bool JOIN::transform_all_conds_and_on_exprs(THD *thd,
Item_transformer transformer)
{
if (conds)
{
conds= conds->transform(thd, transformer, (uchar *) 0);
if (!conds)
return true;
}
if (join_list)
{
if (transform_all_conds_and_on_exprs_in_join_list(thd, join_list,
transformer))
return true;
}
return false;
}
bool JOIN::transform_all_conds_and_on_exprs_in_join_list(
THD *thd, List<TABLE_LIST> *join_list, Item_transformer transformer)
{
TABLE_LIST *table;
List_iterator<TABLE_LIST> li(*join_list);
while ((table= li++))
{
if (table->nested_join)
{
if (transform_all_conds_and_on_exprs_in_join_list(
thd, &table->nested_join->join_list, transformer))
return true;
}
if (table->on_expr)
{
table->on_expr= table->on_expr->transform(thd, transformer, (uchar *) 0);
if (!table->on_expr)
return true;
}
}
return false;
}
/**