mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge branch '10.2-mdev9197-cons' of github.com:shagalla/server
into branch 10.2-mdev9197.
This commit is contained in:
@ -1100,3 +1100,137 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
|
||||
unit->set_thd(thd);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Extract the condition depended on derived table/view and pushed it there
|
||||
|
||||
@param thd The thread handle
|
||||
@param cond The condition from which to extract the pushed condition
|
||||
@param derived The reference to the derived table/view
|
||||
|
||||
@details
|
||||
This functiom builds the most restrictive condition depending only on
|
||||
the derived table/view that can be extracted from the condition cond.
|
||||
The built condition is pushed into the having clauses of the
|
||||
selects contained in the query specifying the derived table/view.
|
||||
The function also checks for each select whether any condition depending
|
||||
only on grouping fields can be extracted from the pushed condition.
|
||||
If so, it pushes the condition over grouping fields into the where
|
||||
clause of the select.
|
||||
|
||||
@retval
|
||||
true if an error is reported
|
||||
false otherwise
|
||||
*/
|
||||
|
||||
bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
||||
{
|
||||
if (!cond)
|
||||
return false;
|
||||
/*
|
||||
Build the most restrictive condition extractable from 'cond'
|
||||
that can be pushed into the derived table 'derived'.
|
||||
All subexpressions of this condition are cloned from the
|
||||
subexpressions of 'cond'.
|
||||
This condition has to be fixed yet.
|
||||
*/
|
||||
Item *extracted_cond;
|
||||
derived->check_pushable_cond_for_table(cond);
|
||||
extracted_cond= derived->build_pushable_cond_for_table(thd, cond);
|
||||
if (!extracted_cond)
|
||||
{
|
||||
/* Nothing can be pushed into the derived table */
|
||||
return false;
|
||||
}
|
||||
/* Push extracted_cond into every select of the unit specifying 'derived' */
|
||||
st_select_lex_unit *unit= derived->get_unit();
|
||||
st_select_lex *save_curr_select= thd->lex->current_select;
|
||||
st_select_lex *sl= unit->first_select();
|
||||
for (; sl; sl= sl->next_select())
|
||||
{
|
||||
thd->lex->current_select= sl;
|
||||
/*
|
||||
For each select of the unit except the last one
|
||||
create a clone of extracted_cond
|
||||
*/
|
||||
Item *extracted_cond_copy= !sl->next_select() ? extracted_cond :
|
||||
extracted_cond->build_clone(thd, thd->mem_root);
|
||||
if (!extracted_cond_copy)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Figure out what can be extracted from the pushed condition
|
||||
that could be pushed into the where clause of sl
|
||||
*/
|
||||
Item *cond_over_grouping_fields;
|
||||
sl->collect_grouping_fields(thd);
|
||||
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
|
||||
&Item::exclusive_dependence_on_grouping_fields_processor);
|
||||
cond_over_grouping_fields=
|
||||
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
|
||||
|
||||
/*
|
||||
Transform the references to the 'derived' columns from the condition
|
||||
pushed into the where clause of sl to make them usable in the new context
|
||||
*/
|
||||
if (cond_over_grouping_fields)
|
||||
cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
|
||||
&Item::derived_field_transformer_for_where,
|
||||
(uchar*) sl);
|
||||
|
||||
if (cond_over_grouping_fields)
|
||||
{
|
||||
/*
|
||||
In extracted_cond_copy remove top conjuncts that
|
||||
has been pushed into the where clause of sl
|
||||
*/
|
||||
extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
|
||||
|
||||
/*
|
||||
Create the conjunction of the existing where condition of sl
|
||||
and the pushed condition, take it as the new where condition of sl
|
||||
and fix this new condition
|
||||
*/
|
||||
cond_over_grouping_fields->walk(&Item::cleanup_processor, 0, 0);
|
||||
thd->change_item_tree(&sl->join->conds,
|
||||
and_conds(thd, sl->join->conds,
|
||||
cond_over_grouping_fields));
|
||||
|
||||
if (sl->join->conds->fix_fields(thd, &sl->join->conds))
|
||||
goto err;
|
||||
|
||||
if (!extracted_cond_copy)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
Transform the references to the 'derived' columns from the condition
|
||||
pushed into the having clause of sl to make them usable in the new context
|
||||
*/
|
||||
extracted_cond_copy= extracted_cond_copy->transform(thd,
|
||||
&Item::derived_field_transformer_for_having,
|
||||
(uchar*) sl);
|
||||
if (!extracted_cond_copy)
|
||||
continue;
|
||||
/*
|
||||
Create the conjunction of the existing having condition of sl
|
||||
and the pushed condition, take it as the new having condition of sl
|
||||
and fix this new condition
|
||||
*/
|
||||
extracted_cond_copy->walk(&Item::cleanup_processor, 0, 0);
|
||||
thd->change_item_tree(&sl->join->having,
|
||||
and_conds(thd, sl->join->having,
|
||||
extracted_cond_copy));
|
||||
sl->having_fix_field= 1;
|
||||
if (sl->join->having->fix_fields(thd, &sl->join->having))
|
||||
return true;
|
||||
sl->having_fix_field= 0;
|
||||
}
|
||||
thd->lex->current_select= save_curr_select;
|
||||
return false;
|
||||
err:
|
||||
thd->lex->current_select= save_curr_select;
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user