Commit 261268d8 authored by Mattias Jonsson's avatar Mattias Jonsson

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
parent 39a87704
......@@ -6,5 +6,5 @@ HANDLER bug13510739 READ `primary` = (2);
c
HANDLER bug13510739 READ `primary` NEXT;
c
4
3
DROP TABLE bug13510739;
......@@ -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);
}
}
......
......@@ -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 @@ row_search_for_mysql(
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 @@ row_search_for_mysql(
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 @@ row_search_for_mysql(
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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment