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

Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext

This commit is contained in:
Alexander Barkov
2017-05-05 16:12:54 +04:00
398 changed files with 15220 additions and 4380 deletions

View File

@ -141,7 +141,7 @@ bool With_clause::check_dependencies()
/*
Mark those elements where tables are defined with direct or indirect
make recursion.
recursion.
*/
for (With_element *with_elem= with_list.first;
with_elem;
@ -342,6 +342,8 @@ void With_element::check_dependencies_in_select(st_select_lex *sl,
tbl->with_internal_reference_map= get_elem_map();
if (in_subq)
sq_dep_map|= tbl->with->get_elem_map();
else
top_level_dep_map|= tbl->with->get_elem_map();
}
}
/* Now look for the dependencies in the subqueries of sl */
@ -351,6 +353,53 @@ void With_element::check_dependencies_in_select(st_select_lex *sl,
}
/**
@brief
Find a recursive reference to this with element in subqueries of a select
@param sel The select in whose subqueries the reference
to be looked for
@details
The function looks for a recursive reference to this with element in
subqueries of select sl. When the first such reference is found
it is returned as the result.
The function assumes that the identification of all CTE references
has been performed earlier.
@retval
Pointer to the found recursive reference if the search succeeded
NULL - otherwise
*/
TABLE_LIST *With_element::find_first_sq_rec_ref_in_select(st_select_lex *sel)
{
TABLE_LIST *rec_ref= NULL;
st_select_lex_unit *inner_unit= sel->first_inner_unit();
for (; inner_unit; inner_unit= inner_unit->next_unit())
{
st_select_lex *sl= inner_unit->first_select();
for (; sl; sl= sl->next_select())
{
for (TABLE_LIST *tbl= sl->table_list.first; tbl; tbl= tbl->next_local)
{
if (tbl->derived || tbl->nested_join)
continue;
if (tbl->with && tbl->with->owner== this->owner &&
(tbl->with_internal_reference_map & mutually_recursive))
{
rec_ref= tbl;
return rec_ref;
}
}
if ((rec_ref= find_first_sq_rec_ref_in_select(sl)))
return rec_ref;
}
}
return 0;
}
/**
@brief
Find the dependencies of this element on its siblings in a unit
@ -602,6 +651,10 @@ void With_clause::move_anchors_ahead()
@details
If the specification of this with element contains anchors the method
moves them at the very beginning of the specification.
Additionally for the other selects of the specification if none of them
contains a recursive reference to this with element or a mutually recursive
one the method looks for the first such reference in the first recursive
select and set a pointer to it in this->sq_rec_ref.
*/
void With_element::move_anchors_ahead()
@ -618,6 +671,11 @@ void With_element::move_anchors_ahead()
sl->move_node(new_pos);
new_pos= sl->next_select();
}
else if (!sq_rec_ref && no_rec_ref_on_top_level())
{
sq_rec_ref= find_first_sq_rec_ref_in_select(sl);
DBUG_ASSERT(sq_rec_ref != NULL);
}
last_sl= sl;
}
if (spec->union_distinct)
@ -967,6 +1025,17 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
{
if (table)
{
/*
This table was prematurely identified as a temporary table.
We correct it here, but it's not a nice solution in the case
when the temporary table with this name is not used anywhere
else in the query.
*/
thd->mark_tmp_table_as_free_for_reuse(table);
table= 0;
}
with= with_elem;
if (!with_elem->is_referenced() || with_elem->is_recursive)
derived= with_elem->spec;
@ -1228,6 +1297,7 @@ bool st_select_lex::check_subqueries_with_recursive_references()
continue;
Item_subselect *subq= (Item_subselect *) sl_master->item;
subq->with_recursive_reference= true;
subq->register_as_with_rec_ref(tbl->with);
}
}
return false;