diff options
author | Alexander Barkov <bar@mariadb.org> | 2017-05-05 16:12:54 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2017-05-05 16:12:54 +0400 |
commit | ac53b49b1be807f588aebd83883ec93b764f5d54 (patch) | |
tree | c86cbdb535eefb15e2077a7ac2ffaeff9d76955e /sql/sql_cte.cc | |
parent | 583b68e89961c35fa95a06c38988f82e33c73f4a (diff) | |
parent | db0917f68f2681882974afd53935aa8cba29c6b8 (diff) | |
download | mariadb-git-ac53b49b1be807f588aebd83883ec93b764f5d54.tar.gz |
Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext
Diffstat (limited to 'sql/sql_cte.cc')
-rw-r--r-- | sql/sql_cte.cc | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 7c2a8cf9e65..c163044547f 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -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 */ @@ -353,6 +355,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 @param unit The unit where to look for the dependencies @@ -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; |