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
3f5b4949
Commit
3f5b4949
authored
Aug 20, 2009
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MWL#17: Table elimination
- Multiple-equality handling
parent
46c96776
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
299 additions
and
119 deletions
+299
-119
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+1
-0
sql/opt_table_elimination.cc
sql/opt_table_elimination.cc
+298
-119
No files found.
sql/item_cmpfunc.h
View file @
3f5b4949
...
@@ -1578,6 +1578,7 @@ public:
...
@@ -1578,6 +1578,7 @@ public:
uint
members
();
uint
members
();
bool
contains
(
Field
*
field
);
bool
contains
(
Field
*
field
);
Item_field
*
get_first
()
{
return
fields
.
head
();
}
Item_field
*
get_first
()
{
return
fields
.
head
();
}
uint
n_fields
()
{
return
fields
.
elements
;
}
void
merge
(
Item_equal
*
item
);
void
merge
(
Item_equal
*
item
);
void
update_const
();
void
update_const
();
enum
Functype
functype
()
const
{
return
MULT_EQUAL_FUNC
;
}
enum
Functype
functype
()
const
{
return
MULT_EQUAL_FUNC
;
}
...
...
sql/opt_table_elimination.cc
View file @
3f5b4949
...
@@ -175,7 +175,10 @@ public:
...
@@ -175,7 +175,10 @@ public:
field_index
field_index
*/
*/
Field_value
*
next_table_field
;
Field_value
*
next_table_field
;
uint
bitmap_offset
;
/* Offset of our part of the bitmap */
/*
Offset of our part of the bitmap psergey-todo: better comment!
*/
uint
bitmap_offset
;
/*
/*
Field became known. Check out
Field became known. Check out
...
@@ -214,10 +217,6 @@ public:
...
@@ -214,10 +217,6 @@ public:
class
Module_dep
:
public
Sql_alloc
class
Module_dep
:
public
Sql_alloc
{
{
public:
public:
enum
{
MODULE_OUTER_JOIN
}
type
;
/* Type of the object */
virtual
bool
now_bound
(
Func_dep_analyzer
*
fda
,
Value_dep
**
bound_modules
)
=
0
;
virtual
bool
now_bound
(
Func_dep_analyzer
*
fda
,
Value_dep
**
bound_modules
)
=
0
;
virtual
~
Module_dep
(){}
virtual
~
Module_dep
(){}
/*
/*
...
@@ -232,8 +231,10 @@ public:
...
@@ -232,8 +231,10 @@ public:
/*
/*
A "tbl.column= expr" equality dependency. tbl.column depends on fields
This represents either
used in expr.
- "tbl.column= expr" equality dependency, i.e. tbl.column depends on fields
used in the expression, or
- tbl1.col1=tbl2.col2=... multi-equality.
*/
*/
class
Equality_module
:
public
Module_dep
class
Equality_module
:
public
Module_dep
{
{
...
@@ -241,6 +242,8 @@ public:
...
@@ -241,6 +242,8 @@ public:
Field_value
*
field
;
Field_value
*
field
;
Item
*
expression
;
Item
*
expression
;
List
<
Field_value
>
*
mult_equal_fields
;
/* Used during condition analysis only, similar to KEYUSE::level */
/* Used during condition analysis only, similar to KEYUSE::level */
uint
level
;
uint
level
;
bool
now_bound
(
Func_dep_analyzer
*
fda
,
Value_dep
**
bound_values
);
bool
now_bound
(
Func_dep_analyzer
*
fda
,
Value_dep
**
bound_values
);
...
@@ -331,7 +334,7 @@ bool check_func_dependency(JOIN *join,
...
@@ -331,7 +334,7 @@ bool check_func_dependency(JOIN *join,
Item
*
cond
);
Item
*
cond
);
static
static
void
build_eq_mods_for_cond
(
Func_dep_analyzer
*
fda
,
Equality_module
**
fdeps
,
void
build_eq_mods_for_cond
(
Func_dep_analyzer
*
fda
,
Equality_module
**
eq_mod
,
uint
*
and_level
,
Item
*
cond
);
uint
*
and_level
,
Item
*
cond
);
static
static
void
add_eq_mod
(
Func_dep_analyzer
*
fda
,
Equality_module
**
eq_mod
,
void
add_eq_mod
(
Func_dep_analyzer
*
fda
,
Equality_module
**
eq_mod
,
...
@@ -346,6 +349,9 @@ static Table_value *get_table_value(Func_dep_analyzer *fda, TABLE *table);
...
@@ -346,6 +349,9 @@ static Table_value *get_table_value(Func_dep_analyzer *fda, TABLE *table);
static
Field_value
*
get_field_value
(
Func_dep_analyzer
*
fda
,
Field
*
field
);
static
Field_value
*
get_field_value
(
Func_dep_analyzer
*
fda
,
Field
*
field
);
static
void
mark_as_eliminated
(
JOIN
*
join
,
TABLE_LIST
*
tbl
);
static
void
mark_as_eliminated
(
JOIN
*
join
,
TABLE_LIST
*
tbl
);
static
void
add_eq_mod2
(
Func_dep_analyzer
*
fda
,
Equality_module
**
eq_mod
,
uint
and_level
,
Field_value
*
field_val
,
Item
*
right
,
List
<
Field_value
>*
mult_equal_fields
);
#ifndef DBUG_OFF
#ifndef DBUG_OFF
...
@@ -360,7 +366,7 @@ static void dbug_print_deps(Func_dep_analyzer *fda);
...
@@ -360,7 +366,7 @@ static void dbug_print_deps(Func_dep_analyzer *fda);
SYNOPSIS
SYNOPSIS
build_eq_mods_for_cond()
build_eq_mods_for_cond()
fda Table elimination context
fda Table elimination context
fdeps
INOUT Put produced equality conditions here
eq_mod
INOUT Put produced equality conditions here
and_level INOUT AND-level (like in add_key_fields)
and_level INOUT AND-level (like in add_key_fields)
cond Condition to process
cond Condition to process
...
@@ -369,34 +375,34 @@ static void dbug_print_deps(Func_dep_analyzer *fda);
...
@@ -369,34 +375,34 @@ static void dbug_print_deps(Func_dep_analyzer *fda);
*/
*/
static
static
void
build_eq_mods_for_cond
(
Func_dep_analyzer
*
fda
,
Equality_module
**
fdeps
,
void
build_eq_mods_for_cond
(
Func_dep_analyzer
*
fda
,
Equality_module
**
eq_mod
,
uint
*
and_level
,
Item
*
cond
)
uint
*
and_level
,
Item
*
cond
)
{
{
if
(
cond
->
type
()
==
Item_func
::
COND_ITEM
)
if
(
cond
->
type
()
==
Item_func
::
COND_ITEM
)
{
{
List_iterator_fast
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
List_iterator_fast
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
Equality_module
*
org_key_fields
=
*
fdeps
;
Equality_module
*
org_key_fields
=
*
eq_mod
;
/* AND/OR */
/* AND/OR */
if
(((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
)
if
(((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
)
{
{
Item
*
item
;
Item
*
item
;
while
((
item
=
li
++
))
while
((
item
=
li
++
))
build_eq_mods_for_cond
(
fda
,
fdeps
,
and_level
,
item
);
build_eq_mods_for_cond
(
fda
,
eq_mod
,
and_level
,
item
);
for
(;
org_key_fields
!=
*
fdeps
;
org_key_fields
++
)
for
(;
org_key_fields
!=
*
eq_mod
;
org_key_fields
++
)
org_key_fields
->
level
=
*
and_level
;
org_key_fields
->
level
=
*
and_level
;
}
}
else
else
{
{
Item
*
item
;
Item
*
item
;
(
*
and_level
)
++
;
(
*
and_level
)
++
;
build_eq_mods_for_cond
(
fda
,
fdeps
,
and_level
,
li
++
);
build_eq_mods_for_cond
(
fda
,
eq_mod
,
and_level
,
li
++
);
while
((
item
=
li
++
))
while
((
item
=
li
++
))
{
{
Equality_module
*
start_key_fields
=
*
fdeps
;
Equality_module
*
start_key_fields
=
*
eq_mod
;
(
*
and_level
)
++
;
(
*
and_level
)
++
;
build_eq_mods_for_cond
(
fda
,
fdeps
,
and_level
,
item
);
build_eq_mods_for_cond
(
fda
,
eq_mod
,
and_level
,
item
);
*
fdeps
=
merge_func_deps
(
org_key_fields
,
start_key_fields
,
*
fdeps
,
*
eq_mod
=
merge_func_deps
(
org_key_fields
,
start_key_fields
,
*
eq_mod
,
++
(
*
and_level
));
++
(
*
and_level
));
}
}
}
}
...
@@ -414,8 +420,8 @@ void build_eq_mods_for_cond(Func_dep_analyzer *fda, Equality_module **fdeps,
...
@@ -414,8 +420,8 @@ void build_eq_mods_for_cond(Func_dep_analyzer *fda, Equality_module **fdeps,
{
{
if
(
cond_func
->
argument_count
()
==
2
)
if
(
cond_func
->
argument_count
()
==
2
)
{
{
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
1
],
args
[
0
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
1
],
args
[
0
]);
}
}
break
;
break
;
}
}
...
@@ -426,62 +432,72 @@ void build_eq_mods_for_cond(Func_dep_analyzer *fda, Equality_module **fdeps,
...
@@ -426,62 +432,72 @@ void build_eq_mods_for_cond(Func_dep_analyzer *fda, Equality_module **fdeps,
(
fld
=
args
[
0
]
->
real_item
())
->
type
()
==
Item
::
FIELD_ITEM
&&
(
fld
=
args
[
0
]
->
real_item
())
->
type
()
==
Item
::
FIELD_ITEM
&&
args
[
1
]
->
eq
(
args
[
2
],
((
Item_field
*
)
fld
)
->
field
->
binary
()))
args
[
1
]
->
eq
(
args
[
2
],
((
Item_field
*
)
fld
)
->
field
->
binary
()))
{
{
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
1
],
args
[
0
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
1
],
args
[
0
]);
}
}
break
;
break
;
}
}
case
Item_func
:
:
EQ_FUNC
:
case
Item_func
:
:
EQ_FUNC
:
case
Item_func
:
:
EQUAL_FUNC
:
case
Item_func
:
:
EQUAL_FUNC
:
{
{
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
1
],
args
[
0
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
1
],
args
[
0
]);
break
;
break
;
}
}
case
Item_func
:
:
ISNULL_FUNC
:
case
Item_func
:
:
ISNULL_FUNC
:
{
{
Item
*
tmp
=
new
Item_null
;
Item
*
tmp
=
new
Item_null
;
if
(
tmp
)
if
(
tmp
)
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
add_eq_mod
(
fda
,
eq_mod
,
*
and_level
,
cond_func
,
args
[
0
],
args
[
1
]);
break
;
break
;
}
}
case
Item_func
:
:
MULT_EQUAL_FUNC
:
case
Item_func
:
:
MULT_EQUAL_FUNC
:
{
{
Item_equal
*
item_equal
=
(
Item_equal
*
)
cond
;
Item_equal
*
item_equal
=
(
Item_equal
*
)
cond
;
Item
*
const_item
=
item_equal
->
get_const
();
// const item is 'item', field -> NULL. mult_equal_fields <-- an ordered
// list of
List
<
Field_value
>
*
fvl
;
if
(
!
(
fvl
=
new
List
<
Field_value
>
))
break
;
Item_equal_iterator
it
(
*
item_equal
);
Item_equal_iterator
it
(
*
item_equal
);
Item_field
*
item
;
Item_field
*
item
;
if
(
const_item
)
Item
*
bound_item
=
item_equal
->
get_const
();
while
((
item
=
it
++
))
{
{
/*
if
((
item
->
used_tables
()
&
fda
->
usable_tables
))
For each field field1 from item_equal consider the equality
field1=const_item as a condition allowing an index access of the table
with field1 by the keys value of field1.
*/
while
((
item
=
it
++
))
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
item
,
const_item
);
}
else
{
/*
Consider all pairs of different fields included into item_equal.
For each of them (field1, field1) consider the equality
field1=field2 as a condition allowing an index access of the table
with field1 by the keys value of field2.
*/
Item_equal_iterator
fi
(
*
item_equal
);
while
((
item
=
fi
++
))
{
{
Field
*
field
=
item
->
field
;
Field_value
*
field_val
;
Item_field
*
item2
;
if
((
field_val
=
get_field_value
(
fda
,
item
->
field
)))
while
((
item2
=
it
++
))
{
{
if
(
!
field
->
eq
(
item2
->
field
))
List_iterator
<
Field_value
>
it2
(
*
fvl
);
add_eq_mod
(
fda
,
fdeps
,
*
and_level
,
cond_func
,
item
,
item2
);
Field_value
*
other_f
;
uint
field_val_ratio
=
field_val
->
field
->
table
->
tablenr
*
MAX_FIELDS
+
field_val
->
field
->
field_index
;
bool
added
=
FALSE
;
while
((
other_f
=
it2
++
))
{
uint
other_f_ratio
=
other_f
->
field
->
table
->
tablenr
*
MAX_FIELDS
+
other_f
->
field
->
field_index
;
if
(
other_f_ratio
>
field_val_ratio
)
{
*
(
it2
.
ref
())
=
field_val
;
it2
.
after
(
other_f
);
added
=
TRUE
;
break
;
}
}
if
(
!
added
)
fvl
->
push_back
(
field_val
);
}
}
it
.
rewind
();
}
else
{
if
(
!
bound_item
)
bound_item
=
item
;
}
}
}
}
add_eq_mod2
(
fda
,
eq_mod
,
*
and_level
,
NULL
,
bound_item
,
fvl
);
break
;
break
;
}
}
default:
default:
...
@@ -490,6 +506,39 @@ void build_eq_mods_for_cond(Func_dep_analyzer *fda, Equality_module **fdeps,
...
@@ -490,6 +506,39 @@ void build_eq_mods_for_cond(Func_dep_analyzer *fda, Equality_module **fdeps,
}
}
/*
The only requirement of this function is to order fields in some
deterministic way.
*/
int
cmp_equal_fields
(
Item_field
*
field1
,
Item_field
*
field2
,
void
*
arg
)
{
int
cmp
=
0
;
bool
outer_ref
=
0
;
if
(
field2
->
used_tables
()
&
OUTER_REF_TABLE_BIT
)
{
outer_ref
=
1
;
cmp
=
-
1
;
}
if
(
field2
->
used_tables
()
&
OUTER_REF_TABLE_BIT
)
{
outer_ref
=
1
;
cmp
++
;
}
if
(
outer_ref
)
return
cmp
;
cmp
=
(
int
)
field2
->
field
->
table
->
tablenr
-
(
int
)
field1
->
field
->
table
->
tablenr
;
if
(
cmp
)
return
cmp
<
0
?
-
1
:
1
;
cmp
=
(
int
)
field2
->
field
->
field_index
-
(
int
)
field1
->
field
->
field_index
;
return
cmp
<
0
?
-
1
:
(
cmp
?
1
:
0
);
}
/*
/*
Perform an OR operation on two (adjacent) Equality_module arrays.
Perform an OR operation on two (adjacent) Equality_module arrays.
...
@@ -540,9 +589,9 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
...
@@ -540,9 +589,9 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
Equality_module
*
end
,
uint
and_level
)
Equality_module
*
end
,
uint
and_level
)
{
{
if
(
start
==
new_fields
)
if
(
start
==
new_fields
)
return
start
;
// Impossible or
return
start
;
// Impossible or
if
(
new_fields
==
end
)
if
(
new_fields
==
end
)
return
start
;
// No new fields, skip all
return
start
;
// No new fields, skip all
Equality_module
*
first_free
=
new_fields
;
Equality_module
*
first_free
=
new_fields
;
...
@@ -551,40 +600,119 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
...
@@ -551,40 +600,119 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
for
(
Equality_module
*
old
=
start
;
old
!=
first_free
;
old
++
)
for
(
Equality_module
*
old
=
start
;
old
!=
first_free
;
old
++
)
{
{
/*
/*
TODO: does it make sense to attempt to merging multiple-equalities?
Merge multiple-equalities:
A: YES.
A: YES.
(a=b=c) OR (a=b=d) produce "a=b".
(a=b=c) OR (a=b=d) produce "a=b".
QQ:
What to use for merging? Trivial N*M algorithm or pre-sort and then
TODO:
merge ordered sequences?
sort by (table_ptr, column_index)
then run along the two and produce an intersection
Q: What about constants?
a=b=3 OR a=b=5 -> a=b= (either 3 or 5)
a=b OR a=b=5 -> a=b= (any constant)
A: keep the constant iff it is present in both sides and is the same.
class Multi_equality
{
Item *const_item;
List<...) list;
};
*/
*/
if
(
old
->
field
==
new_fields
->
field
)
if
(
old
->
field
==
new_fields
->
field
)
{
{
if
(
!
new_fields
->
expression
->
const_item
())
if
(
!
old
->
field
)
{
{
/*
/*
If the value matches, we can use the key reference.
OR-ing two multiple equalities. We must compute an intersection of
If not, we keep it until we have examined all new values
used fields, and check the constants according to these rules:
*/
if
(
old
->
expression
->
eq
(
new_fields
->
expression
,
old
->
field
->
field
->
binary
()))
a=b=c=d OR a=c=e=f -> a=c (compute intersection)
{
a=const1 OR a=b -> (nothing)
old
->
level
=
and_level
;
a=const1 OR a=const1 -> a=const1
}
a=const1 OR a=const2 -> (nothing)
}
else
if
(
old
->
expression
->
eq_by_collation
(
new_fields
->
expression
,
If we're performing an OR operation over multiple equalities, e.g.
old
->
field
->
field
->
binary
(),
old
->
field
->
field
->
charset
()))
(a=b=c AND p=q) OR (a=b AND v=z)
{
old
->
level
=
and_level
;
then we'll need to try combining each equality with each. ANDed
}
equalities are guaranteed to be disjoint, so we'll only get one
else
hit.
{
*/
if
(
old
->
expression
&&
new_fields
->
expression
&&
old
->
expression
->
eq_by_collation
(
new_fields
->
expression
,
old
->
mult_equal_fields
->
head
()
->
field
->
binary
(),
old
->
mult_equal_fields
->
head
()
->
field
->
charset
()))
{
/* Ok, keep */
}
else
{
// no single constant/bound item.
old
->
expression
=
NULL
;
}
List
<
Field_value
>
*
fv
;
if
(
!
(
fv
=
new
List
<
Field_value
>
))
break
;
List_iterator
<
Field_value
>
it1
(
*
old
->
mult_equal_fields
);
List_iterator
<
Field_value
>
it2
(
*
new_fields
->
mult_equal_fields
);
Field_value
*
lfield
=
it1
++
;
Field_value
*
rfield
=
it2
++
;
// Merge
while
(
lfield
&&
rfield
)
{
if
(
lfield
==
rfield
)
fv
->
push_back
(
lfield
);
else
{
uint
left_ratio
=
lfield
->
field
->
table
->
tablenr
*
MAX_FIELDS
+
lfield
->
field
->
field_index
;
uint
right_ratio
=
rfield
->
field
->
table
->
tablenr
*
MAX_FIELDS
+
rfield
->
field
->
field_index
;
if
(
left_ratio
<
right_ratio
)
lfield
=
it1
++
;
else
rfield
=
it2
++
;
}
}
if
(
fv
->
elements
+
test
(
old
->
expression
)
>
1
)
{
old
->
mult_equal_fields
=
fv
;
old
->
level
=
and_level
;
}
}
else
if
(
!
new_fields
->
expression
->
const_item
())
{
/*
If the value matches, we can use the key reference.
If not, we keep it until we have examined all new values
*/
if
(
old
->
expression
->
eq
(
new_fields
->
expression
,
old
->
field
->
field
->
binary
()))
{
old
->
level
=
and_level
;
}
}
else
if
(
old
->
expression
->
eq_by_collation
(
new_fields
->
expression
,
old
->
field
->
field
->
binary
(),
old
->
field
->
field
->
charset
()))
{
old
->
level
=
and_level
;
}
else
{
/* The expressions are different. */
/* The expressions are different. */
if
(
old
==
--
first_free
)
// If last item
if
(
old
==
--
first_free
)
// If last item
break
;
break
;
*
old
=
*
first_free
;
// Remove old value
*
old
=
*
first_free
;
// Remove old value
old
--
;
// Retry this value
old
--
;
// Retry this value
}
}
}
}
}
}
}
}
...
@@ -596,10 +724,10 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
...
@@ -596,10 +724,10 @@ Equality_module *merge_func_deps(Equality_module *start, Equality_module *new_fi
for
(
Equality_module
*
old
=
start
;
old
!=
first_free
;)
for
(
Equality_module
*
old
=
start
;
old
!=
first_free
;)
{
{
if
(
old
->
level
!=
and_level
)
if
(
old
->
level
!=
and_level
)
{
// Not used in all levels
{
// Not used in all levels
if
(
old
==
--
first_free
)
if
(
old
==
--
first_free
)
break
;
break
;
*
old
=
*
first_free
;
// Remove old value
*
old
=
*
first_free
;
// Remove old value
continue
;
continue
;
}
}
old
++
;
old
++
;
...
@@ -659,32 +787,41 @@ void add_eq_mod(Func_dep_analyzer *fda, Equality_module **eq_mod,
...
@@ -659,32 +787,41 @@ void add_eq_mod(Func_dep_analyzer *fda, Equality_module **eq_mod,
return
;
return
;
}
}
}
}
Field_value
*
field_val
;
if
(
*
eq_mod
==
fda
->
equality_mods
+
fda
->
n_equality_mods_alloced
)
if
((
field_val
=
get_field_value
(
fda
,
field
)))
{
add_eq_mod2
(
fda
,
eq_mod
,
and_level
,
field_val
,
right
,
NULL
);
/*
}
We've filled the entire equality_mods array. Replace it with a bigger
}
one. We do it somewhat inefficiently but it doesn't matter.
*/
Equality_module
*
new_arr
;
if
(
!
(
new_arr
=
new
Equality_module
[
fda
->
n_equality_mods_alloced
*
2
]))
return
;
fda
->
n_equality_mods_alloced
*=
2
;
for
(
int
i
=
0
;
i
<
*
eq_mod
-
fda
->
equality_mods
;
i
++
)
new_arr
[
i
]
=
fda
->
equality_mods
[
i
];
fda
->
equality_mods
=
new_arr
;
*
eq_mod
=
new_arr
+
(
*
eq_mod
-
fda
->
equality_mods
);
}
if
(
!
((
*
eq_mod
)
->
field
=
get_field_value
(
fda
,
field
)))
/* Just add eq_mod w/o any checks */
static
void
add_eq_mod2
(
Func_dep_analyzer
*
fda
,
Equality_module
**
eq_mod
,
uint
and_level
,
Field_value
*
field_val
,
Item
*
right
,
List
<
Field_value
>*
mult_equal_fields
)
{
if
(
*
eq_mod
==
fda
->
equality_mods
+
fda
->
n_equality_mods_alloced
)
{
/*
We've filled the entire equality_mods array. Replace it with a bigger
one. We do it somewhat inefficiently but it doesn't matter.
*/
Equality_module
*
new_arr
;
if
(
!
(
new_arr
=
new
Equality_module
[
fda
->
n_equality_mods_alloced
*
2
]))
return
;
return
;
(
*
eq_mod
)
->
expression
=
right
;
fda
->
n_equality_mods_alloced
*=
2
;
(
*
eq_mod
)
->
level
=
and_level
;
for
(
int
i
=
0
;
i
<
*
eq_mod
-
fda
->
equality_mods
;
i
++
)
(
*
eq_mod
)
++
;
new_arr
[
i
]
=
fda
->
equality_mods
[
i
];
fda
->
equality_mods
=
new_arr
;
*
eq_mod
=
new_arr
+
(
*
eq_mod
-
fda
->
equality_mods
);
}
}
}
(
*
eq_mod
)
->
field
=
field_val
;
(
*
eq_mod
)
->
expression
=
right
;
(
*
eq_mod
)
->
level
=
and_level
;
(
*
eq_mod
)
->
mult_equal_fields
=
mult_equal_fields
;
(
*
eq_mod
)
++
;
}
/*
/*
Get a Table_value object for the given table, creating it if necessary.
Get a Table_value object for the given table, creating it if necessary.
...
@@ -782,11 +919,15 @@ public:
...
@@ -782,11 +919,15 @@ public:
*/
*/
fda
->
equality_mods
[
expr_offset
].
unknown_args
++
;
fda
->
equality_mods
[
expr_offset
].
unknown_args
++
;
}
}
else
saw_other_tbl
=
TRUE
;
}
}
Func_dep_analyzer
*
fda
;
Func_dep_analyzer
*
fda
;
/* Offset of the expression we're processing in the dependency bitmap */
/* Offset of the expression we're processing in the dependency bitmap */
uint
expr_offset
;
uint
expr_offset
;
bool
saw_other_tbl
;
};
};
...
@@ -858,9 +999,21 @@ bool setup_equality_modules_deps(Func_dep_analyzer *fda,
...
@@ -858,9 +999,21 @@ bool setup_equality_modules_deps(Func_dep_analyzer *fda,
eq_mod
++
)
eq_mod
++
)
{
{
deps_recorder
.
expr_offset
=
eq_mod
-
fda
->
equality_mods
;
deps_recorder
.
expr_offset
=
eq_mod
-
fda
->
equality_mods
;
deps_recorder
.
saw_other_tbl
=
FALSE
;
eq_mod
->
unknown_args
=
0
;
eq_mod
->
unknown_args
=
0
;
/* Regular tbl.col=expr(tblX1.col1, tblY1.col2, ...) */
eq_mod
->
expression
->
walk
(
&
Item
::
check_column_usage_processor
,
FALSE
,
eq_mod
->
expression
->
walk
(
&
Item
::
check_column_usage_processor
,
FALSE
,
(
uchar
*
)
&
deps_recorder
);
(
uchar
*
)
&
deps_recorder
);
if
(
!
eq_mod
->
field
)
{
if
(
eq_mod
->
unknown_args
)
eq_mod
->
unknown_args
=
1
;
if
(
deps_recorder
.
saw_other_tbl
)
eq_mod
->
unknown_args
=
0
;
}
if
(
!
eq_mod
->
unknown_args
)
if
(
!
eq_mod
->
unknown_args
)
{
{
eq_mod
->
next
=
bound_dep
;
eq_mod
->
next
=
bound_dep
;
...
@@ -1235,12 +1388,30 @@ bool Equality_module::now_bound(Func_dep_analyzer *fda,
...
@@ -1235,12 +1388,30 @@ bool Equality_module::now_bound(Func_dep_analyzer *fda,
Value_dep
**
bound_values
)
Value_dep
**
bound_values
)
{
{
/* For field=expr and we got to know the expr, so we know the field */
/* For field=expr and we got to know the expr, so we know the field */
if
(
!
field
->
bound
)
if
(
mult_equal_fields
)
{
{
/* Mark as bound and add to the list */
List_iterator
<
Field_value
>
it
(
*
mult_equal_fields
);
field
->
bound
=
TRUE
;
Field_value
*
fv
;
field
->
next
=
*
bound_values
;
while
((
fv
=
it
++
))
*
bound_values
=
field
;
{
if
(
!
fv
->
bound
)
{
/* Mark as bound and add to the list */
fv
->
bound
=
TRUE
;
fv
->
next
=
*
bound_values
;
*
bound_values
=
fv
;
}
}
}
else
{
if
(
!
field
->
bound
)
{
/* Mark as bound and add to the list */
field
->
bound
=
TRUE
;
field
->
next
=
*
bound_values
;
*
bound_values
=
field
;
}
}
}
return
FALSE
;
return
FALSE
;
}
}
...
@@ -1313,11 +1484,19 @@ void dbug_print_deps(Func_dep_analyzer *fda)
...
@@ -1313,11 +1484,19 @@ void dbug_print_deps(Func_dep_analyzer *fda)
String
str
(
buf
,
sizeof
(
buf
),
&
my_charset_bin
);
String
str
(
buf
,
sizeof
(
buf
),
&
my_charset_bin
);
str
.
length
(
0
);
str
.
length
(
0
);
eq_mod
->
expression
->
print
(
&
str
,
QT_ORDINARY
);
eq_mod
->
expression
->
print
(
&
str
,
QT_ORDINARY
);
fprintf
(
DBUG_FILE
,
" equality%d: %s -> %s.%s
\n
"
,
if
(
eq_mod
->
field
)
eq_mod
-
fda
->
equality_mods
,
{
str
.
c_ptr
(),
fprintf
(
DBUG_FILE
,
" equality%d: %s -> %s.%s
\n
"
,
eq_mod
->
field
->
table
->
table
->
alias
,
eq_mod
-
fda
->
equality_mods
,
eq_mod
->
field
->
field
->
field_name
);
str
.
c_ptr
(),
eq_mod
->
field
->
table
->
table
->
alias
,
eq_mod
->
field
->
field
->
field_name
);
}
else
{
fprintf
(
DBUG_FILE
,
" equality%d: multi-equality"
,
eq_mod
-
fda
->
equality_mods
);
}
}
}
fprintf
(
DBUG_FILE
,
"
\n
"
);
fprintf
(
DBUG_FILE
,
"
\n
"
);
...
...
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