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
bb15b9e2
Commit
bb15b9e2
authored
May 19, 2015
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-7950 Item_func::type() takes 0.26% in OLTP RO
parent
bac6bbab
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
309 additions
and
217 deletions
+309
-217
sql/item.h
sql/item.h
+10
-0
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+47
-0
sql/item_geofunc.h
sql/item_geofunc.h
+7
-3
sql/sql_select.cc
sql/sql_select.cc
+245
-214
No files found.
sql/item.h
View file @
bb15b9e2
...
...
@@ -59,6 +59,9 @@ struct TABLE_LIST;
void
item_init
(
void
);
/* Init item functions */
class
Item_field
;
class
user_var_entry
;
class
JOIN
;
struct
KEY_FIELD
;
struct
SARGABLE_PARAM
;
static
inline
uint32
...
...
@@ -1137,6 +1140,13 @@ public:
}
virtual
COND
*
remove_eq_conds
(
THD
*
thd
,
Item
::
cond_result
*
cond_value
,
bool
top_level
);
virtual
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
return
;
}
/*
Checks whether the item is:
- a simple equality (field=field_item or field=constant_item), or
...
...
sql/item_cmpfunc.h
View file @
bb15b9e2
...
...
@@ -122,6 +122,10 @@ public:
class
Item_bool_func
:
public
Item_int_func
{
protected:
void
add_key_fields_optimize_op
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
,
bool
equal_func
);
public:
Item_bool_func
()
:
Item_int_func
()
{}
Item_bool_func
(
Item
*
a
)
:
Item_int_func
(
a
)
{}
...
...
@@ -434,6 +438,13 @@ public:
return
min_max_arg_item
->
field
->
can_optimize_group_min_max
(
this
,
const_item
);
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
return
add_key_fields_optimize_op
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
,
false
);
}
};
/**
...
...
@@ -512,6 +523,9 @@ public:
const
char
*
func_name
()
const
{
return
"trigcond"
;
};
bool
const_item
()
const
{
return
FALSE
;
}
bool
*
get_trig_var
()
{
return
trig_var
;
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
};
class
Item_func_not_all
:
public
Item_func_not
...
...
@@ -567,6 +581,13 @@ public:
COND
*
build_equal_items
(
THD
*
thd
,
COND_EQUAL
*
inherited
,
bool
link_item_fields
,
COND_EQUAL
**
cond_equal_ref
);
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
return
add_key_fields_optimize_op
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
,
true
);
}
bool
check_equality
(
THD
*
thd
,
COND_EQUAL
*
cond
,
List
<
Item
>
*
eq_list
);
/*
- If this equality is created from the subquery's IN-equality:
...
...
@@ -591,6 +612,13 @@ public:
cond_result
eq_cmp_result
()
const
{
return
COND_TRUE
;
}
const
char
*
func_name
()
const
{
return
"<=>"
;
}
Item
*
neg_transformer
(
THD
*
thd
)
{
return
0
;
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
return
add_key_fields_optimize_op
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
,
true
);
}
};
...
...
@@ -656,6 +684,8 @@ public:
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_KEY
;
}
const
char
*
func_name
()
const
{
return
"<>"
;
}
Item
*
negated_item
();
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
};
...
...
@@ -712,6 +742,9 @@ public:
bool
eval_not_null_tables
(
uchar
*
opt_arg
);
void
fix_after_pullout
(
st_select_lex
*
new_parent
,
Item
**
ref
);
bool
count_sargable_conds
(
uchar
*
arg
);
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
};
...
...
@@ -1392,6 +1425,8 @@ public:
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_KEY
;
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
virtual
void
print
(
String
*
str
,
enum_query_type
query_type
);
enum
Functype
functype
()
const
{
return
IN_FUNC
;
}
const
char
*
func_name
()
const
{
return
" IN "
;
}
...
...
@@ -1436,6 +1471,8 @@ class Item_func_null_predicate :public Item_bool_func
public:
Item_func_null_predicate
(
Item
*
a
)
:
Item_bool_func
(
a
)
{
sargable
=
true
;
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_NULL
;
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
CHARSET_INFO
*
compare_collation
()
const
{
return
args
[
0
]
->
collation
.
collation
;
}
void
fix_length_and_dec
()
{
decimals
=
0
;
max_length
=
1
;
maybe_null
=
0
;
}
...
...
@@ -1587,6 +1624,8 @@ public:
*/
return
compare_collation
()
==
&
my_charset_bin
?
COND_TRUE
:
COND_OK
;
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
const
char
*
func_name
()
const
{
return
"like"
;
}
bool
fix_fields
(
THD
*
thd
,
Item
**
ref
);
void
cleanup
();
...
...
@@ -1781,6 +1820,9 @@ public:
COND_EQUAL
**
cond_equal_ref
);
COND
*
remove_eq_conds
(
THD
*
thd
,
Item
::
cond_result
*
cond_value
,
bool
top_level
);
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
virtual
void
print
(
String
*
str
,
enum_query_type
query_type
);
void
split_sum_func
(
THD
*
thd
,
Item
**
ref_pointer_array
,
List
<
Item
>
&
fields
);
friend
int
setup_conds
(
THD
*
thd
,
TABLE_LIST
*
tables
,
TABLE_LIST
*
leaves
,
...
...
@@ -1971,6 +2013,9 @@ public:
COND
*
build_equal_items
(
THD
*
thd
,
COND_EQUAL
*
inherited
,
bool
link_item_fields
,
COND_EQUAL
**
cond_equal_ref
);
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
bool
walk
(
Item_processor
processor
,
bool
walk_subquery
,
uchar
*
arg
);
Item
*
transform
(
Item_transformer
transformer
,
uchar
*
arg
);
virtual
void
print
(
String
*
str
,
enum_query_type
query_type
);
...
...
@@ -2125,6 +2170,8 @@ public:
COND
*
build_equal_items
(
THD
*
thd
,
COND_EQUAL
*
inherited
,
bool
link_item_fields
,
COND_EQUAL
**
cond_equal_ref
);
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
);
};
inline
bool
is_cond_and
(
Item
*
item
)
...
...
sql/item_geofunc.h
View file @
bb15b9e2
...
...
@@ -288,6 +288,13 @@ public:
enum
Functype
rev_functype
()
const
{
return
spatial_rel
;
}
bool
is_null
()
{
(
void
)
val_int
();
return
null_value
;
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_OP
;
}
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
return
add_key_fields_optimize_op
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
,
false
);
}
};
...
...
@@ -404,7 +411,6 @@ class Item_func_isempty: public Item_bool_func
public:
Item_func_isempty
(
Item
*
a
)
:
Item_bool_func
(
a
)
{}
longlong
val_int
();
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_NONE
;
}
const
char
*
func_name
()
const
{
return
"st_isempty"
;
}
void
fix_length_and_dec
()
{
maybe_null
=
1
;
}
};
...
...
@@ -418,7 +424,6 @@ class Item_func_issimple: public Item_bool_func
public:
Item_func_issimple
(
Item
*
a
)
:
Item_bool_func
(
a
)
{}
longlong
val_int
();
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_NONE
;
}
const
char
*
func_name
()
const
{
return
"st_issimple"
;
}
void
fix_length_and_dec
()
{
maybe_null
=
1
;
}
};
...
...
@@ -428,7 +433,6 @@ class Item_func_isclosed: public Item_bool_func
public:
Item_func_isclosed
(
Item
*
a
)
:
Item_bool_func
(
a
)
{}
longlong
val_int
();
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_NONE
;
}
const
char
*
func_name
()
const
{
return
"st_isclosed"
;
}
void
fix_length_and_dec
()
{
maybe_null
=
1
;
}
};
...
...
sql/sql_select.cc
View file @
bb15b9e2
...
...
@@ -75,7 +75,7 @@ static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
JOIN_TAB
*
join_tab
,
uint
tables
,
COND
*
conds
,
table_map
table_map
,
SELECT_LEX
*
select_lex
,
st_sargable_param
**
sargables
);
SARGABLE_PARAM
**
sargables
);
static
bool
sort_and_filter_keyuse
(
THD
*
thd
,
DYNAMIC_ARRAY
*
keyuse
,
bool
skip_unprefixed_keyparts
);
static
int
sort_keyuse
(
KEYUSE
*
a
,
KEYUSE
*
b
);
...
...
@@ -3381,12 +3381,12 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
We form a bitmap of indexes that can be used for sargable predicates.
Only such indexes are involved in range analysis.
*/
typedef
struct
st_sargable_param
struct
SARGABLE_PARAM
{
Field
*
field
;
/* field against which to check sargability */
Item
**
arg_value
;
/* values of potential keys for lookups */
uint
num_values
;
/* number of values in the above array */
}
SARGABLE_PARAM
;
}
;
/**
...
...
@@ -4127,7 +4127,7 @@ error:
*****************************************************************************/
/// Used when finding key fields
typedef
struct
key_field_t
{
struct
KEY_FIELD
{
Field
*
field
;
Item_func
*
cond
;
Item
*
val
;
///< May be empty if diff constant
...
...
@@ -4141,7 +4141,8 @@ typedef struct key_field_t {
bool
null_rejecting
;
bool
*
cond_guard
;
/* See KEYUSE::cond_guard */
uint
sj_pred_no
;
/* See KEYUSE::sj_pred_no */
}
KEY_FIELD
;
};
/**
Merge new key definitions to old ones, remove those not used in both.
...
...
@@ -4602,240 +4603,269 @@ is_local_field (Item *field)
operation
*/
static
void
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
COND
*
cond
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
void
Item_cond_and
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
if
(
cond
->
type
()
==
Item_func
::
COND_ITEM
)
{
List_iterator_fast
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
KEY_FIELD
*
org_key_fields
=
*
key_fields
;
List_iterator_fast
<
Item
>
li
(
*
argument_list
());
KEY_FIELD
*
org_key_fields
=
*
key_fields
;
if
(((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
)
{
Item
*
item
;
while
((
item
=
li
++
))
add_key_fields
(
join
,
key_fields
,
and_level
,
item
,
usable_tables
,
sargables
);
for
(;
org_key_fields
!=
*
key_fields
;
org_key_fields
++
)
org_key_fields
->
level
=
*
and_level
;
}
else
{
(
*
and_level
)
++
;
add_key_fields
(
join
,
key_fields
,
and_level
,
li
++
,
usable_tables
,
sargables
);
Item
*
item
;
while
((
item
=
li
++
))
{
KEY_FIELD
*
start_key_fields
=
*
key_fields
;
(
*
and_level
)
++
;
add_key_fields
(
join
,
key_fields
,
and_level
,
item
,
usable_tables
,
sargables
);
*
key_fields
=
merge_key_fields
(
org_key_fields
,
start_key_fields
,
*
key_fields
,
++
(
*
and_level
));
}
}
return
;
Item
*
item
;
while
((
item
=
li
++
))
item
->
add_key_fields
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
);
for
(;
org_key_fields
!=
*
key_fields
;
org_key_fields
++
)
org_key_fields
->
level
=
*
and_level
;
}
void
Item_cond
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
List_iterator_fast
<
Item
>
li
(
*
argument_list
());
KEY_FIELD
*
org_key_fields
=
*
key_fields
;
(
*
and_level
)
++
;
(
li
++
)
->
add_key_fields
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
);
Item
*
item
;
while
((
item
=
li
++
))
{
KEY_FIELD
*
start_key_fields
=
*
key_fields
;
(
*
and_level
)
++
;
item
->
add_key_fields
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
);
*
key_fields
=
merge_key_fields
(
org_key_fields
,
start_key_fields
,
*
key_fields
,
++
(
*
and_level
));
}
}
void
Item_func_trig_cond
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
/*
Subquery optimization: Conditions that are pushed down into subqueries
are wrapped into Item_func_trig_cond. We process the wrapped condition
but need to set cond_guard for KEYUSE elements generated from it.
*/
if
(
!
join
->
group_list
&&
!
join
->
order
&&
join
->
unit
->
item
&&
join
->
unit
->
item
->
substype
()
==
Item_subselect
::
IN_SUBS
&&
!
join
->
unit
->
is_union
())
{
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
TRIG_COND_FUNC
)
KEY_FIELD
*
save
=
*
key_fields
;
args
[
0
]
->
add_key_fields
(
join
,
key_fields
,
and_level
,
usable_tables
,
sargables
);
// Indicate that this ref access candidate is for subquery lookup:
for
(;
save
!=
*
key_fields
;
save
++
)
save
->
cond_guard
=
get_trig_var
();
}
}
void
Item_func_between
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
/*
Build list of possible keys for 'a BETWEEN low AND high'.
It is handled similar to the equivalent condition
'a >= low AND a <= high':
*/
Item_field
*
field_item
;
bool
equal_func
=
false
;
uint
num_values
=
2
;
bool
binary_cmp
=
(
args
[
0
]
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
)
?
((
Item_field
*
)
args
[
0
]
->
real_item
())
->
field
->
binary
()
:
true
;
/*
Additional optimization: If 'low = high':
Handle as if the condition was "t.key = low".
*/
if
(
!
negated
&&
args
[
1
]
->
eq
(
args
[
2
],
binary_cmp
))
{
equal_func
=
true
;
num_values
=
1
;
}
/*
Append keys for 'field <cmp> value[]' if the
condition is of the form::
'<field> BETWEEN value[1] AND value[2]'
*/
if
(
is_local_field
(
args
[
0
]))
{
field_item
=
(
Item_field
*
)
(
args
[
0
]
->
real_item
());
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
field_item
,
equal_func
,
&
args
[
1
],
num_values
,
usable_tables
,
sargables
);
}
/*
Append keys for 'value[0] <cmp> field' if the
condition is of the form:
'value[0] BETWEEN field1 AND field2'
*/
for
(
uint
i
=
1
;
i
<=
num_values
;
i
++
)
{
if
(
is_local_field
(
args
[
i
]))
{
Item
*
cond_arg
=
((
Item_func
*
)
cond
)
->
arguments
()[
0
];
if
(
!
join
->
group_list
&&
!
join
->
order
&&
join
->
unit
->
item
&&
join
->
unit
->
item
->
substype
()
==
Item_subselect
::
IN_SUBS
&&
!
join
->
unit
->
is_union
())
{
KEY_FIELD
*
save
=
*
key_fields
;
add_key_fields
(
join
,
key_fields
,
and_level
,
cond_arg
,
usable_tables
,
sargables
);
// Indicate that this ref access candidate is for subquery lookup:
for
(;
save
!=
*
key_fields
;
save
++
)
save
->
cond_guard
=
((
Item_func_trig_cond
*
)
cond
)
->
get_trig_var
();
}
return
;
field_item
=
(
Item_field
*
)
(
args
[
i
]
->
real_item
());
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
field_item
,
equal_func
,
args
,
1
,
usable_tables
,
sargables
);
}
}
}
/* If item is of type 'field op field/constant' add it to key_fields */
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
return
;
Item_func
*
cond_func
=
(
Item_func
*
)
cond
;
switch
(
cond_func
->
select_optimize
())
{
case
Item_func
:
:
OPTIMIZE_NONE
:
break
;
case
Item_func
:
:
OPTIMIZE_KEY
:
void
Item_func_in
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
if
(
is_local_field
(
args
[
0
])
&&
!
(
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
DBUG_ASSERT
(
arg_count
!=
2
);
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
(
Item_field
*
)
(
args
[
0
]
->
real_item
()),
false
,
args
+
1
,
arg_count
-
1
,
usable_tables
,
sargables
);
}
}
void
Item_func_ne
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
if
(
is_local_field
(
args
[
0
])
&&
!
(
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
Item
**
values
=
is_local_field
(
args
[
1
])
?
args
:
args
+
1
;
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
(
Item_field
*
)
(
args
[
0
]
->
real_item
()),
false
,
values
,
1
,
usable_tables
,
sargables
);
}
}
void
Item_func_like
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
if
(
is_local_field
(
args
[
0
])
&&
Item_func_like
::
select_optimize
()
==
OPTIMIZE_OP
)
{
Item
**
values
;
/*
Build list of possible keys for 'a BETWEEN low AND high'.
It is handled similar to the equivalent condition
'a >= low AND a <= high':
SELECT * FROM t1 WHERE field LIKE const_pattern
const_pattern starts with a non-wildcard character
*/
if
(
cond_func
->
functype
()
==
Item_func
::
BETWEEN
)
{
Item_field
*
field_item
;
bool
equal_func
=
FALSE
;
uint
num_values
=
2
;
values
=
cond_func
->
arguments
();
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
(
Item_field
*
)
args
[
0
]
->
real_item
(),
false
,
args
+
1
,
1
,
usable_tables
,
sargables
);
}
}
bool
binary_cmp
=
(
values
[
0
]
->
real_item
()
->
type
()
==
Item
::
FIELD_ITEM
)
?
((
Item_field
*
)
values
[
0
]
->
real_item
())
->
field
->
binary
()
:
TRUE
;
/*
Additional optimization: If 'low = high':
Handle as if the condition was "t.key = low".
*/
if
(
!
((
Item_func_between
*
)
cond_func
)
->
negated
&&
values
[
1
]
->
eq
(
values
[
2
],
binary_cmp
))
{
equal_func
=
TRUE
;
num_values
=
1
;
}
void
Item_bool_func
::
add_key_fields_optimize_op
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
,
bool
equal_func
)
{
/* If item is of type 'field op field/constant' add it to key_fields */
if
(
is_local_field
(
args
[
0
]))
{
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
(
Item_field
*
)
args
[
0
]
->
real_item
(),
equal_func
,
args
+
1
,
1
,
usable_tables
,
sargables
);
}
if
(
is_local_field
(
args
[
1
]))
{
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
(
Item_field
*
)
args
[
1
]
->
real_item
(),
equal_func
,
args
,
1
,
usable_tables
,
sargables
);
}
}
/*
Append keys for 'field <cmp> value[]' if the
condition is of the form::
'<field> BETWEEN value[1] AND value[2]'
*/
if
(
is_local_field
(
values
[
0
]))
{
field_item
=
(
Item_field
*
)
(
values
[
0
]
->
real_item
());
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
cond_func
,
field_item
,
equal_func
,
&
values
[
1
],
num_values
,
usable_tables
,
sargables
);
}
/*
Append keys for 'value[0] <cmp> field' if the
condition is of the form:
'value[0] BETWEEN field1 AND field2'
*/
for
(
uint
i
=
1
;
i
<=
num_values
;
i
++
)
{
if
(
is_local_field
(
values
[
i
]))
{
field_item
=
(
Item_field
*
)
(
values
[
i
]
->
real_item
());
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
cond_func
,
field_item
,
equal_func
,
values
,
1
,
usable_tables
,
sargables
);
}
}
}
// if ( ... Item_func::BETWEEN)
// IN, NE
else
if
(
is_local_field
(
cond_func
->
key_item
())
&&
!
(
cond_func
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
values
=
cond_func
->
arguments
()
+
1
;
if
(
cond_func
->
functype
()
==
Item_func
::
NE_FUNC
&&
is_local_field
(
cond_func
->
arguments
()[
1
]))
values
--
;
DBUG_ASSERT
(
cond_func
->
functype
()
!=
Item_func
::
IN_FUNC
||
cond_func
->
argument_count
()
!=
2
);
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
cond_func
,
(
Item_field
*
)
(
cond_func
->
key_item
()
->
real_item
()),
0
,
values
,
cond_func
->
argument_count
()
-
1
,
usable_tables
,
sargables
);
}
break
;
}
case
Item_func
:
:
OPTIMIZE_OP
:
void
Item_func_null_predicate
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
/* column_name IS [NOT] NULL */
if
(
is_local_field
(
args
[
0
])
&&
!
(
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
bool
equal_func
=
(
cond_func
->
functype
()
==
Item_func
::
EQ_FUNC
||
cond_func
->
functype
()
==
Item_func
::
EQUAL_FUNC
);
Item
*
tmp
=
new
Item_null
;
if
(
unlikely
(
!
tmp
))
// Should never be true
return
;
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
this
,
(
Item_field
*
)
args
[
0
]
->
real_item
(),
functype
()
==
Item_func
::
ISNULL_FUNC
,
&
tmp
,
1
,
usable_tables
,
sargables
);
}
}
if
(
is_local_field
(
cond_func
->
arguments
()[
0
]))
{
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
cond_func
,
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
(),
equal_func
,
cond_func
->
arguments
()
+
1
,
1
,
usable_tables
,
sargables
);
}
if
(
is_local_field
(
cond_func
->
arguments
()[
1
])
&&
cond_func
->
functype
()
!=
Item_func
::
LIKE_FUNC
)
void
Item_equal
::
add_key_fields
(
JOIN
*
join
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
table_map
usable_tables
,
SARGABLE_PARAM
**
sargables
)
{
Item
*
const_item
=
get_const
();
Item_equal_fields_iterator
it
(
*
this
);
if
(
const_item
)
{
/*
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
(
it
++
)
{
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
cond_func
,
(
Item_field
*
)
(
cond_func
->
arguments
()[
1
])
->
real_item
(),
equal_func
,
cond_func
->
arguments
(),
1
,
usable_tables
,
sargables
);
Field
*
equal_field
=
it
.
get_curr_field
();
add_key_field
(
join
,
key_fields
,
*
and_level
,
this
,
equal_field
,
TRUE
,
&
const_item
,
1
,
usable_tables
,
sargables
);
}
break
;
}
case
Item_func
:
:
OPTIMIZE_NULL
:
/* column_name IS [NOT] NULL */
if
(
is_local_field
(
cond_func
->
arguments
()[
0
])
&&
!
(
cond_func
->
used_tables
()
&
OUTER_REF_TABLE_BIT
))
{
Item
*
tmp
=
new
Item_null
;
if
(
unlikely
(
!
tmp
))
// Should never be true
return
;
add_key_equal_fields
(
join
,
key_fields
,
*
and_level
,
cond_func
,
(
Item_field
*
)
(
cond_func
->
arguments
()[
0
])
->
real_item
(),
cond_func
->
functype
()
==
Item_func
::
ISNULL_FUNC
,
&
tmp
,
1
,
usable_tables
,
sargables
);
}
break
;
case
Item_func
:
:
OPTIMIZE_EQUAL
:
Item_equal
*
item_equal
=
(
Item_equal
*
)
cond
;
Item
*
const_item
=
item_equal
->
get_const
();
Item_equal_fields_iterator
it
(
*
item_equal
);
if
(
const_item
)
{
/*
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
(
it
++
)
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_fields_iterator
fi
(
*
this
);
while
(
fi
++
)
{
Field
*
field
=
fi
.
get_curr_field
();
Item
*
item
;
while
((
item
=
it
++
))
{
Field
*
equal_field
=
it
.
get_curr_field
();
add_key_field
(
join
,
key_fields
,
*
and_level
,
cond_func
,
equal_field
,
TRUE
,
&
const_item
,
1
,
usable_tables
,
sargables
);
}
}
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_fields_iterator
fi
(
*
item_equal
);
while
(
fi
++
)
{
Field
*
field
=
fi
.
get_curr_field
();
Item
*
item
;
while
((
item
=
it
++
))
if
(
!
field
->
eq
(
equal_field
))
{
Field
*
equal_field
=
it
.
get_curr_field
();
if
(
!
field
->
eq
(
equal_field
))
{
add_key_field
(
join
,
key_fields
,
*
and_level
,
cond_func
,
field
,
TRUE
,
&
item
,
1
,
usable_tables
,
sargables
);
}
add_key_field
(
join
,
key_fields
,
*
and_level
,
this
,
field
,
TRUE
,
&
item
,
1
,
usable_tables
,
sargables
);
}
it
.
rewind
();
}
it
.
rewind
();
}
break
;
}
}
...
...
@@ -5120,8 +5150,8 @@ static void add_key_fields_for_nj(JOIN *join, TABLE_LIST *nested_join_table,
tables
|=
table
->
table
->
map
;
}
if
(
nested_join_table
->
on_expr
)
add_key_fields
(
join
,
end
,
and_level
,
nested_join_table
->
on_expr
,
tables
,
sargables
);
nested_join_table
->
on_expr
->
add_key_fields
(
join
,
end
,
and_level
,
tables
,
sargables
);
}
...
...
@@ -5244,8 +5274,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
if
(
cond
)
{
KEY_FIELD
*
saved_field
=
field
;
add_key_fields
(
join_tab
->
join
,
&
end
,
&
and_level
,
cond
,
normal_tables
,
sargables
);
cond
->
add_key_fields
(
join_tab
->
join
,
&
end
,
&
and_level
,
normal_tables
,
sargables
);
for
(;
field
!=
end
;
field
++
)
{
...
...
@@ -5268,9 +5298,10 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
into account as well.
*/
if
(
*
join_tab
[
i
].
on_expr_ref
)
add_key_fields
(
join_tab
->
join
,
&
end
,
&
and_level
,
*
join_tab
[
i
].
on_expr_ref
,
join_tab
[
i
].
table
->
map
,
sargables
);
(
*
join_tab
[
i
].
on_expr_ref
)
->
add_key_fields
(
join_tab
->
join
,
&
end
,
&
and_level
,
join_tab
[
i
].
table
->
map
,
sargables
);
}
/* Process ON conditions for the nested joins */
...
...
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