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
017c7518
Commit
017c7518
authored
Dec 02, 2010
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Plain Diff
Merge
parents
e7337563
44be131c
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
206 additions
and
164 deletions
+206
-164
mysql-test/include/mrr_tests.inc
mysql-test/include/mrr_tests.inc
+3
-0
mysql-test/r/innodb_mrr.result
mysql-test/r/innodb_mrr.result
+1
-0
mysql-test/r/maria_mrr.result
mysql-test/r/maria_mrr.result
+1
-0
mysql-test/r/myisam_mrr.result
mysql-test/r/myisam_mrr.result
+3
-2
mysql-test/t/myisam_mrr.test
mysql-test/t/myisam_mrr.test
+1
-1
sql/handler.h
sql/handler.h
+17
-0
sql/multi_range_read.cc
sql/multi_range_read.cc
+131
-127
sql/multi_range_read.h
sql/multi_range_read.h
+33
-30
sql/opt_range.cc
sql/opt_range.cc
+2
-2
sql/sql_join_cache.cc
sql/sql_join_cache.cc
+14
-2
No files found.
mysql-test/include/mrr_tests.inc
View file @
017c7518
...
@@ -71,6 +71,9 @@ select b,filler from t3 where (b>='c-1011=w' and b<= 'c-1018=w') or
...
@@ -71,6 +71,9 @@ select b,filler from t3 where (b>='c-1011=w' and b<= 'c-1018=w') or
#
#
# Now try different keypart types and special values
# Now try different keypart types and special values
#
#
--
disable_warnings
drop
table
if
exists
t4
;
--
enable_warnings
create
table
t4
(
a
varchar
(
10
),
b
int
,
c
char
(
10
),
filler
char
(
200
),
create
table
t4
(
a
varchar
(
10
),
b
int
,
c
char
(
10
),
filler
char
(
200
),
key
idx1
(
a
,
b
,
c
));
key
idx1
(
a
,
b
,
c
));
...
...
mysql-test/r/innodb_mrr.result
View file @
017c7518
...
@@ -168,6 +168,7 @@ c-1020=w filler
...
@@ -168,6 +168,7 @@ c-1020=w filler
c-1021=w filler
c-1021=w filler
c-1022=w filler
c-1022=w filler
c-1023=w filler
c-1023=w filler
drop table if exists t4;
create table t4 (a varchar(10), b int, c char(10), filler char(200),
create table t4 (a varchar(10), b int, c char(10), filler char(200),
key idx1 (a, b, c));
key idx1 (a, b, c));
insert into t4 (filler) select concat('NULL-', 15-a) from t2 order by a limit 15;
insert into t4 (filler) select concat('NULL-', 15-a) from t2 order by a limit 15;
...
...
mysql-test/r/maria_mrr.result
View file @
017c7518
...
@@ -169,6 +169,7 @@ c-1020=w filler
...
@@ -169,6 +169,7 @@ c-1020=w filler
c-1021=w filler
c-1021=w filler
c-1022=w filler
c-1022=w filler
c-1023=w filler
c-1023=w filler
drop table if exists t4;
create table t4 (a varchar(10), b int, c char(10), filler char(200),
create table t4 (a varchar(10), b int, c char(10), filler char(200),
key idx1 (a, b, c));
key idx1 (a, b, c));
insert into t4 (filler) select concat('NULL-', 15-a) from t2 order by a limit 15;
insert into t4 (filler) select concat('NULL-', 15-a) from t2 order by a limit 15;
...
...
mysql-test/r/myisam_mrr.result
View file @
017c7518
drop table if exists t1, t2, t3;
drop table if exists t
0, t
1, t2, t3;
set @mrr_buffer_size_save= @@mrr_buffer_size;
set @mrr_buffer_size_save= @@mrr_buffer_size;
set mrr_buffer_size=79;
set mrr_buffer_size=79;
Warnings:
Warnings:
...
@@ -170,6 +170,7 @@ c-1020=w filler
...
@@ -170,6 +170,7 @@ c-1020=w filler
c-1021=w filler
c-1021=w filler
c-1022=w filler
c-1022=w filler
c-1023=w filler
c-1023=w filler
drop table if exists t4;
create table t4 (a varchar(10), b int, c char(10), filler char(200),
create table t4 (a varchar(10), b int, c char(10), filler char(200),
key idx1 (a, b, c));
key idx1 (a, b, c));
insert into t4 (filler) select concat('NULL-', 15-a) from t2 order by a limit 15;
insert into t4 (filler) select concat('NULL-', 15-a) from t2 order by a limit 15;
...
@@ -432,8 +433,8 @@ a a b
...
@@ -432,8 +433,8 @@ a a b
1 1 1
1 1 1
2 2 2
2 2 2
NULL NULL 1234
NULL NULL 1234
NULL NULL 1234
NULL NULL 5678
NULL NULL 5678
NULL NULL 1234
NULL NULL 5678
NULL NULL 5678
set @@join_cache_level=@save_join_cache_level;
set @@join_cache_level=@save_join_cache_level;
drop table t0, t1;
drop table t0, t1;
...
...
mysql-test/t/myisam_mrr.test
View file @
017c7518
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
#
#
--
disable_warnings
--
disable_warnings
drop
table
if
exists
t1
,
t2
,
t3
;
drop
table
if
exists
t
0
,
t
1
,
t2
,
t3
;
--
enable_warnings
--
enable_warnings
set
@
mrr_buffer_size_save
=
@@
mrr_buffer_size
;
set
@
mrr_buffer_size_save
=
@@
mrr_buffer_size
;
...
...
sql/handler.h
View file @
017c7518
...
@@ -1154,6 +1154,23 @@ typedef void *range_seq_t;
...
@@ -1154,6 +1154,23 @@ typedef void *range_seq_t;
typedef
struct
st_range_seq_if
typedef
struct
st_range_seq_if
{
{
/*
Get key information
SYNOPSIS
get_key_info()
init_params The seq_init_param parameter
length OUT length of the keys in this range sequence
map OUT key_part_map of the keys in this range sequence
DESCRIPTION
This function is set only when using HA_MRR_FIXED_KEY mode. In that mode,
all ranges are single-point equality ranges that use the same set of key
parts. This function allows the MRR implementation to get the length of
a key, and which keyparts it uses.
*/
void
(
*
get_key_info
)(
void
*
init_params
,
uint
*
length
,
key_part_map
*
map
);
/*
/*
Initialize the traversal of range sequence
Initialize the traversal of range sequence
...
...
sql/multi_range_read.cc
View file @
017c7518
...
@@ -288,7 +288,9 @@ scan_it_again:
...
@@ -288,7 +288,9 @@ scan_it_again:
int
Mrr_simple_index_reader
::
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
int
Mrr_simple_index_reader
::
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
void
*
seq_init_param
,
uint
n_ranges
,
void
*
seq_init_param
,
uint
n_ranges
,
uint
mode
,
Buffer_manager
*
buf_manager_arg
)
uint
mode
,
Key_parameters
*
key_par_arg
,
Lifo_buffer
*
key_buffer_arg
,
Buffer_manager
*
buf_manager_arg
)
{
{
HANDLER_BUFFER
no_buffer
=
{
NULL
,
NULL
,
NULL
};
HANDLER_BUFFER
no_buffer
=
{
NULL
,
NULL
,
NULL
};
h
=
h_arg
;
h
=
h_arg
;
...
@@ -332,42 +334,29 @@ int Mrr_ordered_index_reader::get_next(char **range_info)
...
@@ -332,42 +334,29 @@ int Mrr_ordered_index_reader::get_next(char **range_info)
int
res
;
int
res
;
DBUG_ENTER
(
"Mrr_ordered_index_reader::get_next"
);
DBUG_ENTER
(
"Mrr_ordered_index_reader::get_next"
);
if
(
!
know_key_tuple_params
)
{
//psergey-todo: this will be removed
/*
We're at the very start, haven't filled the buffer or even know what
will be there. Force the caller to call refill_buffer():
*/
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
}
for
(;;)
for
(;;)
{
{
if
(
scanning_key_val_iter
)
if
(
!
scanning_key_val_iter
)
{
if
((
res
=
kv_it
.
get_next
()))
{
scanning_key_val_iter
=
FALSE
;
if
((
res
!=
HA_ERR_KEY_NOT_FOUND
&&
res
!=
HA_ERR_END_OF_FILE
))
DBUG_RETURN
(
res
);
kv_it
.
move_to_next_key_value
();
continue
;
}
}
else
{
{
while
((
res
=
kv_it
.
init
(
this
)))
while
((
res
=
kv_it
.
init
(
this
)))
{
{
if
((
res
!=
HA_ERR_KEY_NOT_FOUND
&&
res
!=
HA_ERR_END_OF_FILE
))
if
((
res
!=
HA_ERR_KEY_NOT_FOUND
&&
res
!=
HA_ERR_END_OF_FILE
))
DBUG_RETURN
(
res
);
/* Some fatal error */
DBUG_RETURN
(
res
);
/* Some fatal error */
if
(
key_buffer
->
is_empty
())
//psergey-todo: the problem is here?
if
(
key_buffer
->
is_empty
())
{
{
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
}
}
}
}
scanning_key_val_iter
=
TRUE
;
scanning_key_val_iter
=
TRUE
;
}
if
((
res
=
kv_it
.
get_next
()))
{
scanning_key_val_iter
=
FALSE
;
if
((
res
!=
HA_ERR_KEY_NOT_FOUND
&&
res
!=
HA_ERR_END_OF_FILE
))
DBUG_RETURN
(
res
);
kv_it
.
move_to_next_key_value
();
continue
;
continue
;
}
}
...
@@ -386,14 +375,6 @@ int Mrr_ordered_index_reader::get_next(char **range_info)
...
@@ -386,14 +375,6 @@ int Mrr_ordered_index_reader::get_next(char **range_info)
/**
/**
Fill the buffer with (lookup_tuple, range_id) pairs and sort
Fill the buffer with (lookup_tuple, range_id) pairs and sort
@note
We don't know lookup_tuple before we get the first key from
mrr_funcs.get_next(). Not knowing tuple length means we can't setup the
key buffer (in particular, which part of the buffer space it should occupy
when we have both key and rowid buffers). This problem is solved by having
know_key_tuple_params variabe, and buf_manager, which we ask to set/reset
buffers for us.
*/
*/
int
Mrr_ordered_index_reader
::
refill_buffer
(
bool
initial
)
int
Mrr_ordered_index_reader
::
refill_buffer
(
bool
initial
)
...
@@ -403,45 +384,25 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial)
...
@@ -403,45 +384,25 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial)
uchar
*
key_ptr
;
uchar
*
key_ptr
;
DBUG_ENTER
(
"Mrr_ordered_index_reader::refill_buffer"
);
DBUG_ENTER
(
"Mrr_ordered_index_reader::refill_buffer"
);
DBUG_ASSERT
(
!
know_key_tuple_params
||
key_buffer
->
is_empty
());
DBUG_ASSERT
(
key_buffer
->
is_empty
());
if
(
source_exhausted
)
if
(
source_exhausted
)
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
if
(
know_key_tuple_params
)
//
if (know_key_tuple_params)
{
{
buf_manager
->
reset_buffer_sizes
();
buf_manager
->
reset_buffer_sizes
(
buf_manager
->
arg
);
key_buffer
->
reset
();
key_buffer
->
reset
();
key_buffer
->
setup_writing
(
&
key_ptr
,
keypar
.
key_size_in_keybuf
,
key_buffer
->
setup_writing
(
&
key_ptr
,
keypar
.
key_size_in_keybuf
,
is_mrr_assoc
?
(
uchar
**
)
&
range_info_ptr
:
NULL
,
is_mrr_assoc
?
(
uchar
**
)
&
range_info_ptr
:
NULL
,
sizeof
(
uchar
*
));
sizeof
(
uchar
*
));
}
}
while
(
(
!
know_key_tuple_params
||
key_buffer
->
can_write
()
)
&&
while
(
key_buffer
->
can_write
(
)
&&
!
(
source_exhausted
=
(
bool
)
mrr_funcs
.
next
(
mrr_iter
,
&
cur_range
)))
!
(
source_exhausted
=
(
bool
)
mrr_funcs
.
next
(
mrr_iter
,
&
cur_range
)))
{
{
DBUG_ASSERT
(
cur_range
.
range_flag
&
EQ_RANGE
);
DBUG_ASSERT
(
cur_range
.
range_flag
&
EQ_RANGE
);
if
(
!
know_key_tuple_params
)
{
/* This only happens when we've just started filling the buffer */
key_range
*
sample_key
=
&
cur_range
.
start_key
;
know_key_tuple_params
=
TRUE
;
keypar
.
key_tuple_length
=
sample_key
->
length
;
keypar
.
key_tuple_map
=
sample_key
->
keypart_map
;
keypar
.
key_size_in_keybuf
=
keypar
.
use_key_pointers
?
sizeof
(
char
*
)
:
keypar
.
key_tuple_length
;
KEY
*
key_info
=
&
h
->
get_table
()
->
key_info
[
h
->
active_index
];
keypar
.
index_ranges_unique
=
test
(
key_info
->
flags
&
HA_NOSAME
&&
key_info
->
key_parts
==
my_count_bits
(
sample_key
->
keypart_map
));
buf_manager
->
setup_buffer_sizes
(
keypar
.
key_size_in_keybuf
,
keypar
.
key_tuple_map
);
key_buffer
=
buf_manager
->
get_key_buffer
();
key_buffer
->
setup_writing
(
&
key_ptr
,
keypar
.
key_size_in_keybuf
,
is_mrr_assoc
?
(
uchar
**
)
&
range_info_ptr
:
NULL
,
sizeof
(
uchar
*
));
DBUG_ASSERT
(
key_buffer
->
can_write
());
}
/* Put key, or {key, range_id} pair into the buffer */
/* Put key, or {key, range_id} pair into the buffer */
key_ptr
=
(
keypar
.
use_key_pointers
)
?
(
uchar
*
)
&
cur_range
.
start_key
.
key
:
key_ptr
=
(
keypar
.
use_key_pointers
)
?
(
uchar
*
)
&
cur_range
.
start_key
.
key
:
(
uchar
*
)
cur_range
.
start_key
.
key
;
(
uchar
*
)
cur_range
.
start_key
.
key
;
...
@@ -452,7 +413,7 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial)
...
@@ -452,7 +413,7 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial)
/* Force get_next() to start with kv_it.init() call: */
/* Force get_next() to start with kv_it.init() call: */
scanning_key_val_iter
=
FALSE
;
scanning_key_val_iter
=
FALSE
;
if
(
source_exhausted
&&
(
!
know_key_tuple_params
||
key_buffer
->
is_empty
()
))
if
(
source_exhausted
&&
key_buffer
->
is_empty
(
))
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
key_buffer
->
sort
((
key_buffer
->
type
()
==
Lifo_buffer
::
FORWARD
)
?
key_buffer
->
sort
((
key_buffer
->
type
()
==
Lifo_buffer
::
FORWARD
)
?
...
@@ -465,16 +426,24 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial)
...
@@ -465,16 +426,24 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial)
int
Mrr_ordered_index_reader
::
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
int
Mrr_ordered_index_reader
::
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
void
*
seq_init_param
,
uint
n_ranges
,
void
*
seq_init_param
,
uint
n_ranges
,
uint
mode
,
Buffer_manager
*
buf_manager_arg
)
uint
mode
,
Key_parameters
*
key_par_arg
,
Lifo_buffer
*
key_buffer_arg
,
Buffer_manager
*
buf_manager_arg
)
{
{
h
=
h_arg
;
h
=
h_arg
;
key_buffer
=
key_buffer_arg
;
buf_manager
=
buf_manager_arg
;
keypar
=
*
key_par_arg
;
KEY
*
key_info
=
&
h
->
get_table
()
->
key_info
[
h
->
active_index
];
keypar
.
index_ranges_unique
=
test
(
key_info
->
flags
&
HA_NOSAME
&&
key_info
->
key_parts
==
my_count_bits
(
keypar
.
key_tuple_map
));
mrr_iter
=
seq_funcs
->
init
(
seq_init_param
,
n_ranges
,
mode
);
mrr_iter
=
seq_funcs
->
init
(
seq_init_param
,
n_ranges
,
mode
);
keypar
.
use_key_pointers
=
test
(
mode
&
HA_MRR_MATERIALIZED_KEYS
);
is_mrr_assoc
=
!
test
(
mode
&
HA_MRR_NO_ASSOCIATION
);
is_mrr_assoc
=
!
test
(
mode
&
HA_MRR_NO_ASSOCIATION
);
mrr_funcs
=
*
seq_funcs
;
mrr_funcs
=
*
seq_funcs
;
know_key_tuple_params
=
FALSE
;
source_exhausted
=
FALSE
;
source_exhausted
=
FALSE
;
buf_manager
=
buf_manager_arg
;
/*
/*
Short: don't do identical key handling when we have a pushed index
Short: don't do identical key handling when we have a pushed index
condition.
condition.
...
@@ -546,9 +515,6 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg,
...
@@ -546,9 +515,6 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg,
When this function returns, either rowid buffer is not empty, or the source
When this function returns, either rowid buffer is not empty, or the source
of lookup keys (i.e. ranges) is exhaused.
of lookup keys (i.e. ranges) is exhaused.
dsmrr_eof is set to indicate whether we've exhausted the list of ranges we're
scanning. This function never returns HA_ERR_END_OF_FILE.
@retval 0 OK, the next portion of rowids is in the buffer,
@retval 0 OK, the next portion of rowids is in the buffer,
properly ordered
properly ordered
@retval other Error
@retval other Error
...
@@ -751,6 +717,11 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
...
@@ -751,6 +717,11 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
{
{
THD
*
thd
=
current_thd
;
THD
*
thd
=
current_thd
;
int
res
;
int
res
;
Key_parameters
keypar
;
uint
key_buff_elem_size
;
handler
*
h_idx
;
Mrr_ordered_rndpos_reader
*
disk_strategy
=
NULL
;
bool
do_sort_keys
=
FALSE
;
DBUG_ENTER
(
"DsMrr_impl::dsmrr_init"
);
DBUG_ENTER
(
"DsMrr_impl::dsmrr_init"
);
/*
/*
...
@@ -762,15 +733,13 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
...
@@ -762,15 +733,13 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
strategy_exhausted
=
FALSE
;
strategy_exhausted
=
FALSE
;
/* By default, have do-nothing buffer manager */
buf_manager
.
arg
=
this
;
buf_manager
.
reset_buffer_sizes
=
do_nothing
;
buf_manager
.
redistribute_buffer_space
=
do_nothing
;
if
(
mode
&
(
HA_MRR_USE_DEFAULT_IMPL
|
HA_MRR_SORTED
))
if
(
mode
&
(
HA_MRR_USE_DEFAULT_IMPL
|
HA_MRR_SORTED
))
{
goto
use_default_impl
;
DBUG_ASSERT
(
h
->
inited
==
handler
::
INDEX
);
/* Call correct init function and assign to top level object */
Mrr_simple_index_reader
*
s
=
&
reader_factory
.
simple_index_reader
;
res
=
s
->
init
(
h
,
seq_funcs
,
seq_init_param
,
n_ranges
,
mode
,
this
);
strategy
=
s
;
DBUG_RETURN
(
res
);
}
/*
/*
Determine whether we'll need to do key sorting and/or rnd_pos() scan
Determine whether we'll need to do key sorting and/or rnd_pos() scan
...
@@ -779,6 +748,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
...
@@ -779,6 +748,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if
((
mode
&
HA_MRR_SINGLE_POINT
)
&&
if
((
mode
&
HA_MRR_SINGLE_POINT
)
&&
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_MRR_SORT_KEYS
))
optimizer_flag
(
thd
,
OPTIMIZER_SWITCH_MRR_SORT_KEYS
))
{
{
do_sort_keys
=
TRUE
;
index_strategy
=
&
reader_factory
.
ordered_index_reader
;
index_strategy
=
&
reader_factory
.
ordered_index_reader
;
}
}
else
else
...
@@ -794,10 +764,9 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
...
@@ -794,10 +764,9 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
(
h
->
inited
==
handler
::
RND
&&
h2
&&
(
h
->
inited
==
handler
::
RND
&&
h2
&&
h2
->
inited
==
handler
::
INDEX
));
h2
->
inited
==
handler
::
INDEX
));
h
andler
*
h
_idx
=
(
h
->
inited
==
handler
::
INDEX
)
?
h
:
h2
;
h_idx
=
(
h
->
inited
==
handler
::
INDEX
)
?
h
:
h2
;
keyno
=
h_idx
->
active_index
;
keyno
=
h_idx
->
active_index
;
Mrr_ordered_rndpos_reader
*
disk_strategy
=
NULL
;
if
(
!
(
keyno
==
table
->
s
->
primary_key
&&
h_idx
->
primary_key_is_clustered
()))
if
(
!
(
keyno
==
table
->
s
->
primary_key
&&
h_idx
->
primary_key_is_clustered
()))
{
{
strategy
=
disk_strategy
=
&
reader_factory
.
ordered_rndpos_reader
;
strategy
=
disk_strategy
=
&
reader_factory
.
ordered_rndpos_reader
;
...
@@ -809,28 +778,63 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
...
@@ -809,28 +778,63 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
full_buf
=
buf
->
buffer
;
full_buf
=
buf
->
buffer
;
full_buf_end
=
buf
->
buffer_end
;
full_buf_end
=
buf
->
buffer_end
;
if
(
do_sort_keys
)
{
/* Pre-calculate some parameters of key sorting */
keypar
.
use_key_pointers
=
test
(
mode
&
HA_MRR_MATERIALIZED_KEYS
);
seq_funcs
->
get_key_info
(
seq_init_param
,
&
keypar
.
key_tuple_length
,
&
keypar
.
key_tuple_map
);
keypar
.
key_size_in_keybuf
=
keypar
.
use_key_pointers
?
sizeof
(
char
*
)
:
keypar
.
key_tuple_length
;
key_buff_elem_size
=
keypar
.
key_size_in_keybuf
+
(
int
)
is_mrr_assoc
*
sizeof
(
void
*
);
}
if
(
strategy
==
index_strategy
)
if
(
strategy
==
index_strategy
)
{
{
/* Index strategy serves it all. We don't need two handlers, etc */
/*
/* Give the buffer to index strategy */
Index strategy alone handles the record retrieval. Give all buffer space
to it. Key buffer should have forward orientation so we can return the
end of it.
*/
key_buffer
=
&
forward_key_buf
;
key_buffer
->
set_buffer_space
(
full_buf
,
full_buf_end
);
/* Safety: specify that rowid buffer has zero size: */
rowid_buffer
.
set_buffer_space
(
full_buf_end
,
full_buf_end
);
if
(
do_sort_keys
&&
!
key_buffer
->
have_space_for
(
key_buff_elem_size
))
goto
use_default_impl
;
if
((
res
=
index_strategy
->
init
(
h
,
seq_funcs
,
seq_init_param
,
n_ranges
,
if
((
res
=
index_strategy
->
init
(
h
,
seq_funcs
,
seq_init_param
,
n_ranges
,
mode
,
this
)))
mode
,
&
keypar
,
key_buffer
,
&
buf_manager
)))
goto
error
;
goto
error
;
}
}
else
else
{
{
/*
/* We'll have both index and rndpos strategies working together */
If we got here the request is served by both index and rndpos strategies
if
(
do_sort_keys
)
working together.
{
/* Both strategies will need buffer space, share the buffer */
if
(
setup_buffer_sharing
(
keypar
.
key_size_in_keybuf
,
keypar
.
key_tuple_map
))
goto
use_default_impl
;
*/
buf_manager
.
reset_buffer_sizes
=
reset_buffer_sizes
;
rowid_buffer
.
set_buffer_space
(
buf
->
buffer
,
buf
->
buffer_end
);
buf_manager
.
redistribute_buffer_space
=
redistribute_buffer_space
;
}
else
{
/* index strategy doesn't need buffer, give all space to rowids*/
rowid_buffer
.
set_buffer_space
(
full_buf
,
full_buf_end
);
if
(
!
rowid_buffer
.
have_space_for
(
h
->
ref_length
+
(
int
)
is_mrr_assoc
*
sizeof
(
char
*
)))
goto
use_default_impl
;
}
if
((
res
=
setup_two_handlers
()))
if
((
res
=
setup_two_handlers
()))
goto
error
;
goto
error
;
if
((
res
=
index_strategy
->
init
(
h2
,
seq_funcs
,
seq_init_param
,
n_ranges
,
if
((
res
=
index_strategy
->
init
(
h2
,
seq_funcs
,
seq_init_param
,
n_ranges
,
mode
,
this
))
||
mode
,
&
keypar
,
key_buffer
,
&
buf_manager
))
||
(
res
=
disk_strategy
->
init
(
h
,
index_strategy
,
mode
,
&
rowid_buffer
)))
(
res
=
disk_strategy
->
init
(
h
,
index_strategy
,
mode
,
&
rowid_buffer
)))
{
{
goto
error
;
goto
error
;
...
@@ -859,6 +863,14 @@ error:
...
@@ -859,6 +863,14 @@ error:
/* Safety, not really needed but: */
/* Safety, not really needed but: */
strategy
=
NULL
;
strategy
=
NULL
;
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
use_default_impl:
DBUG_ASSERT
(
h
->
inited
==
handler
::
INDEX
);
/* Call correct init function and assign to top level object */
Mrr_simple_index_reader
*
s
=
&
reader_factory
.
simple_index_reader
;
res
=
s
->
init
(
h
,
seq_funcs
,
seq_init_param
,
n_ranges
,
mode
,
NULL
,
NULL
,
NULL
);
strategy
=
s
;
DBUG_RETURN
(
res
);
}
}
...
@@ -1010,34 +1022,23 @@ int Mrr_ordered_index_reader::compare_keys_reverse(void* arg, uchar* key1,
...
@@ -1010,34 +1022,23 @@ int Mrr_ordered_index_reader::compare_keys_reverse(void* arg, uchar* key1,
/**
/**
Setup key/rowid buffer sizes based on sample_key and its length.
Set the buffer space to be shared between rowid and key buffer
@param
@return FALSE ok
sample_key A lookup key to use as a sample. It is assumed that
@return TRUE There is so little buffer space that we won't be able to use
all other keys will have the same length/etc.
the strategy.
@note
This happens when we don't have enough space for one rowid
This function must be called when all buffers are empty
element and one key element so this is mainly targeted at
testing.
*/
*/
void
DsMrr_impl
::
setup_buffer_sizes
(
uint
key_size_in_keybuf
,
bool
DsMrr_impl
::
setup_buffer_sharing
(
uint
key_size_in_keybuf
,
key_part_map
key_tuple_map
)
key_part_map
key_tuple_map
)
{
{
uint
key_buff_elem_size
=
key_size_in_keybuf
+
uint
key_buff_elem_size
=
key_size_in_keybuf
+
(
int
)
is_mrr_assoc
*
sizeof
(
void
*
);
(
int
)
is_mrr_assoc
*
sizeof
(
void
*
);
KEY
*
key_info
=
&
h
->
get_table
()
->
key_info
[
keyno
];
KEY
*
key_info
=
&
h
->
get_table
()
->
key_info
[
keyno
];
if
(
strategy
==
index_strategy
)
{
/* Give all space to the key buffer, key buffer must be forward */
key_buffer
=
&
forward_key_buf
;
key_buffer
->
set_buffer_space
(
full_buf
,
full_buf_end
);
DBUG_ASSERT
(
key_buffer
->
have_space_for
(
key_buff_elem_size
));
/* Just in case, tell rowid buffer that it has zero size: */
rowid_buffer
.
set_buffer_space
(
full_buf_end
,
full_buf_end
);
return
;
}
/*
/*
Ok if we got here we need to allocate one part of the buffer
Ok if we got here we need to allocate one part of the buffer
for keys and another part for rowids.
for keys and another part for rowids.
...
@@ -1048,7 +1049,6 @@ void DsMrr_impl::setup_buffer_sizes(uint key_size_in_keybuf,
...
@@ -1048,7 +1049,6 @@ void DsMrr_impl::setup_buffer_sizes(uint key_size_in_keybuf,
/*
/*
Use rec_per_key statistics as a basis to find out how many rowids
Use rec_per_key statistics as a basis to find out how many rowids
we'll get for each key value.
we'll get for each key value.
TODO: are we guaranteed to get r_p_c==1 for unique keys?
TODO: what should be the default value to use when there is no
TODO: what should be the default value to use when there is no
statistics?
statistics?
*/
*/
...
@@ -1065,45 +1065,48 @@ void DsMrr_impl::setup_buffer_sizes(uint key_size_in_keybuf,
...
@@ -1065,45 +1065,48 @@ void DsMrr_impl::setup_buffer_sizes(uint key_size_in_keybuf,
size_t
bytes_for_rowids
=
size_t
bytes_for_rowids
=
round
(
fraction_for_rowids
*
(
full_buf_end
-
full_buf
));
round
(
fraction_for_rowids
*
(
full_buf_end
-
full_buf
));
uint
bytes_for_keys
=
(
full_buf_end
-
full_buf
)
-
bytes_for_rowids
;
long
bytes_for_keys
=
(
full_buf_end
-
full_buf
)
-
bytes_for_rowids
;
if
(
bytes_for_keys
<
key_buff_elem_size
+
1
)
if
(
bytes_for_keys
<
key_buff_elem_size
+
1
)
{
{
u
long
add
=
key_buff_elem_size
+
1
-
bytes_for_keys
;
long
add
=
key_buff_elem_size
+
1
-
bytes_for_keys
;
bytes_for_keys
=
key_buff_elem_size
+
1
;
bytes_for_keys
=
key_buff_elem_size
+
1
;
bytes_for_rowids
-=
add
;
bytes_for_rowids
-=
add
;
DBUG_ASSERT
(
bytes_for_rowids
>=
rowid_buf_elem_size
+
1
);
}
}
if
(
bytes_for_rowids
<
rowid_buf_elem_size
+
1
)
if
(
bytes_for_rowids
<
rowid_buf_elem_size
+
1
)
{
{
u
long
add
=
rowid_buf_elem_size
+
1
-
bytes_for_rowids
;
long
add
=
rowid_buf_elem_size
+
1
-
bytes_for_rowids
;
bytes_for_rowids
=
rowid_buf_elem_size
+
1
;
bytes_for_rowids
=
rowid_buf_elem_size
+
1
;
bytes_for_keys
-=
add
;
bytes_for_keys
-=
add
;
DBUG_ASSERT
(
bytes_for_keys
>=
key_buff_elem_size
+
1
);
}
}
rowid_buffer_end
=
full_buf
+
bytes_for_rowids
;
rowid_buffer_end
=
full_buf
+
bytes_for_rowids
;
rowid_buffer
.
set_buffer_space
(
full_buf
,
rowid_buffer_end
);
rowid_buffer
.
set_buffer_space
(
full_buf
,
rowid_buffer_end
);
key_buffer
=
&
backward_key_buf
;
key_buffer
=
&
backward_key_buf
;
key_buffer
->
set_buffer_space
(
rowid_buffer_end
,
full_buf_end
);
key_buffer
->
set_buffer_space
(
rowid_buffer_end
,
full_buf_end
);
DBUG_ASSERT
(
key_buffer
->
have_space_for
(
key_buff_elem_size
));
DBUG_ASSERT
(
rowid_buffer
.
have_space_for
(
rowid_buf_elem_size
));
if
(
!
key_buffer
->
have_space_for
(
key_buff_elem_size
)
||
!
rowid_buffer
.
have_space_for
(
rowid_buf_elem_size
))
return
TRUE
;
/* Failed to provide minimum space for one of the buffers */
return
FALSE
;
}
}
void
DsMrr_impl
::
reset_buffer_sizes
(
)
void
DsMrr_impl
::
do_nothing
(
void
*
dsmrr_arg
)
{
{
if
(
strategy
!=
index_strategy
)
/* Do nothing */
{
}
/*
Ok we have both ordered index reader and there is a disk rearder.
Redistribute the buffer space.
void
DsMrr_impl
::
reset_buffer_sizes
(
void
*
dsmrr_arg
)
*/
{
rowid_buffer
.
set_buffer_space
(
full_buf
,
rowid_buffer_end
);
DsMrr_impl
*
dsmrr
=
(
DsMrr_impl
*
)
dsmrr_arg
;
key_buffer
=
&
backward_key_buf
;
dsmrr
->
rowid_buffer
.
set_buffer_space
(
dsmrr
->
full_buf
,
key_buffer
->
set_buffer_space
(
rowid_buffer_end
,
full_buf_end
);
dsmrr
->
rowid_buffer_end
);
}
dsmrr
->
key_buffer
->
set_buffer_space
(
dsmrr
->
rowid_buffer_end
,
dsmrr
->
full_buf_end
);
}
}
...
@@ -1111,11 +1114,12 @@ void DsMrr_impl::reset_buffer_sizes()
...
@@ -1111,11 +1114,12 @@ void DsMrr_impl::reset_buffer_sizes()
Take unused space from the key buffer and give it to the rowid buffer
Take unused space from the key buffer and give it to the rowid buffer
*/
*/
void
DsMrr_impl
::
redistribute_buffer_space
()
void
DsMrr_impl
::
redistribute_buffer_space
(
void
*
dsmrr_arg
)
{
{
DsMrr_impl
*
dsmrr
=
(
DsMrr_impl
*
)
dsmrr_arg
;
uchar
*
unused_start
,
*
unused_end
;
uchar
*
unused_start
,
*
unused_end
;
key_buffer
->
remove_unused_space
(
&
unused_start
,
&
unused_end
);
dsmrr
->
key_buffer
->
remove_unused_space
(
&
unused_start
,
&
unused_end
);
rowid_buffer
.
grow
(
unused_start
,
unused_end
);
dsmrr
->
rowid_buffer
.
grow
(
unused_start
,
unused_end
);
}
}
...
...
sql/multi_range_read.h
View file @
017c7518
...
@@ -56,9 +56,6 @@ class Mrr_ordered_index_reader;
...
@@ -56,9 +56,6 @@ class Mrr_ordered_index_reader;
class
Key_parameters
class
Key_parameters
{
{
public:
public:
/* TRUE <=> We can get at most one index tuple for a lookup key */
bool
index_ranges_unique
;
uint
key_tuple_length
;
/* Length of index lookup tuple, in bytes */
uint
key_tuple_length
;
/* Length of index lookup tuple, in bytes */
key_part_map
key_tuple_map
;
/* keyparts used in index lookup tuples */
key_part_map
key_tuple_map
;
/* keyparts used in index lookup tuples */
...
@@ -71,6 +68,9 @@ public:
...
@@ -71,6 +68,9 @@ public:
/* TRUE <=> don't copy key values, use pointers to them instead. */
/* TRUE <=> don't copy key values, use pointers to them instead. */
bool
use_key_pointers
;
bool
use_key_pointers
;
/* TRUE <=> We can get at most one index tuple for a lookup key */
bool
index_ranges_unique
;
};
};
...
@@ -145,28 +145,27 @@ public:
...
@@ -145,28 +145,27 @@ public:
Buffer manager interface. Mrr_reader objects use it to inqure DsMrr_impl
Buffer manager interface. Mrr_reader objects use it to inqure DsMrr_impl
to manage buffer space for them.
to manage buffer space for them.
*/
*/
class
B
uffer_manager
typedef
struct
st_b
uffer_manager
{
{
public:
public:
/* Opaque value to be passed as the first argument to all member functions */
void
*
arg
;
/*
/*
Index-based reader calls this when it gets the first key, so we get to know
This is called when we've freed more space from the rowid buffer. The
key length and
callee will get the unused space from the rowid buffer and give it to the
key buffer.
*/
*/
virtual
void
setup_buffer_sizes
(
uint
key_size_in_keybuf
,
void
(
*
redistribute_buffer_space
)(
void
*
arg
);
key_part_map
key_tuple_map
)
=
0
;
virtual
void
redistribute_buffer_space
()
=
0
;
/*
/*
This is called when both key and rowid buffers are empty, and so it's time
This is called when both key and rowid buffers are empty, and so it's time
to reset them to their original size (They've lost their original size,
to reset them to their original size (They've lost their original size,
because we were dynamically growing rowid buffer and shrinking key buffer).
because we were dynamically growing rowid buffer and shrinking key buffer).
*/
*/
v
irtual
void
reset_buffer_sizes
()
=
0
;
v
oid
(
*
reset_buffer_sizes
)(
void
*
arg
)
;
virtual
Lifo_buffer
*
get_key_buffer
()
=
0
;
}
Buffer_manager
;
virtual
~
Buffer_manager
(){}
/* Shut up the compiler */
};
/*
/*
...
@@ -205,7 +204,9 @@ protected:
...
@@ -205,7 +204,9 @@ protected:
public:
public:
virtual
int
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
virtual
int
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
void
*
seq_init_param
,
uint
n_ranges
,
void
*
seq_init_param
,
uint
n_ranges
,
uint
mode
,
Buffer_manager
*
buf_manager_arg
)
=
0
;
uint
mode
,
Key_parameters
*
key_par
,
Lifo_buffer
*
key_buffer
,
Buffer_manager
*
buf_manager_arg
)
=
0
;
/* Get pointer to place where every get_next() call will put rowid */
/* Get pointer to place where every get_next() call will put rowid */
virtual
uchar
*
get_rowid_ptr
()
=
0
;
virtual
uchar
*
get_rowid_ptr
()
=
0
;
...
@@ -226,7 +227,9 @@ class Mrr_simple_index_reader : public Mrr_index_reader
...
@@ -226,7 +227,9 @@ class Mrr_simple_index_reader : public Mrr_index_reader
public:
public:
int
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
int
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
void
*
seq_init_param
,
uint
n_ranges
,
void
*
seq_init_param
,
uint
n_ranges
,
uint
mode
,
Buffer_manager
*
buf_manager_arg
);
uint
mode
,
Key_parameters
*
key_par
,
Lifo_buffer
*
key_buffer
,
Buffer_manager
*
buf_manager_arg
);
int
get_next
(
char
**
range_info
);
int
get_next
(
char
**
range_info
);
int
refill_buffer
(
bool
initial
)
{
return
initial
?
0
:
HA_ERR_END_OF_FILE
;
}
int
refill_buffer
(
bool
initial
)
{
return
initial
?
0
:
HA_ERR_END_OF_FILE
;
}
uchar
*
get_rowid_ptr
()
{
return
h
->
ref
;
}
uchar
*
get_rowid_ptr
()
{
return
h
->
ref
;
}
...
@@ -247,7 +250,9 @@ class Mrr_ordered_index_reader : public Mrr_index_reader
...
@@ -247,7 +250,9 @@ class Mrr_ordered_index_reader : public Mrr_index_reader
public:
public:
int
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
int
init
(
handler
*
h_arg
,
RANGE_SEQ_IF
*
seq_funcs
,
void
*
seq_init_param
,
uint
n_ranges
,
void
*
seq_init_param
,
uint
n_ranges
,
uint
mode
,
Buffer_manager
*
buf_manager_arg
);
uint
mode
,
Key_parameters
*
key_par
,
Lifo_buffer
*
key_buffer
,
Buffer_manager
*
buf_manager_arg
);
int
get_next
(
char
**
range_info
);
int
get_next
(
char
**
range_info
);
int
refill_buffer
(
bool
initial
);
int
refill_buffer
(
bool
initial
);
uchar
*
get_rowid_ptr
()
{
return
h
->
ref
;
}
uchar
*
get_rowid_ptr
()
{
return
h
->
ref
;
}
...
@@ -278,12 +283,6 @@ private:
...
@@ -278,12 +283,6 @@ private:
/* This manages key buffer allocation and sizing for us */
/* This manages key buffer allocation and sizing for us */
Buffer_manager
*
buf_manager
;
Buffer_manager
*
buf_manager
;
/*
Initially FALSE, becomes TRUE when we saw the first lookup key and set
keypar's member.
*/
bool
know_key_tuple_params
;
Key_parameters
keypar
;
/* index scan and lookup tuple parameters */
Key_parameters
keypar
;
/* index scan and lookup tuple parameters */
/* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */
/* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */
...
@@ -498,7 +497,7 @@ public:
...
@@ -498,7 +497,7 @@ public:
*/
*/
class
DsMrr_impl
:
public
Buffer_manager
class
DsMrr_impl
{
{
public:
public:
typedef
void
(
handler
::*
range_check_toggle_func_t
)(
bool
on
);
typedef
void
(
handler
::*
range_check_toggle_func_t
)(
bool
on
);
...
@@ -582,10 +581,14 @@ private:
...
@@ -582,10 +581,14 @@ private:
uint
*
buffer_size
,
COST_VECT
*
cost
);
uint
*
buffer_size
,
COST_VECT
*
cost
);
bool
check_cpk_scan
(
THD
*
thd
,
uint
keyno
,
uint
mrr_flags
);
bool
check_cpk_scan
(
THD
*
thd
,
uint
keyno
,
uint
mrr_flags
);
/* Buffer_manager implementation */
bool
setup_buffer_sharing
(
uint
key_size_in_keybuf
,
key_part_map
key_tuple_map
);
void
setup_buffer_sizes
(
uint
key_size_in_keybuf
,
key_part_map
key_tuple_map
);
void
redistribute_buffer_space
();
/* Buffer_manager and its member functions */
void
reset_buffer_sizes
();
Buffer_manager
buf_manager
;
static
void
redistribute_buffer_space
(
void
*
dsmrr_arg
);
static
void
reset_buffer_sizes
(
void
*
dsmrr_arg
);
static
void
do_nothing
(
void
*
dsmrr_arg
);
Lifo_buffer
*
get_key_buffer
()
{
return
key_buffer
;
}
Lifo_buffer
*
get_key_buffer
()
{
return
key_buffer
;
}
friend
class
Key_value_records_iterator
;
friend
class
Key_value_records_iterator
;
...
...
sql/opt_range.cc
View file @
017c7518
...
@@ -7449,7 +7449,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
...
@@ -7449,7 +7449,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
uint
*
mrr_flags
,
uint
*
bufsize
,
COST_VECT
*
cost
)
uint
*
mrr_flags
,
uint
*
bufsize
,
COST_VECT
*
cost
)
{
{
SEL_ARG_RANGE_SEQ
seq
;
SEL_ARG_RANGE_SEQ
seq
;
RANGE_SEQ_IF
seq_if
=
{
sel_arg_range_seq_init
,
sel_arg_range_seq_next
,
0
,
0
};
RANGE_SEQ_IF
seq_if
=
{
NULL
,
sel_arg_range_seq_init
,
sel_arg_range_seq_next
,
0
,
0
};
handler
*
file
=
param
->
table
->
file
;
handler
*
file
=
param
->
table
->
file
;
ha_rows
rows
;
ha_rows
rows
;
uint
keynr
=
param
->
real_keynr
[
idx
];
uint
keynr
=
param
->
real_keynr
[
idx
];
...
@@ -8377,7 +8377,7 @@ int QUICK_RANGE_SELECT::reset()
...
@@ -8377,7 +8377,7 @@ int QUICK_RANGE_SELECT::reset()
if
(
!
mrr_buf_desc
)
if
(
!
mrr_buf_desc
)
empty_buf
.
buffer
=
empty_buf
.
buffer_end
=
empty_buf
.
end_of_used_area
=
NULL
;
empty_buf
.
buffer
=
empty_buf
.
buffer_end
=
empty_buf
.
end_of_used_area
=
NULL
;
RANGE_SEQ_IF
seq_funcs
=
{
quick_range_seq_init
,
quick_range_seq_next
,
0
,
0
};
RANGE_SEQ_IF
seq_funcs
=
{
NULL
,
quick_range_seq_init
,
quick_range_seq_next
,
0
,
0
};
error
=
file
->
multi_range_read_init
(
&
seq_funcs
,
(
void
*
)
this
,
ranges
.
elements
,
error
=
file
->
multi_range_read_init
(
&
seq_funcs
,
(
void
*
)
this
,
ranges
.
elements
,
mrr_flags
,
mrr_buf_desc
?
mrr_buf_desc
:
mrr_flags
,
mrr_buf_desc
?
mrr_buf_desc
:
&
empty_buf
);
&
empty_buf
);
...
...
sql/sql_join_cache.cc
View file @
017c7518
...
@@ -3597,6 +3597,16 @@ int JOIN_TAB_SCAN_MRR::next()
...
@@ -3597,6 +3597,16 @@ int JOIN_TAB_SCAN_MRR::next()
}
}
static
void
bka_range_seq_key_info
(
void
*
init_params
,
uint
*
length
,
key_part_map
*
map
)
{
TABLE_REF
*
ref
=
&
(((
JOIN_CACHE
*
)
init_params
)
->
join_tab
->
ref
);
*
length
=
ref
->
key_length
;
*
map
=
(
key_part_map
(
1
)
<<
ref
->
key_parts
)
-
1
;
}
/*
/*
Initialize retrieval of range sequence for BKA join algorithm
Initialize retrieval of range sequence for BKA join algorithm
...
@@ -3876,7 +3886,8 @@ int JOIN_CACHE_BKA::init()
...
@@ -3876,7 +3886,8 @@ int JOIN_CACHE_BKA::init()
int
res
;
int
res
;
bool
check_only_first_match
=
join_tab
->
check_only_first_match
();
bool
check_only_first_match
=
join_tab
->
check_only_first_match
();
RANGE_SEQ_IF
rs_funcs
=
{
bka_range_seq_init
,
RANGE_SEQ_IF
rs_funcs
=
{
bka_range_seq_key_info
,
bka_range_seq_init
,
bka_range_seq_next
,
bka_range_seq_next
,
check_only_first_match
?
check_only_first_match
?
bka_range_seq_skip_record
:
0
,
bka_range_seq_skip_record
:
0
,
...
@@ -4265,7 +4276,8 @@ int JOIN_CACHE_BKAH::init()
...
@@ -4265,7 +4276,8 @@ int JOIN_CACHE_BKAH::init()
no_association
=
test
(
mrr_mode
&
HA_MRR_NO_ASSOCIATION
);
no_association
=
test
(
mrr_mode
&
HA_MRR_NO_ASSOCIATION
);
RANGE_SEQ_IF
rs_funcs
=
{
bkah_range_seq_init
,
RANGE_SEQ_IF
rs_funcs
=
{
bka_range_seq_key_info
,
bkah_range_seq_init
,
bkah_range_seq_next
,
bkah_range_seq_next
,
check_only_first_match
&&
!
no_association
?
check_only_first_match
&&
!
no_association
?
bkah_range_seq_skip_record
:
0
,
bkah_range_seq_skip_record
:
0
,
...
...
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