Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
96065256
Commit
96065256
authored
Jun 25, 2016
by
Igor Babaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplified the code that fills recursive tables.
parent
0eec1871
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
135 additions
and
205 deletions
+135
-205
sql/sql_cte.cc
sql/sql_cte.cc
+23
-13
sql/sql_cte.h
sql/sql_cte.h
+12
-79
sql/sql_derived.cc
sql/sql_derived.cc
+31
-16
sql/sql_lex.h
sql/sql_lex.h
+1
-1
sql/sql_select.cc
sql/sql_select.cc
+3
-11
sql/sql_union.cc
sql/sql_union.cc
+64
-84
sql/table.h
sql/table.h
+1
-1
No files found.
sql/sql_cte.cc
View file @
96065256
...
...
@@ -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
();
...
...
sql/sql_cte.h
View file @
96065256
...
...
@@ -39,6 +39,7 @@ class With_element : public Sql_alloc
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 @@ class With_element : public Sql_alloc
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 @@ class With_element : public Sql_alloc
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 @@ class With_element : public Sql_alloc
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 @@ class With_clause : public Sql_alloc
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 @@ class With_clause : public Sql_alloc
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,68 +321,11 @@ 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
()
{
...
...
sql/sql_derived.cc
View file @
96065256
...
...
@@ -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
;
...
...
sql/sql_lex.h
View file @
96065256
...
...
@@ -704,7 +704,7 @@ class st_select_lex_unit: public st_select_lex_node {
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
();
...
...
sql/sql_select.cc
View file @
96065256
...
...
@@ -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())
{
...
...
sql/sql_union.cc
View file @
96065256
...
...
@@ -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 @@ bool st_select_lex_unit::exec()
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
);
}
...
...
sql/table.h
View file @
96065256
...
...
@@ -1244,7 +1244,6 @@ struct TABLE
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
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment