diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2011-03-04 00:54:10 +0300 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2011-03-04 00:54:10 +0300 |
commit | 8ef094fe4f2b3de93695d4d6f2e3dafa6d012534 (patch) | |
tree | bfdd51bb40e16ed8565eced90228f1ce30b0a31a /sql/multi_range_read.h | |
parent | c6ba9598026b06f5d64e7508abb652ac22d50e48 (diff) | |
download | mariadb-git-8ef094fe4f2b3de93695d4d6f2e3dafa6d012534.tar.gz |
BUG#707925: Wrong result with join_cache_level=6 optimizer_use_mrr = force (incremental, BKA join)
- The problem was that Mrr_ordered_index_reader's interrupt_read() and resume_read() would
save and restore 1) index tuple 2) the rowid (as bytes returned by handler->position()). Clustered
primary key columns were not saved/restored.
They are not explicitly present in the index tuple (i.e. table->key_info[secondary_key].key_parts
doesn't list them), but they are actually there, in particular
table->field[clustered_primary_key_member].part_of_key(secondary_key) == 1. Index condition pushdown
code [correctly] uses the latter as inidication that pushed index condition can refer to clustered PK
members.
The fix was to make interrupt_read()/resume_read() to save/restore clustered primary key members as well,
so that we get correct values for them when evaluating pushed index condition.
[3rd attempt: remove the debugging aids, fix comments in testcase]
Diffstat (limited to 'sql/multi_range_read.h')
-rw-r--r-- | sql/multi_range_read.h | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/sql/multi_range_read.h b/sql/multi_range_read.h index fb0cd738855..fe33d2a4093 100644 --- a/sql/multi_range_read.h +++ b/sql/multi_range_read.h @@ -271,7 +271,8 @@ public: mrr_funcs.skip_index_tuple(mrr_iter, range_info)); } - bool set_interruption_temp_buffer(uint rowid_length, uint key_len, + bool set_interruption_temp_buffer(uint rowid_length, uint key_len, + uint saved_pk_len, uchar **space_start, uchar *space_end); void set_no_interruption_temp_buffer(); @@ -300,20 +301,28 @@ private: /* TRUE == reached eof when enumerating ranges */ bool source_exhausted; - - bool support_scan_interruptions; + /* - Space where we save the rowid of the last record we've returned. This is - needed for the cases where index scan is interrupted by some other activity - that destroys contents in file->record[0] (which some storage engines use - to store the last rowid value) - */ + Following members are for interrupt_read()/resume_read(). The idea is that + in some cases index scan that is done by this object is interrupted by + rnd_pos() calls made by Mrr_ordered_rndpos_reader. The problem is that + we're sharing handler->record[0] with that object, and it destroys its + contents. + We need to save/restore our current + - index tuple (for pushed index condition checks) + - clustered primary key values (again, for pushed index condition checks) + - rowid of the last record we've retrieved (in case this rowid matches + multiple ranges and we'll need to return it again) + */ + bool support_scan_interruptions; + /* Space where we save the rowid of the last record we've returned */ uchar *saved_rowid; - + /* TRUE <=> saved_rowid has the last saved rowid */ bool have_saved_rowid; - - uchar *saved_key_tuple; + + uchar *saved_key_tuple; /* Saved current key tuple */ + uchar *saved_primary_key; /* Saved current primary key tuple */ static int compare_keys(void* arg, uchar* key1, uchar* key2); static int compare_keys_reverse(void* arg, uchar* key1, uchar* key2); |