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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
fef409cb
Commit
fef409cb
authored
Aug 14, 2009
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MWL#17: Table elimination
- More function renames, added comments
parent
a2839036
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
189 additions
and
124 deletions
+189
-124
sql/opt_table_elimination.cc
sql/opt_table_elimination.cc
+189
-124
No files found.
sql/opt_table_elimination.cc
View file @
fef409cb
...
...
@@ -93,11 +93,9 @@ public:
/*
A field.
- Depends on table or equality
- Has expressions it participates as dependencies
There is no counter, bound fields are in $list, not bound are not.
A table field. There is only one such object for any tblX.fieldY
- the field epends on its table and equalities
- expressions that use the field are its dependencies
*/
class
Field_dep
:
public
Func_dep
{
...
...
@@ -107,19 +105,23 @@ public:
{
type
=
Func_dep
::
FD_FIELD
;
}
/* Table we're from. It also has pointers to keys that we're part of */
Table_dep
*
table
;
Table_dep
*
table
;
/* Table this field is from */
Field
*
field
;
/*
Field_deps that belong to one table form a linked list. list members are
ordered by field_index
*/
Field_dep
*
next_table_field
;
uint
bitmap_offset
;
/* Offset of our part of the bitmap */
};
/*
A
u
nique key.
-
Depends on all
its components
-
Has its table a
s dependency
A
U
nique key.
-
Unique key depends on all of
its components
-
Key's table is it
s dependency
*/
class
Key_dep
:
public
Func_dep
{
...
...
@@ -133,14 +135,15 @@ public:
Table_dep
*
table
;
/* Table this key is from */
uint
keyno
;
uint
n_missing_keyparts
;
/* Unique keys form a linked list, ordered by keyno */
Key_dep
*
next_table_key
;
};
/*
A table.
-
D
epends on any of its unique keys
-
H
as its fields and embedding outer join as dependency.
-
table d
epends on any of its unique keys
-
h
as its fields and embedding outer join as dependency.
*/
class
Table_dep
:
public
Func_dep
{
...
...
@@ -151,16 +154,16 @@ public:
type
=
Func_dep
::
FD_TABLE
;
}
TABLE
*
table
;
Field_dep
*
fields
;
/*
F
ields that belong to this table */
Key_dep
*
keys
;
/*
Unique keys
*/
Outer_join_dep
*
outer_join_dep
;
Field_dep
*
fields
;
/*
Ordered list of f
ields that belong to this table */
Key_dep
*
keys
;
/*
Ordered list of Unique keys in this table
*/
Outer_join_dep
*
outer_join_dep
;
/* Innermost eliminable outer join we're in */
};
/*
An outer join nest
.
-
Depends on all tables inside it.
-
(And that's it).
An outer join nest
that is subject to elimination
-
it depends on all tables inside it
-
has its parent outer join as dependency
*/
class
Outer_join_dep
:
public
Func_dep
{
...
...
@@ -171,14 +174,27 @@ public:
{
type
=
Func_dep
::
FD_OUTER_JOIN
;
}
/*
Outer join we're representing. This can be a join nest or a one table that
is outer join'ed.
*/
TABLE_LIST
*
table_list
;
/*
Tables within this outer join (and its descendants) that are not yet known
to be functionally dependent.
*/
table_map
missing_tables
;
/* All tables within this outer join and its descendants */
table_map
all_tables
;
/* Parent eliminable outer join, if any */
Outer_join_dep
*
parent
;
};
/* TODO need this? */
/*
Table elimination context
*/
class
Table_elimination
{
public:
...
...
@@ -204,11 +220,11 @@ public:
static
void
build_
func
deps_for_cond
(
Table_elimination
*
te
,
Equality_dep
**
fdeps
,
void
build_
eq_
deps_for_cond
(
Table_elimination
*
te
,
Equality_dep
**
fdeps
,
uint
*
and_level
,
Item
*
cond
,
table_map
usable_tables
);
static
void
add_
func
dep
(
Table_elimination
*
te
,
void
add_
eq_
dep
(
Table_elimination
*
te
,
Equality_dep
**
eq_dep
,
uint
and_level
,
Item_func
*
cond
,
Field
*
field
,
bool
eq_func
,
Item
**
value
,
...
...
@@ -217,7 +233,9 @@ static
Equality_dep
*
merge_func_deps
(
Equality_dep
*
start
,
Equality_dep
*
new_fields
,
Equality_dep
*
end
,
uint
and_level
);
Field_dep
*
get_field_dep
(
Table_elimination
*
te
,
Field
*
field
);
static
Table_dep
*
get_table_dep
(
Table_elimination
*
te
,
TABLE
*
table
);
static
Field_dep
*
get_field_dep
(
Table_elimination
*
te
,
Field
*
field
);
void
eliminate_tables
(
JOIN
*
join
);
static
void
mark_as_eliminated
(
JOIN
*
join
,
TABLE_LIST
*
tbl
);
...
...
@@ -228,23 +246,24 @@ static void dbug_print_deps(Table_elimination *te);
/*******************************************************************************************/
/*
Produce FUNC_DEP elements for the given item (i.e. condition) and add them
to fdeps array.
Produce Eq_dep elements for given condition.
SYNOPSIS
build_funcdeps_for_cond()
fdeps INOUT Put created FUNC_DEP structures here
build_eq_deps_for_cond()
te Table elimination context
fdeps INOUT Put produced equality conditions here
and_level INOUT AND-level (like in add_key_fields)
cond Condition to process
usable_tables Tables which fields we're interested in. That is,
Equality_dep represent "tbl.col=expr" and we'll
produce them only if tbl is in usable_tables.
DESCRIPTION
a
SEE ALSO
add_key_fields()
This function is modeled after add_key_fields()
*/
static
void
build_
funcdeps_for_cond
(
Table_elimination
*
te
,
Equality_dep
**
fdeps
,
uint
*
and_level
,
Item
*
cond
,
void
build_
eq_deps_for_cond
(
Table_elimination
*
te
,
Equality_dep
**
fdeps
,
uint
*
and_level
,
Item
*
cond
,
table_map
usable_tables
)
{
if
(
cond
->
type
()
==
Item_func
::
COND_ITEM
)
...
...
@@ -258,7 +277,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
Item
*
item
;
while
((
item
=
li
++
))
{
build_
func
deps_for_cond
(
te
,
fdeps
,
and_level
,
item
,
usable_tables
);
build_
eq_
deps_for_cond
(
te
,
fdeps
,
and_level
,
item
,
usable_tables
);
}
/*
TODO: inject here a "if we have {t.col=const AND t.col=smth_else}, then
...
...
@@ -270,13 +289,13 @@ void build_funcdeps_for_cond(Table_elimination *te,
else
{
(
*
and_level
)
++
;
build_
func
deps_for_cond
(
te
,
fdeps
,
and_level
,
li
++
,
usable_tables
);
build_
eq_
deps_for_cond
(
te
,
fdeps
,
and_level
,
li
++
,
usable_tables
);
Item
*
item
;
while
((
item
=
li
++
))
{
Equality_dep
*
start_key_fields
=
*
fdeps
;
(
*
and_level
)
++
;
build_
func
deps_for_cond
(
te
,
fdeps
,
and_level
,
item
,
usable_tables
);
build_
eq_
deps_for_cond
(
te
,
fdeps
,
and_level
,
item
,
usable_tables
);
*
fdeps
=
merge_func_deps
(
org_key_fields
,
start_key_fields
,
*
fdeps
,
++
(
*
and_level
));
}
...
...
@@ -304,7 +323,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
values
--
;
DBUG_ASSERT
(
cond_func
->
functype
()
!=
Item_func
::
IN_FUNC
||
cond_func
->
argument_count
()
!=
2
);
add_
func
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
add_
eq_
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
((
Item_field
*
)(
cond_func
->
key_item
()
->
real_item
()))
->
field
,
0
,
values
,
cond_func
->
argument_count
()
-
1
,
...
...
@@ -321,7 +340,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
!
(
cond_func
->
arguments
()[
i
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
field_item
=
(
Item_field
*
)
(
cond_func
->
arguments
()[
i
]
->
real_item
());
add_
func
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
add_
eq_
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
field_item
->
field
,
0
,
values
,
1
,
usable_tables
);
}
}
...
...
@@ -336,7 +355,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
if
(
cond_func
->
arguments
()[
0
]
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
&&
!
(
cond_func
->
arguments
()[
0
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
add_
func
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
add_
eq_
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
((
Item_field
*
)(
cond_func
->
arguments
()[
0
])
->
real_item
())
->
field
,
equal_func
,
cond_func
->
arguments
()
+
1
,
1
,
usable_tables
);
...
...
@@ -345,7 +364,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
cond_func
->
functype
()
!=
Item_func
::
LIKE_FUNC
&&
!
(
cond_func
->
arguments
()[
1
]
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
add_
func
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
add_
eq_
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
((
Item_field
*
)(
cond_func
->
arguments
()[
1
])
->
real_item
())
->
field
,
equal_func
,
cond_func
->
arguments
(),
1
,
usable_tables
);
...
...
@@ -360,7 +379,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
Item
*
tmp
=
new
Item_null
;
if
(
unlikely
(
!
tmp
))
// Should never be true
return
;
add_
func
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
add_
eq_
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
((
Item_field
*
)(
cond_func
->
arguments
()[
0
])
->
real_item
())
->
field
,
cond_func
->
functype
()
==
Item_func
::
ISNULL_FUNC
,
&
tmp
,
1
,
usable_tables
);
...
...
@@ -380,7 +399,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
*/
while
((
item
=
it
++
))
{
add_
func
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
item
->
field
,
add_
eq_
dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
item
->
field
,
TRUE
,
&
const_item
,
1
,
usable_tables
);
}
}
...
...
@@ -400,7 +419,7 @@ void build_funcdeps_for_cond(Table_elimination *te,
{
if
(
!
field
->
eq
(
item
->
field
))
{
add_
funcdep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
field
/*item*/
,
add_
eq_dep
(
te
,
fdeps
,
*
and_level
,
cond_func
,
field
,
TRUE
,
(
Item
**
)
&
item
,
1
,
usable_tables
);
}
}
...
...
@@ -411,15 +430,19 @@ void build_funcdeps_for_cond(Table_elimination *te,
}
}
/*
Perform an OR operation on two (adjacent)
FUNC_DEP
arrays.
Perform an OR operation on two (adjacent)
Equality_dep
arrays.
SYNOPSIS
merge_func_deps()
start Start of left OR-part
new_fields Start of right OR-part
end End of right OR-part
and_level AND-level.
DESCRIPTION
This function is invoked for two adjacent arrays of FUNC_DEP elements:
This function is invoked for two adjacent arrays of Equality_dep elements:
$LEFT_PART $RIGHT_PART
+-----------------------+-----------------------+
...
...
@@ -527,17 +550,18 @@ Equality_dep *merge_func_deps(Equality_dep *start, Equality_dep *new_fields,
/*
Add a funcdep for a given equality.
Add an Equality_dep element for a given predicate, if applicable
DESCRIPTION
This function is modeled after add_key_field().
*/
static
void
add_funcdep
(
Table_elimination
*
te
,
Equality_dep
**
eq_dep
,
uint
and_level
,
Item_func
*
cond
,
Field
*
field
,
bool
eq_func
,
Item
**
value
,
uint
num_values
,
table_map
usable_tables
)
void
add_eq_dep
(
Table_elimination
*
te
,
Equality_dep
**
eq_dep
,
uint
and_level
,
Item_func
*
cond
,
Field
*
field
,
bool
eq_func
,
Item
**
value
,
uint
num_values
,
table_map
usable_tables
)
{
// Field *field= item_field->field;
if
(
!
(
field
->
table
->
map
&
usable_tables
))
return
;
...
...
@@ -606,7 +630,11 @@ void add_funcdep(Table_elimination *te,
}
Table_dep
*
get_table_dep
(
Table_elimination
*
te
,
TABLE
*
table
)
/*
Get a Table_dep object for the given table, creating it if necessary.
*/
static
Table_dep
*
get_table_dep
(
Table_elimination
*
te
,
TABLE
*
table
)
{
Table_dep
*
tbl_dep
=
new
Table_dep
(
table
);
Key_dep
**
key_list
=
&
(
tbl_dep
->
keys
);
...
...
@@ -625,19 +653,21 @@ Table_dep *get_table_dep(Table_elimination *te, TABLE *table)
return
te
->
table_deps
[
table
->
tablenr
]
=
tbl_dep
;
}
/*
Given a field, get its dependency element: if it already exists, find it,
otherwise create it.
Get a Field_dep object for the given field, creating it if necessary
*/
Field_dep
*
get_field_dep
(
Table_elimination
*
te
,
Field
*
field
)
static
Field_dep
*
get_field_dep
(
Table_elimination
*
te
,
Field
*
field
)
{
TABLE
*
table
=
field
->
table
;
Table_dep
*
tbl_dep
;
/* First, get the table*/
if
(
!
(
tbl_dep
=
te
->
table_deps
[
table
->
tablenr
]))
tbl_dep
=
get_table_dep
(
te
,
table
);
/* Try finding the field in field list */
Field_dep
**
pfield
=
&
(
tbl_dep
->
fields
);
while
(
*
pfield
&&
(
*
pfield
)
->
field
->
field_index
<
field
->
field_index
)
{
...
...
@@ -646,20 +676,34 @@ Field_dep *get_field_dep(Table_elimination *te, Field *field)
if
(
*
pfield
&&
(
*
pfield
)
->
field
->
field_index
==
field
->
field_index
)
return
*
pfield
;
/* Create the field and insert it in the list */
Field_dep
*
new_field
=
new
Field_dep
(
tbl_dep
,
field
);
new_field
->
next_table_field
=
*
pfield
;
*
pfield
=
new_field
;
return
new_field
;
}
/*
Create an Outer_join_dep object for the given outer join
DESCRIPTION
Outer_join_dep objects for children (or further descendants) are always
created before the parents.
*/
static
Outer_join_dep
*
get_outer_join_dep
(
Table_elimination
*
te
,
TABLE_LIST
*
outer_join
,
table_map
deps_map
)
{
Outer_join_dep
*
oj_dep
;
oj_dep
=
new
Outer_join_dep
(
outer_join
,
deps_map
);
/*
Collect a bitmap fo tables that we depend on, and also set parent pointer
for descendant outer join elements.
*/
Table_map_iterator
it
(
deps_map
);
int
idx
;
while
((
idx
=
it
.
next_bit
())
!=
Table_map_iterator
::
BITMAP_END
)
...
...
@@ -667,6 +711,11 @@ Outer_join_dep *get_outer_join_dep(Table_elimination *te,
Table_dep
*
table_dep
;
if
(
!
(
table_dep
=
te
->
table_deps
[
idx
]))
{
/*
We get here only when ON expression had no references to inner tables
and Table_map objects weren't created for them. This is a rare/
unimportant case so it's ok to do not too efficient searches.
*/
TABLE
*
table
=
NULL
;
for
(
TABLE_LIST
*
tlist
=
te
->
join
->
select_lex
->
leaf_tables
;
tlist
;
tlist
=
tlist
->
next_leaf
)
...
...
@@ -681,6 +730,12 @@ Outer_join_dep *get_outer_join_dep(Table_elimination *te,
table_dep
=
get_table_dep
(
te
,
table
);
}
/*
Walk from the table up to its embedding outer joins. The goal is to
find the least embedded outer join nest and set its parent pointer to
point to the newly created Outer_join_dep.
to set the pointer of its near
*/
if
(
!
table_dep
->
outer_join_dep
)
table_dep
->
outer_join_dep
=
oj_dep
;
else
...
...
@@ -690,43 +745,35 @@ Outer_join_dep *get_outer_join_dep(Table_elimination *te,
oj
=
oj
->
parent
;
oj
->
parent
=
oj_dep
;
}
}
return
oj_dep
;
}
/*
Perform table elimination in a
given join list
Build functional dependency graph for elements of
given join list
SYNOPSIS
collect_funcdeps_for_join_list()
te Table elimination context.
join_list Join list to work on
its_outer_join TRUE <=> the join_list is an inner side of an
outer join
FALSE <=> otherwise (this is top-level join
list, simplify_joins flattens out all
other kinds of join lists)
tables_in_list Bitmap of tables embedded in the join_list.
build_eq_deps TRUE <=> build Equality_dep elements for all
members of the join list, even if they cannot
be individually eliminated
tables_used_elsewhere Bitmap of tables that are referred to from
somewhere outside of the join list (e.g.
select list, HAVING, etc).
somewhere outside of this join list (e.g.
select list, HAVING, ON expressions of parent
joins, etc).
eliminable_tables INOUT Tables that can potentially be eliminated
(needed so we know for which tables to build
dependencies for)
eq_dep INOUT End of array of equality dependencies.
DESCRIPTION
Perform table elimination for a join list.
Try eliminating children nests first.
The "all tables in join nest can produce only one matching record
combination" property checking is modeled after constant table detection,
plus we reuse info attempts to eliminate child join nests.
RETURN
Number of children left after elimination. 0 means everything was
eliminated.
.
*/
static
uint
static
void
collect_funcdeps_for_join_list
(
Table_elimination
*
te
,
List
<
TABLE_LIST
>
*
join_list
,
bool
build_eq_deps
,
...
...
@@ -771,7 +818,7 @@ collect_funcdeps_for_join_list(Table_elimination *te,
{
// build comp_cond from ON expression
uint
and_level
=
0
;
build_
func
deps_for_cond
(
te
,
eq_dep
,
&
and_level
,
tbl
->
on_expr
,
build_
eq_
deps_for_cond
(
te
,
eq_dep
,
&
and_level
,
tbl
->
on_expr
,
*
eliminable_tables
);
}
...
...
@@ -781,19 +828,13 @@ collect_funcdeps_for_join_list(Table_elimination *te,
tables_used_on_left
|=
tbl
->
on_expr
->
used_tables
();
}
}
return
0
;
return
;
}
/*
Analyze exising FUNC_DEP array and add elements for tables and uniq keys
SYNOPSIS
DESCRIPTION
Add FUNC_DEP elements
RETURN
.
/*
This is used to analyse expressions in "tbl.col=expr" dependencies so
that we can figure out which fields the expression depends on.
*/
class
Field_dependency_setter
:
public
Field_enumerator
...
...
@@ -819,20 +860,41 @@ public:
return
;
}
}
/* We didn't find the field. Bump the dependency anyway */
/*
We got here if didn't find this field. It's not a part of
a unique key, and/or there is no field=expr element for it.
Bump the dependency anyway, this will signal that this dependency
cannot be satisfied.
*/
te
->
equality_deps
[
expr_offset
].
unknown_args
++
;
}
}
Table_elimination
*
te
;
uint
expr_offset
;
/* Offset of the expression we're processing */
/* Offset of the expression we're processing in the dependency bitmap */
uint
expr_offset
;
};
/*
Setup equality dependencies
SYNOPSIS
setup_equality_deps()
te Table elimination context
bound_deps_list OUT Start of linked list of elements that were found to
be bound (caller will use this to see if that
allows to declare further elements bound)
*/
static
bool
setup_equality_deps
(
Table_elimination
*
te
,
Func_dep
**
bound_deps_list
)
{
DBUG_ENTER
(
"setup_equality_deps"
);
/*
Count Field_dep objects and assign each of them a unique bitmap_offset.
*/
uint
offset
=
0
;
for
(
Table_dep
**
tbl_dep
=
te
->
table_deps
;
tbl_dep
<
te
->
table_deps
+
MAX_TABLES
;
...
...
@@ -859,7 +921,10 @@ bool setup_equality_deps(Table_elimination *te, Func_dep **bound_deps_list)
bitmap_clear_all
(
&
te
->
expr_deps
);
/*
Walk through all field=expr elements and collect all fields.
Analyze all "field=expr" dependencies, and have te->expr_deps encode
dependencies of expressions from fields.
Also collect a linked list of equalities that are bound.
*/
Func_dep
*
bound_dep
=
NULL
;
Field_dependency_setter
deps_setter
(
te
);
...
...
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