summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2016-06-25 21:38:40 -0700
committerIgor Babaev <igor@askmonty.org>2016-06-25 21:38:40 -0700
commit9606525666eeead285f211bd0e603b50b4f09189 (patch)
treedbc20fb0fc2c9fc5fad56914cd99cd5ea66dece0 /sql
parent0eec187153e8266b99f4ae66dba810a9b39e206d (diff)
downloadmariadb-git-9606525666eeead285f211bd0e603b50b4f09189.tar.gz
Simplified the code that fills recursive tables.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_cte.cc36
-rw-r--r--sql/sql_cte.h91
-rw-r--r--sql/sql_derived.cc47
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_select.cc14
-rw-r--r--sql/sql_union.cc148
-rw-r--r--sql/table.h2
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()
{