diff options
author | Igor Babaev <igor@askmonty.org> | 2016-06-25 21:38:40 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2016-06-25 21:38:40 -0700 |
commit | 9606525666eeead285f211bd0e603b50b4f09189 (patch) | |
tree | dbc20fb0fc2c9fc5fad56914cd99cd5ea66dece0 /sql | |
parent | 0eec187153e8266b99f4ae66dba810a9b39e206d (diff) | |
download | mariadb-git-9606525666eeead285f211bd0e603b50b4f09189.tar.gz |
Simplified the code that fills recursive tables.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_cte.cc | 36 | ||||
-rw-r--r-- | sql/sql_cte.h | 91 | ||||
-rw-r--r-- | sql/sql_derived.cc | 47 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 14 | ||||
-rw-r--r-- | sql/sql_union.cc | 148 | ||||
-rw-r--r-- | sql/table.h | 2 |
7 files changed, 135 insertions, 205 deletions
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 04a4fcb8a2b..2b3a72c1b3a 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -248,22 +248,32 @@ bool With_clause::check_anchors() if (!with_elem->is_recursive) continue; - table_map with_elem_dep= with_elem->derived_dep_map; - table_map with_elem_map= with_elem->get_elem_map(); - for (With_element *elem= with_elem; - elem != NULL; - elem= elem->next_elem) + if (!with_elem->next_mutually_recursive) { - if (!elem->is_recursive) - continue; - - if (elem == with_elem || - ((elem->derived_dep_map & with_elem_map) && - (with_elem_dep & elem->get_elem_map()))) - { + With_element *last_mutually_recursive= with_elem; + table_map with_elem_dep= with_elem->derived_dep_map; + table_map with_elem_map= with_elem->get_elem_map(); + for (With_element *elem= with_elem; + elem != NULL; + elem= elem->next_elem) + { + if (!elem->is_recursive) + continue; + + if (elem == with_elem || + ((elem->derived_dep_map & with_elem_map) && + (with_elem_dep & elem->get_elem_map()))) + { + elem->next_mutually_recursive= with_elem; + last_mutually_recursive->next_mutually_recursive= elem; + last_mutually_recursive= elem; with_elem->mutually_recursive|= elem->get_elem_map(); - elem->mutually_recursive|= with_elem_map; } + } + for (With_element *elem= with_elem->next_mutually_recursive; + elem != with_elem; + elem= elem->next_mutually_recursive) + elem->mutually_recursive= with_elem->mutually_recursive; } for (st_select_lex *sl= with_elem->spec->first_select(); diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 744f50eb7ef..8b81644e838 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -39,6 +39,7 @@ private: table_map work_dep_map; // dependency map used for work /* Dependency map of with elements mutually recursive with this with element */ table_map mutually_recursive; + With_element *next_mutually_recursive; /* Total number of references to this element in the FROM lists of the queries that are in the scope of the element (including @@ -87,17 +88,21 @@ public: select_union_recursive *rec_result; TABLE *result_table; + + TABLE *first_rec_table_to_update; With_element(LEX_STRING *name, List <LEX_STRING> list, st_select_lex_unit *unit) : next_elem(NULL), base_dep_map(0), derived_dep_map(0), - sq_dep_map(0), work_dep_map(0), mutually_recursive(0), + sq_dep_map(0), work_dep_map(0), mutually_recursive(0), + next_mutually_recursive(NULL), references(0), table(NULL), query_name(name), column_list(list), spec(unit), is_recursive(false), with_anchor(false), - level(0), rec_result(NULL), result_table(NULL) + level(0), rec_result(NULL), result_table(NULL), + first_rec_table_to_update(NULL) {} bool check_dependencies_in_spec(THD *thd); @@ -146,6 +151,9 @@ public: table_map get_mutually_recursive() { return mutually_recursive; } + With_element *get_next_mutually_recursive() + { return next_mutually_recursive; } + void set_table(TABLE *tab) { table= tab; } TABLE *get_table() { return table; } @@ -166,22 +174,6 @@ public: void reset_for_exec(); - bool no_driving_recursive_is_set(); - - void set_as_driving_recursive(); - - bool is_driving_recursive(); - - void cleanup_driving_recursive(); - - void cleanup_incr_ready(); - - void set_as_incr_ready(); - - bool is_incr_ready(); - - bool all_incr_are_ready(); - void cleanup_stabilized(); void set_as_stabilized(); @@ -228,8 +220,6 @@ private: table_map unrestricted; table_map with_prepared_anchor; table_map cleaned; - table_map driving_recursive; - table_map incr_ready; table_map stabilized; public: @@ -241,7 +231,7 @@ public: embedding_with_clause(emb_with_clause), next_with_clause(NULL), dependencies_are_checked(false), unrestricted(0), with_prepared_anchor(0), cleaned(0), - driving_recursive(0), incr_ready(0), stabilized(0), + stabilized(0), with_recursive(recursive_fl) { last_next= &first_elem; } @@ -331,69 +321,12 @@ void With_element::reset_for_exec() level= 0; owner->with_prepared_anchor&= ~mutually_recursive; owner->cleaned&= ~get_elem_map(); - owner->driving_recursive&= ~get_elem_map(); - cleanup_incr_ready(); + first_rec_table_to_update= NULL; cleanup_stabilized(); } inline -bool With_element::no_driving_recursive_is_set() -{ - return !(owner->driving_recursive & mutually_recursive); -} - - -inline -void With_element::set_as_driving_recursive() -{ - owner->driving_recursive|= get_elem_map(); -} - - -inline -bool With_element::is_driving_recursive() -{ - return owner->driving_recursive & get_elem_map(); -} - - -inline -void With_element::cleanup_driving_recursive() -{ - owner->driving_recursive&= ~mutually_recursive; -} - - -inline -void With_element::cleanup_incr_ready() -{ - owner->incr_ready&= ~mutually_recursive; -} - - -inline -void With_element::set_as_incr_ready() -{ - owner->incr_ready|= get_elem_map(); -} - - -inline -bool With_element::is_incr_ready() -{ - return owner->incr_ready & get_elem_map(); -} - - -inline -bool With_element::all_incr_are_ready() -{ - return (owner->incr_ready & mutually_recursive) == mutually_recursive; -} - - -inline void With_element::cleanup_stabilized() { owner->stabilized&= ~mutually_recursive; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index f84cdd939fe..b1f665ad70b 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -663,7 +663,6 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived->is_with_table_recursive_reference()) { unit->with_element->rec_result->rec_tables.push_back(derived->table); - derived->table->is_rec_table= true; } } DBUG_ASSERT(derived->table || res); @@ -921,6 +920,28 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) } +bool TABLE_LIST::fill_recursive(THD *thd) +{ + bool rc= false; + st_select_lex_unit *unit= get_unit(); + if (is_with_table_recursive_reference()) + rc= unit->exec_recursive(false); + else + { + while(!with->all_are_stabilized() && !rc) + { + rc= unit->exec_recursive(true); + } + if (!rc) + { + TABLE *src= with->rec_result->table; + rc =src->insert_all_rows_into(thd, table, true); + } + } + return rc; +} + + /* Execute subquery of a materialized derived table/view and fill the result table. @@ -944,6 +965,7 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) @return TRUE Error */ + bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_fill"); @@ -951,14 +973,6 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) bool derived_is_recursive= derived->is_recursive_with_table(); bool res= FALSE; - if (derived_is_recursive && derived->with->all_are_stabilized()) - { - TABLE *src= unit->with_element->rec_result->table; - TABLE *dest= derived->table; - res= src->insert_all_rows_into(thd, dest, true); - DBUG_RETURN(res); - } - if (unit->executed && !unit->uncacheable && !unit->describe && !derived_is_recursive) DBUG_RETURN(FALSE); @@ -967,11 +981,14 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX *first_select= unit->first_select(); select_union *derived_result= derived->derived_result; SELECT_LEX *save_current_select= lex->current_select; - if (unit->is_union() || derived_is_recursive) + + if (derived_is_recursive) + { + res= derived->fill_recursive(thd); + } + else if (unit->is_union()) { // execute union without clean up - if (derived_is_recursive) - unit->with_element->set_result_table(derived->table); res= unit->exec(); } else @@ -995,15 +1012,13 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) derived_result, unit, first_select); } - if (!res) + if (!res && !derived_is_recursive) { if (derived_result->flush()) res= TRUE; unit->executed= TRUE; } - if (res || - (!lex->describe && - !(unit->with_element && unit->with_element->is_recursive))) + if (res || (!lex->describe && !derived_is_recursive)) unit->cleanup(); lex->current_select= save_current_select; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8cfb2f99fb0..785908d9750 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -704,7 +704,7 @@ public: bool prepare(THD *thd, select_result *result, ulong additional_options); bool optimize(); bool exec(); - bool exec_recursive(); + bool exec_recursive(bool is_driving_recursive); bool cleanup(); inline void unclean() { cleaned= 0; } void reinit_exec_mechanism(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 25a509472dc..9b537a61c29 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11606,11 +11606,7 @@ bool JOIN_TAB::preread_init() /* Materialize derived table/view. */ if ((!derived->get_unit()->executed || - (derived->is_recursive_with_table() && - (!derived->is_with_table_recursive_reference() || - (!derived->with->is_driving_recursive() && - !derived->with->is_incr_ready()) && - !derived->with->all_are_stabilized()))) && + derived->is_recursive_with_table()) && mysql_handle_single_derived(join->thd->lex, derived, DT_CREATE | DT_FILL)) return TRUE; @@ -18241,8 +18237,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) flush_dups_table->sj_weedout_delete_rows(); } - if ((!join_tab->preread_init_done || join_tab->table->is_rec_table) && - join_tab->preread_init()) + if (!join_tab->preread_init_done && join_tab->preread_init()) DBUG_RETURN(NESTED_LOOP_ERROR); join->return_tab= join_tab; @@ -19195,8 +19190,7 @@ int join_init_read_record(JOIN_TAB *tab) report_error(tab->table, error); return 1; } - if ((!tab->preread_init_done || tab->table->is_rec_table) && - tab->preread_init()) + if (!tab->preread_init_done && tab->preread_init()) return 1; if (init_read_record(&tab->read_record, tab->join->thd, tab->table, tab->select, tab->filesort_result, 1,1, FALSE)) @@ -19429,8 +19423,6 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!end_of_records) { -#if 0 -#endif if (join->table_count && join->join_tab->is_using_loose_index_scan()) { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 14c66f6546c..4c32779f347 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -244,7 +244,6 @@ select_union_recursive::create_result_table(THD *thd_arg, if (rec_tables.push_back(rec_table)) return true; - rec_table->is_rec_table= true; return false; } @@ -918,9 +917,8 @@ bool st_select_lex_unit::exec() bool first_execution= !executed; DBUG_ENTER("st_select_lex_unit::exec"); bool was_executed= executed; - bool is_recursive= with_element && with_element->is_recursive; - if (executed && !uncacheable && !describe && !is_recursive) + if (executed && !uncacheable && !describe) DBUG_RETURN(FALSE); executed= 1; if (!(uncacheable & ~UNCACHEABLE_EXPLAIN) && item) @@ -936,12 +934,6 @@ bool st_select_lex_unit::exec() if (saved_error) DBUG_RETURN(saved_error); - if (is_recursive && !describe) - { - saved_error= exec_recursive(); - DBUG_RETURN(saved_error); - } - if (uncacheable || !item || !item->assigned() || describe) { if (!fake_select_lex && !(with_element && with_element->is_recursive)) @@ -1168,107 +1160,95 @@ err: -bool st_select_lex_unit::exec_recursive() +bool st_select_lex_unit::exec_recursive(bool is_driving_recursive) { st_select_lex *lex_select_save= thd->lex->current_select; - st_select_lex *first_recursive_sel= with_element->first_recursive; + st_select_lex *start= with_element->first_recursive; TABLE *incr_table= with_element->rec_result->incr_table; - TABLE *result_table= with_element->result_table; - ha_rows examined_rows= 0; - bool unrestricted= with_element->is_unrestricted(); - bool with_anchor= with_element->with_anchor; - uint max_level= thd->variables.max_recursion_level; + st_select_lex *end= NULL; + bool is_unrestricted= with_element->is_unrestricted(); List_iterator_fast<TABLE> li(with_element->rec_result->rec_tables); + ha_rows examined_rows= 0; + bool was_executed= executed; TABLE *rec_table; DBUG_ENTER("st_select_lex_unit::exec_recursive"); - do - { - st_select_lex *first_sl; - st_select_lex *barrier; - if ((saved_error= incr_table->file->ha_delete_all_rows())) - goto err; + executed= 1; + create_explain_query_if_not_exists(thd->lex, thd->mem_root); + if (!was_executed) + save_union_explain(thd->lex->explain); - if (with_element->no_driving_recursive_is_set()) - with_element->set_as_driving_recursive(); + if ((saved_error= incr_table->file->ha_delete_all_rows())) + goto err; - if (with_element->level == 0) - { - first_sl= first_select(); - if (with_anchor) - barrier= first_recursive_sel; - else - barrier= NULL; - } - else + if (is_driving_recursive) + { + With_element *with_elem= with_element; + while ((with_elem= with_elem->get_next_mutually_recursive()) != + with_element) { - first_sl= first_recursive_sel; - barrier= NULL; + rec_table= with_elem->first_rec_table_to_update; + if (rec_table) + rec_table->reginfo.join_tab->preread_init_done= false; } + } - if (with_element->all_incr_are_ready()) - with_element->cleanup_incr_ready(); + if (with_element->level == 0) + { + start= first_select(); + if (with_element->with_anchor) + end= with_element->first_recursive; + } - for (st_select_lex *sl= first_sl ; sl != barrier; sl= sl->next_select()) + for (st_select_lex *sl= start ; sl != end; sl= sl->next_select()) + { + thd->lex->current_select= sl; + sl->join->exec(); + saved_error= sl->join->error; + if (!saved_error) { - thd->lex->current_select= sl; - sl->join->exec(); - saved_error= sl->join->error; - if (!saved_error) - { - examined_rows+= thd->get_examined_row_count(); - thd->set_examined_row_count(0); - if (union_result->flush()) - { - thd->lex->current_select= lex_select_save; - DBUG_RETURN(1); - } - } - if (saved_error) - { - thd->lex->current_select= lex_select_save; - goto err; - } + examined_rows+= thd->get_examined_row_count(); + thd->set_examined_row_count(0); + if (union_result->flush()) + { + thd->lex->current_select= lex_select_save; + DBUG_RETURN(1); + } } - - with_element->set_as_incr_ready(); - - incr_table->file->info(HA_STATUS_VARIABLE); - if (incr_table->file->stats.records == 0 || - with_element->level + 1 == max_level) - with_element->set_as_stabilized(); - else - with_element->level++; - - li.rewind(); - while ((rec_table= li++)) + if (saved_error) { - if ((saved_error= incr_table->insert_all_rows_into(thd, rec_table, - !unrestricted))) - goto err; + thd->lex->current_select= lex_select_save; + goto err; + } - - if (!with_element->is_driving_recursive()) - break; + } - } while (!with_element->all_are_stabilized()); + thd->inc_examined_row_count(examined_rows); - if (with_element->is_driving_recursive()) + incr_table->file->info(HA_STATUS_VARIABLE); + if (incr_table->file->stats.records == 0) + with_element->set_as_stabilized(); + else + with_element->level++; + + while ((rec_table= li++)) { - TABLE *table= with_element->rec_result->table; - if ((saved_error= table->insert_all_rows_into(thd, - result_table, - true))) - goto err; - with_element->cleanup_driving_recursive(); + saved_error= + incr_table->insert_all_rows_into(thd, rec_table, !is_unrestricted); + if (!with_element->first_rec_table_to_update) + with_element->first_rec_table_to_update= rec_table; + if (with_element->level == 1) + rec_table->reginfo.join_tab->preread_init_done= true; } + + if (with_element->level == thd->variables.max_recursion_level) + with_element->set_as_stabilized(); thd->lex->current_select= lex_select_save; err: thd->lex->set_limit_rows_examined(); - DBUG_RETURN(saved_error); - + DBUG_RETURN(saved_error); } diff --git a/sql/table.h b/sql/table.h index a8d01a64599..143bf17f4d4 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1244,7 +1244,6 @@ public: bool alias_name_used; /* true if table_name is alias */ bool get_fields_in_item_tree; /* Signal to fix_field */ bool m_needs_reopen; - bool is_rec_table; private: bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/ public: @@ -2234,6 +2233,7 @@ struct TABLE_LIST bool is_with_table(); bool is_recursive_with_table(); bool is_with_table_recursive_reference(); + bool fill_recursive(THD *thd); inline void set_view() { |