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
ca6c4cc3
Commit
ca6c4cc3
authored
Nov 13, 2003
by
psergey@psergey.(none)
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added index_merge access method
parent
0466c250
Changes
12
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1247 additions
and
158 deletions
+1247
-158
BitKeeper/etc/logging_ok
BitKeeper/etc/logging_ok
+1
-0
sql/opt_ft.cc
sql/opt_ft.cc
+1
-1
sql/opt_ft.h
sql/opt_ft.h
+6
-5
sql/opt_range.cc
sql/opt_range.cc
+901
-104
sql/opt_range.h
sql/opt_range.h
+174
-17
sql/sql_class.cc
sql/sql_class.cc
+2
-2
sql/sql_list.h
sql/sql_list.h
+7
-0
sql/sql_select.cc
sql/sql_select.cc
+86
-18
sql/sql_select.h
sql/sql_select.h
+3
-2
sql/sql_test.cc
sql/sql_test.cc
+31
-1
sql/sql_union.cc
sql/sql_union.cc
+3
-2
sql/sql_update.cc
sql/sql_update.cc
+32
-6
No files found.
BitKeeper/etc/logging_ok
View file @
ca6c4cc3
...
@@ -95,6 +95,7 @@ peter@linux.local
...
@@ -95,6 +95,7 @@ peter@linux.local
peter@mysql.com
peter@mysql.com
peterg@mysql.com
peterg@mysql.com
pgulutzan@linux.local
pgulutzan@linux.local
psergey@psergey.(none)
ram@gw.udmsearch.izhnet.ru
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
ram@mysql.r18.ru
ram@ram.(none)
ram@ram.(none)
...
...
sql/opt_ft.cc
View file @
ca6c4cc3
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
** Create a FT or QUICK RANGE based on a key
** Create a FT or QUICK RANGE based on a key
****************************************************************************/
****************************************************************************/
QUICK_SELECT
*
get_ft_or_quick_select_for_ref
(
TABLE
*
table
,
JOIN_TAB
*
tab
)
QUICK_
RANGE_
SELECT
*
get_ft_or_quick_select_for_ref
(
TABLE
*
table
,
JOIN_TAB
*
tab
)
{
{
if
(
tab
->
type
==
JT_FT
)
if
(
tab
->
type
==
JT_FT
)
return
new
FT_SELECT
(
table
,
&
tab
->
ref
);
return
new
FT_SELECT
(
table
,
&
tab
->
ref
);
...
...
sql/opt_ft.h
View file @
ca6c4cc3
...
@@ -24,17 +24,18 @@
...
@@ -24,17 +24,18 @@
#pragma interface
/* gcc class implementation */
#pragma interface
/* gcc class implementation */
#endif
#endif
class
FT_SELECT
:
public
QUICK_SELECT
{
class
FT_SELECT
:
public
QUICK_
RANGE_
SELECT
{
public:
public:
TABLE_REF
*
ref
;
TABLE_REF
*
ref
;
FT_SELECT
(
TABLE
*
table
,
TABLE_REF
*
tref
)
:
FT_SELECT
(
TABLE
*
table
,
TABLE_REF
*
tref
)
:
QUICK_SELECT
(
table
,
tref
->
key
,
1
),
ref
(
tref
)
{
init
();
}
QUICK_
RANGE_
SELECT
(
table
,
tref
->
key
,
1
),
ref
(
tref
)
{
init
();
}
int
init
()
{
return
error
=
file
->
ft_init
(
);
}
int
init
()
{
QUICK_RANGE_SELECT
::
init
();
return
(
error
=
file
->
ft_init
()
);
}
int
get_next
()
{
return
error
=
file
->
ft_read
(
record
);
}
int
get_next
()
{
return
error
=
file
->
ft_read
(
record
);
}
int
get_type
()
{
return
QS_TYPE_FULLTEXT
;
}
};
};
QUICK_SELECT
*
get_ft_or_quick_select_for_ref
(
TABLE
*
table
,
JOIN_TAB
*
tab
);
QUICK_
RANGE_
SELECT
*
get_ft_or_quick_select_for_ref
(
TABLE
*
table
,
JOIN_TAB
*
tab
);
#endif
#endif
sql/opt_range.cc
View file @
ca6c4cc3
This diff is collapsed.
Click to expand it.
sql/opt_range.h
View file @
ca6c4cc3
...
@@ -65,41 +65,198 @@ class QUICK_RANGE :public Sql_alloc {
...
@@ -65,41 +65,198 @@ class QUICK_RANGE :public Sql_alloc {
}
}
};
};
class
INDEX_MERGE
;
class
QUICK_SELECT
{
/*
Quick select interface.
This class is parent for all QUICK_*_SELECT and FT_SELECT classes.
*/
class
QUICK_SELECT_I
{
public:
public:
ha_rows
records
;
/* estimate of # of records to be retrieved */
double
read_time
;
/* time to perform this retrieval */
TABLE
*
head
;
/*
the only index this quick select uses, or MAX_KEY for
QUICK_INDEX_MERGE_SELECT
*/
uint
index
;
uint
max_used_key_length
,
used_key_parts
;
QUICK_SELECT_I
();
virtual
~
QUICK_SELECT_I
(){};
virtual
int
init
()
=
0
;
virtual
void
reset
(
void
)
=
0
;
virtual
int
get_next
()
=
0
;
/* get next record to retrieve */
virtual
bool
reverse_sorted
()
=
0
;
virtual
bool
unique_key_range
()
{
return
false
;
}
enum
{
QS_TYPE_RANGE
=
0
,
QS_TYPE_INDEX_MERGE
=
1
,
QS_TYPE_RANGE_DESC
=
2
,
QS_TYPE_FULLTEXT
=
3
};
/* Get type of this quick select - one of the QS_* values */
virtual
int
get_type
()
=
0
;
};
struct
st_qsel_param
;
class
SEL_ARG
;
class
QUICK_RANGE_SELECT
:
public
QUICK_SELECT_I
{
protected:
bool
next
,
dont_free
;
bool
next
,
dont_free
;
public:
int
error
;
int
error
;
uint
index
,
max_used_key_length
,
used_key_parts
;
TABLE
*
head
;
handler
*
file
;
handler
*
file
;
byte
*
record
;
byte
*
record
;
protected:
friend
void
print_quick_sel_range
(
QUICK_RANGE_SELECT
*
quick
,
key_map
needed_reg
);
friend
QUICK_RANGE_SELECT
*
get_quick_select_for_ref
(
TABLE
*
table
,
struct
st_table_ref
*
ref
);
friend
bool
get_quick_keys
(
struct
st_qsel_param
*
param
,
QUICK_RANGE_SELECT
*
quick
,
KEY_PART
*
key
,
SEL_ARG
*
key_tree
,
char
*
min_key
,
uint
min_key_flag
,
char
*
max_key
,
uint
max_key_flag
);
friend
QUICK_RANGE_SELECT
*
get_quick_select
(
struct
st_qsel_param
*
,
uint
idx
,
SEL_ARG
*
key_tree
,
MEM_ROOT
*
alloc
);
friend
class
QUICK_SELECT_DESC
;
List
<
QUICK_RANGE
>
ranges
;
List
<
QUICK_RANGE
>
ranges
;
List_iterator
<
QUICK_RANGE
>
it
;
List_iterator
<
QUICK_RANGE
>
it
;
QUICK_RANGE
*
range
;
QUICK_RANGE
*
range
;
MEM_ROOT
alloc
;
MEM_ROOT
alloc
;
KEY_PART
*
key_parts
;
KEY_PART
*
key_parts
;
ha_rows
records
;
int
cmp_next
(
QUICK_RANGE
*
range
);
double
read_time
;
public:
QUICK_RANGE_SELECT
(
TABLE
*
table
,
uint
index_arg
,
bool
no_alloc
=
0
,
MEM_ROOT
*
parent_alloc
=
NULL
);
~
QUICK_RANGE_SELECT
();
QUICK_SELECT
(
TABLE
*
table
,
uint
index_arg
,
bool
no_alloc
=
0
);
virtual
~
QUICK_SELECT
();
void
reset
(
void
)
{
next
=
0
;
it
.
rewind
();
}
void
reset
(
void
)
{
next
=
0
;
it
.
rewind
();
}
int
init
()
{
return
error
=
file
->
index_init
(
index
);
}
int
init
();
virtual
int
get_next
();
int
get_next
();
virtual
bool
reverse_sorted
()
{
return
0
;
}
bool
reverse_sorted
()
{
return
0
;
}
int
cmp_next
(
QUICK_RANGE
*
range
);
bool
unique_key_range
();
bool
unique_key_range
();
int
get_type
()
{
return
QS_TYPE_RANGE
;
}
};
};
/*
Helper class for keeping track of rows that have been passed to output
in index_merge access method.
NOTES
Current implementation uses a temporary table to store ROWIDs of rows that
have been passed to output. In the future it might be changed to use more
efficient mechanisms, like Unique class.
*/
class
INDEX_MERGE
{
public:
INDEX_MERGE
(
THD
*
thd_arg
);
~
INDEX_MERGE
();
int
init
(
TABLE
*
table
);
int
check_record_in
();
int
start_last_quick_select
();
int
error
;
private:
/* The only field in temporary table */
class
Item_rowid
:
public
Item_str_func
{
TABLE
*
head
;
/* source table */
public:
Item_rowid
(
TABLE
*
table
)
:
head
(
table
)
{
max_length
=
table
->
file
->
ref_length
;
collation
.
set
(
&
my_charset_bin
);
};
const
char
*
func_name
()
const
{
return
"rowid"
;
}
bool
const_item
()
const
{
return
0
;
}
String
*
val_str
(
String
*
);
void
fix_length_and_dec
()
{}
};
/* Check if record has been processed and save it if it wasn't */
inline
int
put_record
();
/* Check if record has been processed without saving it */
inline
int
check_record
();
/* If true, check_record_in does't store ROWIDs it is passed. */
bool
dont_save
;
THD
*
thd
;
TABLE
*
head
;
/* source table */
TABLE
*
temp_table
;
/* temp. table used for values storage */
TMP_TABLE_PARAM
tmp_table_param
;
/* temp. table creation parameters */
Item_rowid
*
rowid_item
;
/* the only field in temp. table */
List
<
Item
>
fields
;
/* temp. table fields list
(the only element is rowid_item) */
ORDER
order
;
/* key for temp. table (rowid_item) */
};
/*
Index merge quick select.
It is implemented as a container for several QUICK_RANGE_SELECTs.
*/
class
QUICK_INDEX_MERGE_SELECT
:
public
QUICK_SELECT_I
{
public:
QUICK_INDEX_MERGE_SELECT
(
THD
*
thd
,
TABLE
*
table
);
~
QUICK_INDEX_MERGE_SELECT
();
int
init
();
void
reset
(
void
);
int
get_next
();
bool
reverse_sorted
()
{
return
false
;
}
bool
unique_key_range
()
{
return
false
;
}
int
get_type
()
{
return
QS_TYPE_INDEX_MERGE
;
}
bool
push_quick_back
(
QUICK_RANGE_SELECT
*
quick_sel_range
);
/* range quick selects this index_merge read consists of */
List
<
QUICK_RANGE_SELECT
>
quick_selects
;
/* quick select which is currently used for rows retrieval */
List_iterator_fast
<
QUICK_RANGE_SELECT
>
cur_quick_it
;
QUICK_RANGE_SELECT
*
cur_quick_select
;
/*
Last element in quick_selects list.
INDEX_MERGE::start_last_quick_select is called before retrieving
rows for it.
*/
QUICK_RANGE_SELECT
*
last_quick_select
;
/*
Used to keep track of what records have been already passed to output
when doing index_merge access (NULL means no index_merge)
*/
INDEX_MERGE
index_merge
;
MEM_ROOT
alloc
;
};
class
QUICK_SELECT_DESC
:
public
QUICK_SELECT
class
QUICK_SELECT_DESC
:
public
QUICK_
RANGE_
SELECT
{
{
public:
public:
QUICK_SELECT_DESC
(
QUICK_SELECT
*
q
,
uint
used_key_parts
);
QUICK_SELECT_DESC
(
QUICK_
RANGE_
SELECT
*
q
,
uint
used_key_parts
);
int
get_next
();
int
get_next
();
bool
reverse_sorted
()
{
return
1
;
}
bool
reverse_sorted
()
{
return
1
;
}
int
get_type
()
{
return
QS_TYPE_RANGE_DESC
;
}
private:
private:
int
cmp_prev
(
QUICK_RANGE
*
range
);
int
cmp_prev
(
QUICK_RANGE
*
range
);
bool
range_reads_after_key
(
QUICK_RANGE
*
range
);
bool
range_reads_after_key
(
QUICK_RANGE
*
range
);
...
@@ -114,7 +271,7 @@ private:
...
@@ -114,7 +271,7 @@ private:
class
SQL_SELECT
:
public
Sql_alloc
{
class
SQL_SELECT
:
public
Sql_alloc
{
public:
public:
QUICK_SELECT
*
quick
;
// If quick-select used
QUICK_SELECT
_I
*
quick
;
// If quick-select used
COND
*
cond
;
// where condition
COND
*
cond
;
// where condition
TABLE
*
head
;
TABLE
*
head
;
IO_CACHE
file
;
// Positions to used records
IO_CACHE
file
;
// Positions to used records
...
@@ -134,6 +291,6 @@ class SQL_SELECT :public Sql_alloc {
...
@@ -134,6 +291,6 @@ class SQL_SELECT :public Sql_alloc {
bool
force_quick_range
=
0
);
bool
force_quick_range
=
0
);
};
};
QUICK_SELECT
*
get_quick_select_for_ref
(
TABLE
*
table
,
struct
st_table_ref
*
ref
);
QUICK_
RANGE_
SELECT
*
get_quick_select_for_ref
(
TABLE
*
table
,
struct
st_table_ref
*
ref
);
#endif
#endif
sql/sql_class.cc
View file @
ca6c4cc3
...
@@ -537,8 +537,8 @@ int THD::send_explain_fields(select_result *result)
...
@@ -537,8 +537,8 @@ int THD::send_explain_fields(select_result *result)
item
->
maybe_null
=
1
;
item
->
maybe_null
=
1
;
field_list
.
push_back
(
item
=
new
Item_empty_string
(
"key"
,
NAME_LEN
));
field_list
.
push_back
(
item
=
new
Item_empty_string
(
"key"
,
NAME_LEN
));
item
->
maybe_null
=
1
;
item
->
maybe_null
=
1
;
field_list
.
push_back
(
item
=
new
Item_
return_int
(
"key_len"
,
3
,
field_list
.
push_back
(
item
=
new
Item_
empty_string
(
"key_len"
,
MYSQL_TYPE_LONGLONG
));
NAME_LEN
*
MAX_KEY
));
item
->
maybe_null
=
1
;
item
->
maybe_null
=
1
;
field_list
.
push_back
(
item
=
new
Item_empty_string
(
"ref"
,
field_list
.
push_back
(
item
=
new
Item_empty_string
(
"ref"
,
NAME_LEN
*
MAX_REF_PARTS
));
NAME_LEN
*
MAX_REF_PARTS
));
...
...
sql/sql_list.h
View file @
ca6c4cc3
...
@@ -135,6 +135,12 @@ public:
...
@@ -135,6 +135,12 @@ public:
last
=
&
first
;
last
=
&
first
;
return
tmp
->
info
;
return
tmp
->
info
;
}
}
inline
void
concat
(
base_list
*
list
)
{
*
last
=
list
->
first
;
last
=
list
->
last
;
elements
+=
list
->
elements
;
}
inline
list_node
*
last_node
()
{
return
*
last
;
}
inline
list_node
*
last_node
()
{
return
*
last
;
}
inline
list_node
*
first_node
()
{
return
first
;}
inline
list_node
*
first_node
()
{
return
first
;}
inline
void
*
head
()
{
return
first
->
info
;
}
inline
void
*
head
()
{
return
first
->
info
;
}
...
@@ -255,6 +261,7 @@ public:
...
@@ -255,6 +261,7 @@ public:
}
}
empty
();
empty
();
}
}
inline
void
concat
(
List
<
T
>
*
list
)
{
base_list
::
concat
(
list
);
}
};
};
...
...
sql/sql_select.cc
View file @
ca6c4cc3
...
@@ -32,7 +32,8 @@
...
@@ -32,7 +32,8 @@
const
char
*
join_type_str
[]
=
{
"UNKNOWN"
,
"system"
,
"const"
,
"eq_ref"
,
"ref"
,
const
char
*
join_type_str
[]
=
{
"UNKNOWN"
,
"system"
,
"const"
,
"eq_ref"
,
"ref"
,
"MAYBE_REF"
,
"ALL"
,
"range"
,
"index"
,
"fulltext"
,
"MAYBE_REF"
,
"ALL"
,
"range"
,
"index"
,
"fulltext"
,
"ref_or_null"
,
"simple_in"
,
"index_in"
"ref_or_null"
,
"simple_in"
,
"index_in"
,
"index_merge"
};
};
static
void
optimize_keyuse
(
JOIN
*
join
,
DYNAMIC_ARRAY
*
keyuse_array
);
static
void
optimize_keyuse
(
JOIN
*
join
,
DYNAMIC_ARRAY
*
keyuse_array
);
...
@@ -114,7 +115,6 @@ static int join_read_next_same_or_null(READ_RECORD *info);
...
@@ -114,7 +115,6 @@ static int join_read_next_same_or_null(READ_RECORD *info);
static
COND
*
make_cond_for_table
(
COND
*
cond
,
table_map
table
,
static
COND
*
make_cond_for_table
(
COND
*
cond
,
table_map
table
,
table_map
used_table
);
table_map
used_table
);
static
Item
*
part_of_refkey
(
TABLE
*
form
,
Field
*
field
);
static
Item
*
part_of_refkey
(
TABLE
*
form
,
Field
*
field
);
static
uint
find_shortest_key
(
TABLE
*
table
,
key_map
usable_keys
);
static
bool
test_if_skip_sort_order
(
JOIN_TAB
*
tab
,
ORDER
*
order
,
static
bool
test_if_skip_sort_order
(
JOIN_TAB
*
tab
,
ORDER
*
order
,
ha_rows
select_limit
,
bool
no_changes
);
ha_rows
select_limit
,
bool
no_changes
);
static
int
create_sort_index
(
THD
*
thd
,
JOIN
*
join
,
ORDER
*
order
,
static
int
create_sort_index
(
THD
*
thd
,
JOIN
*
join
,
ORDER
*
order
,
...
@@ -6473,7 +6473,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
...
@@ -6473,7 +6473,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
return
reverse
;
return
reverse
;
}
}
static
uint
find_shortest_key
(
TABLE
*
table
,
key_map
usable_keys
)
uint
find_shortest_key
(
TABLE
*
table
,
key_map
usable_keys
)
{
{
uint
min_length
=
(
uint
)
~
0
;
uint
min_length
=
(
uint
)
~
0
;
uint
best
=
MAX_KEY
;
uint
best
=
MAX_KEY
;
...
@@ -6601,6 +6601,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -6601,6 +6601,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
}
else
if
(
select
&&
select
->
quick
)
// Range found by opt_range
else
if
(
select
&&
select
->
quick
)
// Range found by opt_range
{
{
/* assume results are not ordered when index merge is used */
if
(
select
->
quick
->
get_type
()
==
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
)
DBUG_RETURN
(
0
);
ref_key
=
select
->
quick
->
index
;
ref_key
=
select
->
quick
->
index
;
ref_key_parts
=
select
->
quick
->
used_key_parts
;
ref_key_parts
=
select
->
quick
->
used_key_parts
;
}
}
...
@@ -6635,6 +6638,10 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -6635,6 +6638,10 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
}
else
else
{
{
/*
We have verified above that select->quick is not
index_merge quick select.
*/
select
->
quick
->
index
=
new_ref_key
;
select
->
quick
->
index
=
new_ref_key
;
select
->
quick
->
init
();
select
->
quick
->
init
();
}
}
...
@@ -6656,10 +6663,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -6656,10 +6663,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
*/
if
(
!
select
->
quick
->
reverse_sorted
())
if
(
!
select
->
quick
->
reverse_sorted
())
{
{
if
(
table
->
file
->
index_flags
(
ref_key
)
&
HA_NOT_READ_PREFIX_LAST
)
if
(
table
->
file
->
index_flags
(
ref_key
)
&
HA_NOT_READ_PREFIX_LAST
||
(
select
->
quick
->
get_type
()
==
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
))
DBUG_RETURN
(
0
);
// Use filesort
DBUG_RETURN
(
0
);
// Use filesort
// ORDER BY range_key DESC
// ORDER BY range_key DESC
QUICK_SELECT_DESC
*
tmp
=
new
QUICK_SELECT_DESC
(
select
->
quick
,
QUICK_SELECT_DESC
*
tmp
=
new
QUICK_SELECT_DESC
(
(
QUICK_RANGE_SELECT
*
)(
select
->
quick
)
,
used_key_parts
);
used_key_parts
);
if
(
!
tmp
||
tmp
->
error
)
if
(
!
tmp
||
tmp
->
error
)
{
{
...
@@ -6794,8 +6804,11 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
...
@@ -6794,8 +6804,11 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
{
{
select
->
quick
=
tab
->
quick
;
select
->
quick
=
tab
->
quick
;
tab
->
quick
=
0
;
tab
->
quick
=
0
;
/* We can only use 'Only index' if quick key is same as ref_key */
/*
if
(
table
->
key_read
&&
(
uint
)
tab
->
ref
.
key
!=
select
->
quick
->
index
)
We can only use 'Only index' if quick key is same as ref_key
and in index_merge 'Only index' cannot be used
*/
if
(
table
->
key_read
&&
((
uint
)
tab
->
ref
.
key
!=
select
->
quick
->
index
))
{
{
table
->
key_read
=
0
;
table
->
key_read
=
0
;
table
->
file
->
extra
(
HA_EXTRA_NO_KEYREAD
);
table
->
file
->
extra
(
HA_EXTRA_NO_KEYREAD
);
...
@@ -8598,12 +8611,15 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
...
@@ -8598,12 +8611,15 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
JOIN_TAB
*
tab
=
join
->
join_tab
+
i
;
JOIN_TAB
*
tab
=
join
->
join_tab
+
i
;
TABLE
*
table
=
tab
->
table
;
TABLE
*
table
=
tab
->
table
;
char
buff
[
512
],
*
buff_ptr
=
buff
;
char
buff
[
512
],
*
buff_ptr
=
buff
;
char
buff1
[
512
],
buff2
[
512
];
char
buff1
[
512
],
buff2
[
512
],
buff3
[
512
];
char
keylen_str_buf
[
64
];
char
derived_name
[
64
];
char
derived_name
[
64
];
String
tmp1
(
buff1
,
sizeof
(
buff1
),
cs
);
String
tmp1
(
buff1
,
sizeof
(
buff1
),
cs
);
String
tmp2
(
buff2
,
sizeof
(
buff2
),
cs
);
String
tmp2
(
buff2
,
sizeof
(
buff2
),
cs
);
String
tmp3
(
buff3
,
sizeof
(
buff3
),
cs
);
tmp1
.
length
(
0
);
tmp1
.
length
(
0
);
tmp2
.
length
(
0
);
tmp2
.
length
(
0
);
tmp3
.
length
(
0
);
item_list
.
empty
();
item_list
.
empty
();
item_list
.
push_back
(
new
Item_int
((
int32
)
item_list
.
push_back
(
new
Item_int
((
int32
)
...
@@ -8612,7 +8628,13 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
...
@@ -8612,7 +8628,13 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
strlen
(
join
->
select_lex
->
type
),
strlen
(
join
->
select_lex
->
type
),
cs
));
cs
));
if
(
tab
->
type
==
JT_ALL
&&
tab
->
select
&&
tab
->
select
->
quick
)
if
(
tab
->
type
==
JT_ALL
&&
tab
->
select
&&
tab
->
select
->
quick
)
tab
->
type
=
JT_RANGE
;
{
if
(
tab
->
select
->
quick
->
get_type
()
==
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
)
tab
->
type
=
JT_INDEX_MERGE
;
else
tab
->
type
=
JT_RANGE
;
}
if
(
table
->
derived_select_number
)
if
(
table
->
derived_select_number
)
{
{
/* Derived table name generation */
/* Derived table name generation */
...
@@ -8646,10 +8668,14 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
...
@@ -8646,10 +8668,14 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if
(
tab
->
ref
.
key_parts
)
if
(
tab
->
ref
.
key_parts
)
{
{
KEY
*
key_info
=
table
->
key_info
+
tab
->
ref
.
key
;
KEY
*
key_info
=
table
->
key_info
+
tab
->
ref
.
key
;
register
uint
length
;
item_list
.
push_back
(
new
Item_string
(
key_info
->
name
,
item_list
.
push_back
(
new
Item_string
(
key_info
->
name
,
strlen
(
key_info
->
name
),
strlen
(
key_info
->
name
),
system_charset_info
));
system_charset_info
));
item_list
.
push_back
(
new
Item_int
((
int32
)
tab
->
ref
.
key_length
));
length
=
longlong2str
(
tab
->
ref
.
key_length
,
keylen_str_buf
,
10
)
-
keylen_str_buf
;
item_list
.
push_back
(
new
Item_string
(
keylen_str_buf
,
length
,
system_charset_info
));
for
(
store_key
**
ref
=
tab
->
ref
.
key_copy
;
*
ref
;
ref
++
)
for
(
store_key
**
ref
=
tab
->
ref
.
key_copy
;
*
ref
;
ref
++
)
{
{
if
(
tmp2
.
length
())
if
(
tmp2
.
length
())
...
@@ -8661,18 +8687,60 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
...
@@ -8661,18 +8687,60 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
else
if
(
tab
->
type
==
JT_NEXT
)
else
if
(
tab
->
type
==
JT_NEXT
)
{
{
KEY
*
key_info
=
table
->
key_info
+
tab
->
index
;
KEY
*
key_info
=
table
->
key_info
+
tab
->
index
;
register
uint
length
;
item_list
.
push_back
(
new
Item_string
(
key_info
->
name
,
item_list
.
push_back
(
new
Item_string
(
key_info
->
name
,
strlen
(
key_info
->
name
),
cs
));
strlen
(
key_info
->
name
),
cs
));
item_list
.
push_back
(
new
Item_int
((
int32
)
key_info
->
key_length
));
length
=
longlong2str
(
key_info
->
key_length
,
keylen_str_buf
,
10
)
-
keylen_str_buf
;
item_list
.
push_back
(
new
Item_string
(
keylen_str_buf
,
length
,
system_charset_info
));
item_list
.
push_back
(
item_null
);
item_list
.
push_back
(
item_null
);
}
}
else
if
(
tab
->
select
&&
tab
->
select
->
quick
)
else
if
(
tab
->
select
&&
tab
->
select
->
quick
)
{
{
KEY
*
key_info
=
table
->
key_info
+
tab
->
select
->
quick
->
index
;
if
(
tab
->
select
->
quick
->
get_type
()
==
item_list
.
push_back
(
new
Item_string
(
key_info
->
name
,
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
)
strlen
(
key_info
->
name
),
cs
));
{
item_list
.
push_back
(
new
Item_int
((
int32
)
tab
->
select
->
quick
->
QUICK_INDEX_MERGE_SELECT
*
quick_imerge
=
max_used_key_length
));
(
QUICK_INDEX_MERGE_SELECT
*
)
tab
->
select
->
quick
;
QUICK_RANGE_SELECT
*
quick
;
List_iterator_fast
<
QUICK_RANGE_SELECT
>
it
(
quick_imerge
->
quick_selects
);
while
((
quick
=
it
++
))
{
KEY
*
key_info
=
table
->
key_info
+
quick
->
index
;
register
uint
length
;
if
(
tmp3
.
length
())
tmp3
.
append
(
','
);
tmp3
.
append
(
key_info
->
name
);
if
(
tmp2
.
length
())
tmp2
.
append
(
','
);
length
=
longlong2str
(
quick
->
max_used_key_length
,
keylen_str_buf
,
10
)
-
keylen_str_buf
;
tmp2
.
append
(
keylen_str_buf
,
length
);
}
}
else
{
KEY
*
key_info
=
table
->
key_info
+
tab
->
select
->
quick
->
index
;
register
uint
length
;
tmp3
.
append
(
key_info
->
name
);
length
=
longlong2str
(
tab
->
select
->
quick
->
max_used_key_length
,
keylen_str_buf
,
10
)
-
keylen_str_buf
;
tmp2
.
append
(
keylen_str_buf
,
length
);
}
item_list
.
push_back
(
new
Item_string
(
tmp3
.
ptr
(),
tmp3
.
length
(),
cs
));
item_list
.
push_back
(
new
Item_string
(
tmp2
.
ptr
(),
tmp2
.
length
(),
cs
));
item_list
.
push_back
(
item_null
);
item_list
.
push_back
(
item_null
);
}
}
else
else
...
...
sql/sql_select.h
View file @
ca6c4cc3
...
@@ -76,7 +76,7 @@ typedef struct st_join_cache {
...
@@ -76,7 +76,7 @@ typedef struct st_join_cache {
enum
join_type
{
JT_UNKNOWN
,
JT_SYSTEM
,
JT_CONST
,
JT_EQ_REF
,
JT_REF
,
JT_MAYBE_REF
,
enum
join_type
{
JT_UNKNOWN
,
JT_SYSTEM
,
JT_CONST
,
JT_EQ_REF
,
JT_REF
,
JT_MAYBE_REF
,
JT_ALL
,
JT_RANGE
,
JT_NEXT
,
JT_FT
,
JT_REF_OR_NULL
,
JT_ALL
,
JT_RANGE
,
JT_NEXT
,
JT_FT
,
JT_REF_OR_NULL
,
JT_SIMPLE_IN
,
JT_INDEX_IN
};
JT_SIMPLE_IN
,
JT_INDEX_IN
,
JT_INDEX_MERGE
};
class
JOIN
;
class
JOIN
;
...
@@ -85,7 +85,7 @@ typedef struct st_join_table {
...
@@ -85,7 +85,7 @@ typedef struct st_join_table {
KEYUSE
*
keyuse
;
/* pointer to first used key */
KEYUSE
*
keyuse
;
/* pointer to first used key */
SQL_SELECT
*
select
;
SQL_SELECT
*
select
;
COND
*
select_cond
;
COND
*
select_cond
;
QUICK_SELECT
*
quick
;
QUICK_SELECT
_I
*
quick
;
Item
*
on_expr
;
Item
*
on_expr
;
const
char
*
info
;
const
char
*
info
;
byte
*
null_ref_key
;
byte
*
null_ref_key
;
...
@@ -307,6 +307,7 @@ void copy_fields(TMP_TABLE_PARAM *param);
...
@@ -307,6 +307,7 @@ void copy_fields(TMP_TABLE_PARAM *param);
void
copy_funcs
(
Item
**
func_ptr
);
void
copy_funcs
(
Item
**
func_ptr
);
bool
create_myisam_from_heap
(
THD
*
thd
,
TABLE
*
table
,
TMP_TABLE_PARAM
*
param
,
bool
create_myisam_from_heap
(
THD
*
thd
,
TABLE
*
table
,
TMP_TABLE_PARAM
*
param
,
int
error
,
bool
ignore_last_dupp_error
);
int
error
,
bool
ignore_last_dupp_error
);
uint
find_shortest_key
(
TABLE
*
table
,
key_map
usable_keys
);
/* functions from opt_sum.cc */
/* functions from opt_sum.cc */
int
opt_sum_query
(
TABLE_LIST
*
tables
,
List
<
Item
>
&
all_fields
,
COND
*
conds
);
int
opt_sum_query
(
TABLE_LIST
*
tables
,
List
<
Item
>
&
all_fields
,
COND
*
conds
);
...
...
sql/sql_test.cc
View file @
ca6c4cc3
...
@@ -179,9 +179,39 @@ TEST_join(JOIN *join)
...
@@ -179,9 +179,39 @@ TEST_join(JOIN *join)
" quick select checked for each record (keys: %d)
\n
"
,
" quick select checked for each record (keys: %d)
\n
"
,
(
int
)
tab
->
select
->
quick_keys
);
(
int
)
tab
->
select
->
quick_keys
);
else
if
(
tab
->
select
->
quick
)
else
if
(
tab
->
select
->
quick
)
fprintf
(
DBUG_FILE
,
" quick select used on key %s, length: %d
\n
"
,
{
int
quick_type
=
tab
->
select
->
quick
->
get_type
();
if
((
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_RANGE
)
||
(
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_RANGE_DESC
))
{
fprintf
(
DBUG_FILE
,
" quick select used on key %s, length: %d
\n
"
,
form
->
key_info
[
tab
->
select
->
quick
->
index
].
name
,
form
->
key_info
[
tab
->
select
->
quick
->
index
].
name
,
tab
->
select
->
quick
->
max_used_key_length
);
tab
->
select
->
quick
->
max_used_key_length
);
}
else
if
(
quick_type
==
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
)
{
QUICK_INDEX_MERGE_SELECT
*
quick_imerge
=
(
QUICK_INDEX_MERGE_SELECT
*
)
tab
->
select
->
quick
;
QUICK_RANGE_SELECT
*
quick
;
fprintf
(
DBUG_FILE
,
" index_merge quick select used
\n
"
);
List_iterator_fast
<
QUICK_RANGE_SELECT
>
it
(
quick_imerge
->
quick_selects
);
while
((
quick
=
it
++
))
{
fprintf
(
DBUG_FILE
,
" range quick select: key %s, length: %d
\n
"
,
form
->
key_info
[
quick
->
index
].
name
,
quick
->
max_used_key_length
);
}
}
else
{
fprintf
(
DBUG_FILE
,
" quick select of unknown nature used
\n
"
);
}
}
else
else
VOID
(
fputs
(
" select used
\n
"
,
DBUG_FILE
));
VOID
(
fputs
(
" select used
\n
"
,
DBUG_FILE
));
}
}
...
...
sql/sql_union.cc
View file @
ca6c4cc3
...
@@ -117,6 +117,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
...
@@ -117,6 +117,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
{
{
SELECT_LEX
*
lex_select_save
=
thd
->
lex
.
current_select
;
SELECT_LEX
*
lex_select_save
=
thd
->
lex
.
current_select
;
SELECT_LEX
*
select_cursor
;
SELECT_LEX
*
select_cursor
;
SELECT_LEX
*
sl
;
DBUG_ENTER
(
"st_select_lex_unit::prepare"
);
DBUG_ENTER
(
"st_select_lex_unit::prepare"
);
if
(
prepared
)
if
(
prepared
)
...
@@ -185,7 +186,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
...
@@ -185,7 +186,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
union_result
->
not_describe
=
1
;
union_result
->
not_describe
=
1
;
union_result
->
tmp_table_param
=
tmp_table_param
;
union_result
->
tmp_table_param
=
tmp_table_param
;
for
(
SELECT_LEX
*
sl
=
select_cursor
;
sl
;
sl
=
sl
->
next_select
())
for
(
sl
=
select_cursor
;
sl
;
sl
=
sl
->
next_select
())
{
{
JOIN
*
join
=
new
JOIN
(
thd
,
sl
->
item_list
,
JOIN
*
join
=
new
JOIN
(
thd
,
sl
->
item_list
,
sl
->
options
|
thd
->
options
|
SELECT_NO_UNLOCK
,
sl
->
options
|
thd
->
options
|
SELECT_NO_UNLOCK
,
...
...
sql/sql_update.cc
View file @
ca6c4cc3
...
@@ -171,10 +171,18 @@ int mysql_update(THD *thd,
...
@@ -171,10 +171,18 @@ int mysql_update(THD *thd,
init_ftfuncs
(
thd
,
&
thd
->
lex
.
select_lex
,
1
);
init_ftfuncs
(
thd
,
&
thd
->
lex
.
select_lex
,
1
);
/* Check if we are modifying a key that we are used to search with */
/* Check if we are modifying a key that we are used to search with */
if
(
select
&&
select
->
quick
)
if
(
select
&&
select
->
quick
)
{
if
(
select
->
quick
->
get_type
()
!=
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
)
{
used_index
=
select
->
quick
->
index
;
used_key_is_modified
=
(
!
select
->
quick
->
unique_key_range
()
&&
used_key_is_modified
=
(
!
select
->
quick
->
unique_key_range
()
&&
check_if_key_used
(
table
,
check_if_key_used
(
table
,
used_index
,
fields
));
(
used_index
=
select
->
quick
->
index
),
}
fields
));
else
{
used_key_is_modified
=
true
;
}
}
else
if
((
used_index
=
table
->
file
->
key_used_on_scan
)
<
MAX_KEY
)
else
if
((
used_index
=
table
->
file
->
key_used_on_scan
)
<
MAX_KEY
)
used_key_is_modified
=
check_if_key_used
(
table
,
used_index
,
fields
);
used_key_is_modified
=
check_if_key_used
(
table
,
used_index
,
fields
);
else
else
...
@@ -688,8 +696,26 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
...
@@ -688,8 +696,26 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
case
JT_ALL
:
case
JT_ALL
:
/* If range search on index */
/* If range search on index */
if
(
join_tab
->
quick
)
if
(
join_tab
->
quick
)
return
!
check_if_key_used
(
table
,
join_tab
->
quick
->
index
,
{
*
fields
);
if
(
join_tab
->
quick
->
get_type
()
!=
QUICK_SELECT_I
::
QS_TYPE_INDEX_MERGE
)
{
return
!
check_if_key_used
(
table
,
join_tab
->
quick
->
index
,
*
fields
);
}
else
{
QUICK_INDEX_MERGE_SELECT
*
qsel_imerge
=
(
QUICK_INDEX_MERGE_SELECT
*
)(
join_tab
->
quick
);
List_iterator_fast
<
QUICK_RANGE_SELECT
>
it
(
qsel_imerge
->
quick_selects
);
QUICK_RANGE_SELECT
*
quick
;
while
((
quick
=
it
++
))
{
if
(
check_if_key_used
(
table
,
quick
->
index
,
*
fields
))
return
0
;
}
return
1
;
}
}
/* If scanning in clustered key */
/* If scanning in clustered key */
if
((
table
->
file
->
table_flags
()
&
HA_PRIMARY_KEY_IN_READ_INDEX
)
&&
if
((
table
->
file
->
table_flags
()
&
HA_PRIMARY_KEY_IN_READ_INDEX
)
&&
table
->
primary_key
<
MAX_KEY
)
table
->
primary_key
<
MAX_KEY
)
...
...
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