Skip to content

Commit 57b6d0d

Browse files
author
Chaithra Gopalareddy
committed
Bug#36775910: Record buffer not set in index range scans
The member, "m_expected_rows" defined as part of the IndexRangeScanIterator is meant to be a "double" but was unintentionally changed to "bool" as part of refactoring done in range optimizer. Because of which, innodb's record buffer setting was affected. We are correcting it in this patch. (No test case added as this might impact performance more than the correctness). When the record buffer was enabled for index range scans a problem arised with multi-valued indexes used for covering index range scans. Note that this is only possible when they are used as part of index merge scans as index merge scans force covering index scans. Problem is that the current implementation of Field_typed_array::key_cmp() needs the value of the generated column for the indexed expression, and this column is not available in the multi-valued index, so the storage engine cannot safely evaluate the end range condition when filling the record buffer when it's a covering scan. So we disable using the record buffer when multi-valued indexes are used for covering index range scans. Change-Id: I889ef0b8b3da7b2234d27d5dd1dc69a8ae8a6557
1 parent 2499b16 commit 57b6d0d

File tree

4 files changed

+37
-29
lines changed

4 files changed

+37
-29
lines changed

sql/range_optimizer/index_range_scan.cc

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,18 @@ IndexRangeScanIterator::IndexRangeScanIterator(
5959
MEM_ROOT *return_mem_root, uint mrr_flags, uint mrr_buf_size,
6060
Bounds_checked_array<QUICK_RANGE *> ranges_arg)
6161
: RowIDCapableRowIterator(thd, table_arg),
62-
ranges(ranges_arg),
63-
free_file(false),
64-
cur_range(nullptr),
65-
last_range(nullptr),
66-
mrr_flags(mrr_flags),
67-
mrr_buf_size(mrr_buf_size),
68-
mrr_buf_desc(nullptr),
69-
need_rows_in_rowid_order(need_rows_in_rowid_order),
70-
reuse_handler(reuse_handler),
71-
mem_root(return_mem_root),
72-
m_expected_rows(expected_rows),
73-
m_examined_rows(examined_rows) {
62+
ranges{ranges_arg},
63+
free_file{false},
64+
cur_range{nullptr},
65+
last_range{nullptr},
66+
mrr_flags{mrr_flags},
67+
mrr_buf_size{mrr_buf_size},
68+
mrr_buf_desc{nullptr},
69+
need_rows_in_rowid_order{need_rows_in_rowid_order},
70+
reuse_handler{reuse_handler},
71+
mem_root{return_mem_root},
72+
m_expected_rows{expected_rows},
73+
m_examined_rows{examined_rows} {
7474
DBUG_TRACE;
7575

7676
in_ror_merged_scan = false;
@@ -232,11 +232,19 @@ bool IndexRangeScanIterator::Init() {
232232
// outside of the record. So don't request a buffer in this case, even
233233
// though the current read_set gives the impression that using a
234234
// record buffer would be fine.
235-
const bool skip_record_buffer =
236-
need_rows_in_rowid_order &&
237-
Overlaps(table()->file->ha_table_flags(),
238-
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION) &&
239-
has_blob_primary_key(table());
235+
bool skip_record_buffer = need_rows_in_rowid_order &&
236+
Overlaps(table()->file->ha_table_flags(),
237+
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION) &&
238+
has_blob_primary_key(table());
239+
// Skip the record buffer for covering multi-valued index range scans.
240+
// The current implementation of Field_typed_array::key_cmp() needs the
241+
// value of the generated column for the indexed expression, and this
242+
// column is not available in the multi-valued index, so the storage
243+
// engine cannot safely evaluate the end range condition when filling the
244+
// record buffer when it's a covering scan.
245+
skip_record_buffer |=
246+
Overlaps(table()->key_info[index].flags, HA_MULTI_VALUED_KEY) &&
247+
table()->key_read;
240248
if (!skip_record_buffer) {
241249
if (set_record_buffer(table(), m_expected_rows)) {
242250
return true; /* purecov: inspected */

sql/range_optimizer/index_range_scan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class IndexRangeScanIterator : public RowIDCapableRowIterator {
9999
private:
100100
MEM_ROOT *mem_root;
101101
bool inited = false;
102-
const bool m_expected_rows;
102+
const double m_expected_rows;
103103
ha_rows *m_examined_rows;
104104

105105
int cmp_next(QUICK_RANGE *range);

sql/range_optimizer/reverse_index_range_scan.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@
3434

3535
ReverseIndexRangeScanIterator::ReverseIndexRangeScanIterator(
3636
THD *thd, TABLE *table, ha_rows *examined_rows, double expected_rows,
37-
int index, MEM_ROOT *return_mem_root, uint mrr_flags,
37+
uint index, MEM_ROOT *return_mem_root, uint mrr_flags,
3838
Bounds_checked_array<QUICK_RANGE *> ranges, bool using_extended_key_parts)
3939
: TableRowIterator(thd, table),
40-
m_index(index),
41-
m_expected_rows(expected_rows),
42-
m_examined_rows(examined_rows),
43-
mem_root(return_mem_root),
44-
m_mrr_flags(mrr_flags),
45-
ranges(ranges),
46-
last_range(nullptr),
47-
m_using_extended_key_parts(using_extended_key_parts) {
40+
m_index{index},
41+
m_expected_rows{expected_rows},
42+
m_examined_rows{examined_rows},
43+
mem_root{return_mem_root},
44+
m_mrr_flags{mrr_flags},
45+
ranges{ranges},
46+
last_range{nullptr},
47+
m_using_extended_key_parts{using_extended_key_parts} {
4848
/*
4949
Use default MRR implementation for reverse scans. No table engine
5050
currently can do an MRR scan with output in reverse index order.

sql/range_optimizer/reverse_index_range_scan.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
class ReverseIndexRangeScanIterator : public TableRowIterator {
4343
public:
4444
ReverseIndexRangeScanIterator(THD *thd, TABLE *table, ha_rows *examined_rows,
45-
double expected_rows, int index,
45+
double expected_rows, uint index,
4646
MEM_ROOT *return_mem_root, uint mrr_flags,
4747
Bounds_checked_array<QUICK_RANGE *> ranges,
4848
bool using_extended_key_parts);
@@ -54,7 +54,7 @@ class ReverseIndexRangeScanIterator : public TableRowIterator {
5454
static range_seq_t quick_range_rev_seq_init(void *init_param, uint, uint);
5555

5656
const uint m_index; /* Index this quick select uses */
57-
ha_rows m_expected_rows;
57+
const double m_expected_rows;
5858
ha_rows *m_examined_rows;
5959

6060
MEM_ROOT *mem_root;

0 commit comments

Comments
 (0)