summaryrefslogtreecommitdiff
path: root/sql/multi_range_read.h
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2011-03-04 00:54:10 +0300
committerSergey Petrunya <psergey@askmonty.org>2011-03-04 00:54:10 +0300
commit8ef094fe4f2b3de93695d4d6f2e3dafa6d012534 (patch)
treebfdd51bb40e16ed8565eced90228f1ce30b0a31a /sql/multi_range_read.h
parentc6ba9598026b06f5d64e7508abb652ac22d50e48 (diff)
downloadmariadb-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.h31
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);