Commit c8f85bf2 authored by Igor Babaev's avatar Igor Babaev

mdev-9864: cleanup, re-factoring.

Added comments.
parent f33c3524
......@@ -128,6 +128,11 @@ class Item_subselect :public Item_result_field,
/* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */
bool is_correlated;
/*
TRUE <=> the subquery contains a recursive reference in the FROM list
of one of its selects. In this case some of subquery optimization
strategies cannot be applied for the subquery;
*/
bool with_recursive_reference;
enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
......
......@@ -7157,7 +7157,7 @@ ER_RECURSIVE_WITHOUT_ANCHORS
ER_UNACCEPTABLE_MUTUAL_RECURSION
eng "Unacceptable mutual recursion with anchored table '%s'"
ER_REF_TO_RECURSIVE_WITH_TABLE_IN_DERIVED
eng "Reference to recursive WITH table '%s' in materiazed derived"
eng "Reference to recursive WITH table '%s' in materialized derived"
ER_NOT_STANDARDS_COMPLIANT_RECURSIVE
eng "Restrictions imposed on recursive definitions are violated for table '%s'"
#
......
......@@ -4682,10 +4682,12 @@ class select_union_recursive :public select_union
{
public:
TABLE *incr_table;
TABLE *first_rec_table_to_update;
List<TABLE> rec_tables;
select_union_recursive(THD *thd_arg):
select_union(thd_arg), incr_table(0) {};
select_union(thd_arg),
incr_table(0), first_rec_table_to_update(0) {};
int send_data(List<Item> &items);
bool create_result_table(THD *thd, List<Item> *column_types,
......
This diff is collapsed.
......@@ -21,7 +21,7 @@ class With_element : public Sql_alloc
{
private:
With_clause *owner; // with clause this object belongs to
With_element *next_elem; // next element in the with clause
With_element *next; // next element in the with clause
uint number; // number of the element in the with clause (starting from 0)
table_map elem_map; // The map where with only one 1 set in this->number
/*
......@@ -35,11 +35,23 @@ class With_element : public Sql_alloc
The map derived_dep_map has 1 in i-th position if this with element depends
directly or indirectly from the i-th with element.
*/
table_map derived_dep_map;
table_map derived_dep_map;
/*
The map sq_dep_map has 1 in i-th position if there is a reference to this
with element somewhere in subqueries of the specifications of the tables
defined in the with clause containing this element;
*/
table_map sq_dep_map;
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;
table_map mutually_recursive;
/*
The next with element from the circular chain of the with elements
mutually recursive with this with element.
(If This element is simply recursive than next_mutually_recursive contains
the pointer to itself. If it's not recursive than next_mutually_recursive
is set to NULL.)
*/
With_element *next_mutually_recursive;
/*
Total number of references to this element in the FROM lists of
......@@ -56,8 +68,6 @@ class With_element : public Sql_alloc
/* Return the map where 1 is set only in the position for this element */
table_map get_elem_map() { return 1 << number; }
TABLE *table;
public:
/*
The name of the table introduced by this with elememt. The name
......@@ -79,34 +89,48 @@ class With_element : public Sql_alloc
*/
bool is_recursive;
/*
Any non-recursive select in the specification of a recursive
with element is a called anchor. In the case mutually recursive
elements the specification of some them may be without any anchor.
Yet at least one of them must contain an anchor.
All anchors of any recursivespecification are moved ahead before
the prepare stage.
*/
/* Set to true if this is a recursive element with an anchor */
bool with_anchor;
/*
Set to the first recursive select of the unit specifying the element
after all anchor have been moved to the head of the unit.
*/
st_select_lex *first_recursive;
/* The number of the last performed iteration for recursive table */
/*
The number of the last performed iteration for recursive table
(the number of the initial non-recursive step is 0, the number
of the first iteration is 1).
*/
uint level;
/*
The pointer to the object used to materialize this with element
if it's recursive. This object is built at the end of prepare
stage and is used at the execution stage.
*/
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),
: next(NULL), base_dep_map(0), derived_dep_map(0),
sq_dep_map(0), work_dep_map(0), mutually_recursive(0),
next_mutually_recursive(NULL),
references(0), table(NULL),
next_mutually_recursive(NULL), references(0),
query_name(name), column_list(list), spec(unit),
is_recursive(false), with_anchor(false),
level(0), rec_result(NULL), result_table(NULL),
first_rec_table_to_update(NULL)
level(0), rec_result(NULL)
{}
bool check_dependencies_in_spec(THD *thd);
bool check_dependencies_in_spec();
void check_dependencies_in_select(st_select_lex *sl, st_unit_ctxt_elem *ctxt,
bool in_subq, table_map *dep_map);
......@@ -155,10 +179,6 @@ class With_element : public Sql_alloc
With_element *get_next_mutually_recursive()
{ return next_mutually_recursive; }
void set_table(TABLE *tab) { table= tab; }
TABLE *get_table() { return table; }
bool is_anchor(st_select_lex *sel);
void move_anchors_ahead();
......@@ -173,7 +193,7 @@ class With_element : public Sql_alloc
void mark_as_cleaned();
void reset_for_exec();
void reset_recursive_for_exec();
void cleanup_stabilized();
......@@ -183,8 +203,6 @@ class With_element : public Sql_alloc
bool all_are_stabilized();
void set_result_table(TABLE *tab) { result_table= tab; }
bool instantiate_tmp_tables();
void prepare_for_next_iteration();
......@@ -206,9 +224,9 @@ class With_clause : public Sql_alloc
{
private:
st_select_lex_unit *owner; // the unit this with clause attached to
With_element *first_elem; // the first definition in this with clause
With_element **last_next; // here is set the link for the next added element
uint elements; // number of the elements/defintions in this with clauses
/* The list of all with elements from this with clause */
SQL_I_List<With_element> with_list;
/*
The with clause immediately containing this with clause if there is any,
otherwise NULL. Now used only at parsing.
......@@ -222,9 +240,22 @@ class With_clause : public Sql_alloc
/* Set to true if dependencies between with elements have been checked */
bool dependencies_are_checked;
/*
The bitmap of all recursive with elements whose specifications
are not complied with restrictions imposed by the SQL standards
on recursive specifications.
*/
table_map unrestricted;
/*
The bitmap of all recursive with elements whose anchors
has been already prepared.
*/
table_map with_prepared_anchor;
table_map cleaned;
/*
The bitmap of all recursive with elements that
has been already materialized
*/
table_map stabilized;
public:
......@@ -232,23 +263,20 @@ class With_clause : public Sql_alloc
bool with_recursive;
With_clause(bool recursive_fl, With_clause *emb_with_clause)
: owner(NULL), first_elem(NULL), elements(0),
: owner(NULL),
embedding_with_clause(emb_with_clause), next_with_clause(NULL),
dependencies_are_checked(false),
unrestricted(0), with_prepared_anchor(0), cleaned(0),
stabilized(0),
dependencies_are_checked(false), unrestricted(0),
with_prepared_anchor(0), cleaned(0), stabilized(0),
with_recursive(recursive_fl)
{ last_next= &first_elem; }
{ }
/* Add a new element to the current with clause */
bool add_with_element(With_element *elem)
{
elem->owner= this;
elem->number= elements;
elem->number= with_list.elements;
elem->spec->with_element= elem;
*last_next= elem;
last_next= &elem->next_elem;
elements++;
with_list.link_in_list(elem, &elem->next);
return false;
}
......@@ -263,7 +291,7 @@ class With_clause : public Sql_alloc
With_clause *pop() { return embedding_with_clause; }
bool check_dependencies(THD *thd);
bool check_dependencies();
bool check_anchors();
......@@ -283,7 +311,7 @@ class With_clause : public Sql_alloc
friend
bool
check_dependencies_in_with_clauses(THD *thd, With_clause *with_clauses_list);
check_dependencies_in_with_clauses(With_clause *with_clauses_list);
};
inline
......@@ -321,16 +349,18 @@ void With_element::mark_as_cleaned()
inline
void With_element::reset_for_exec()
void With_element::reset_recursive_for_exec()
{
DBUG_ASSERT(is_recursive);
level= 0;
owner->with_prepared_anchor&= ~mutually_recursive;
owner->cleaned&= ~get_elem_map();
first_rec_table_to_update= NULL;
cleanup_stabilized();
rec_result->first_rec_table_to_update= 0;
}
inline
void With_element::cleanup_stabilized()
{
......@@ -365,7 +395,7 @@ void With_element::prepare_for_next_iteration()
With_element *with_elem= this;
while ((with_elem= with_elem->get_next_mutually_recursive()) != this)
{
TABLE *rec_table= with_elem->first_rec_table_to_update;
TABLE *rec_table= with_elem->rec_result->first_rec_table_to_update;
if (rec_table)
rec_table->reginfo.join_tab->preread_init_done= false;
}
......
......@@ -1109,7 +1109,7 @@ class st_select_lex: public st_select_lex_node
}
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standards_compliant);
void check_subqueries_with_recursive_references();
bool check_subqueries_with_recursive_references();
List<Window_spec> window_specs;
void prepare_add_window_spec(THD *thd);
......@@ -2475,7 +2475,7 @@ struct LEX: public Query_tables_list
SELECT_LEX *all_selects_list;
/* current with clause in parsing if any, otherwise 0*/
With_clause *curr_with_clause;
/* pointer to the first with clause in the current statemant */
/* pointer to the first with clause in the current statement */
With_clause *with_clauses_list;
/*
(*with_clauses_list_last_next) contains a pointer to the last
......
......@@ -6233,7 +6233,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
new (thd->mem_root) Item_int(thd,
(ulonglong) thd->variables.select_limit);
}
if (check_dependencies_in_with_clauses(thd, lex->with_clauses_list))
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
return 1;
if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
......
......@@ -1509,7 +1509,7 @@ static int mysql_test_select(Prepared_statement *stmt,
lex->select_lex.context.resolve_in_select_list= TRUE;
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
if (check_dependencies_in_with_clauses(thd,lex->with_clauses_list))
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
goto error;
if (tables)
{
......
......@@ -1231,8 +1231,8 @@ bool st_select_lex_unit::exec_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->rec_result->first_rec_table_to_update)
with_element->rec_result->first_rec_table_to_update= rec_table;
if (with_element->level == 1)
rec_table->reginfo.join_tab->preread_init_done= true;
}
......@@ -1257,14 +1257,7 @@ bool st_select_lex_unit::cleanup()
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
error|= sl->cleanup();
if (union_result && with_element && with_element->is_recursive)
{
((select_union_recursive *) union_result)->cleanup();
delete union_result;
union_result= 0;
}
if (fake_select_lex)
{
error|= fake_select_lex->cleanup();
......@@ -1289,15 +1282,25 @@ bool st_select_lex_unit::cleanup()
}
if (with_element && with_element->is_recursive)
{
if (union_result )
{
((select_union_recursive *) union_result)->cleanup();
delete union_result;
union_result= 0;
}
with_element->mark_as_cleaned();
if (union_result && !(with_element &&with_element->is_recursive))
}
else
{
delete union_result;
union_result=0; // Safety
if (table)
free_tmp_table(thd, table);
table= 0; // Safety
if (union_result)
{
delete union_result;
union_result=0; // Safety
if (table)
free_tmp_table(thd, table);
table= 0; // Safety
}
}
DBUG_RETURN(error);
......@@ -1325,7 +1328,7 @@ void st_select_lex_unit::reinit_exec_mechanism()
}
#endif
if (with_element && with_element->is_recursive)
with_element->reset_for_exec();
with_element->reset_recursive_for_exec();
}
......
......@@ -430,7 +430,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
view->open_type= OT_BASE_ONLY;
if (check_dependencies_in_with_clauses(thd, lex->with_clauses_list))
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
{
res= TRUE;
goto err;
......@@ -1390,7 +1390,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
TABLE_LIST *tbl;
Security_context *security_ctx= 0;
if (check_dependencies_in_with_clauses(thd, thd->lex->with_clauses_list))
if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list))
goto err;
/*
......
......@@ -1857,8 +1857,9 @@ struct TABLE_LIST
derived tables. Use TABLE_LIST::is_anonymous_derived_table().
*/
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
With_element *with; /* With element of with_table */
table_map with_internal_reference_map;
With_element *with; /* With element defining this table (if any) */
/* Bitmap of the defining with element */
table_map with_internal_reference_map;
bool block_handle_derived;
ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
st_select_lex *schema_select_lex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment