diff options
author | Mattias Jonsson <mattias.jonsson@oracle.com> | 2013-10-01 10:05:45 +0200 |
---|---|---|
committer | Mattias Jonsson <mattias.jonsson@oracle.com> | 2013-10-01 10:05:45 +0200 |
commit | 6ca4be9c03cd8d51b326389eeac6e767a36ec188 (patch) | |
tree | 0de3fbb2755f4072b0ebeb0953a7234ef326313d /storage | |
parent | 99146a50560a282973615addf47c4287fc226e7f (diff) | |
download | mariadb-git-6ca4be9c03cd8d51b326389eeac6e767a36ec188.tar.gz |
Bug#14621190: HA_INNOBASE::INDEX_NEXT SKIPS A RECORD IF PREVIOUS
INDEX_READ_MAP HAD NO MATCH
If index_read_map is called for exact search and no matching records
exists it will position the cursor on the next record, but still having the
relative position to BTR_PCUR_ON.
This will make a call for index_next to read yet another next record,
instead of returning the record the cursor points to.
Fixed by setting pcur->rel_pos = BTR_PCUR_BEFORE if an exact
[prefix] search is done, but failed.
Also avoids optimistic restoration if rel_pos != BTR_PCUR_ON,
since btr_cur may be different than old_rec.
rb#3324, approved by Marko and Jimmy
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/btr/btr0pcur.c | 12 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.c | 24 |
2 files changed, 30 insertions, 6 deletions
diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 0cfdf138bad..fbedc1e7d04 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -273,13 +273,15 @@ btr_pcur_restore_position_func( if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF) || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) { - /* Try optimistic restoration */ + /* Try optimistic restoration if cursor is expected to be + positioned on the same btr record as before (BTR_PCUR_ON). */ - if (UNIV_LIKELY(buf_page_optimistic_get( + if (cursor->rel_pos == BTR_PCUR_ON + && buf_page_optimistic_get( latch_mode, cursor->block_when_stored, cursor->modify_clock, - file, line, mtr))) { + file, line, mtr)) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; buf_block_dbg_add_level( @@ -287,7 +289,7 @@ btr_pcur_restore_position_func( dict_index_is_ibuf(index) ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); - if (cursor->rel_pos == BTR_PCUR_ON) { + { #ifdef UNIV_DEBUG const rec_t* rec; const ulint* offsets1; @@ -312,8 +314,6 @@ btr_pcur_restore_position_func( #endif /* UNIV_DEBUG */ return(TRUE); } - - return(FALSE); } } diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 518eba975ab..28da1f69e8a 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -3116,6 +3116,13 @@ sel_restore_position_for_mysql( return(TRUE); } + /* success can only be TRUE for BTR_PCUR_ON! */ + ut_ad(!success); + + /* BTR_PCUR_BEFORE -> the position is now set to the record before + pcur->old_rec. + BTR_PCUR_AFTER-> positioned to record after pcur->old_rec. */ + if (relative_position == BTR_PCUR_AFTER || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE) { @@ -4120,6 +4127,14 @@ wrong_offs: btr_pcur_store_position(pcur, &mtr); + /* The found record was not a match, but may be used + as NEXT record (index_next). Set the relative position + to BTR_PCUR_BEFORE, to reflect that the position of + the persistent cursor is before the found/stored row + (pcur->old_rec). */ + ut_ad(pcur->rel_pos == BTR_PCUR_ON); + pcur->rel_pos = BTR_PCUR_BEFORE; + err = DB_RECORD_NOT_FOUND; /* ut_print_name(stderr, index->name); fputs(" record not found 3\n", stderr); */ @@ -4159,6 +4174,14 @@ wrong_offs: btr_pcur_store_position(pcur, &mtr); + /* The found record was not a match, but may be used + as NEXT record (index_next). Set the relative position + to BTR_PCUR_BEFORE, to reflect that the position of + the persistent cursor is before the found/stored row + (pcur->old_rec). */ + ut_ad(pcur->rel_pos == BTR_PCUR_ON); + pcur->rel_pos = BTR_PCUR_BEFORE; + err = DB_RECORD_NOT_FOUND; /* ut_print_name(stderr, index->name); fputs(" record not found 4\n", stderr); */ @@ -4736,6 +4759,7 @@ normal_return: if (prebuilt->n_fetch_cached > 0) { row_sel_pop_cached_row_for_mysql(buf, prebuilt); + DEBUG_SYNC_C("row_search_cached_row"); err = DB_SUCCESS; } |