mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
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
This commit is contained in:
@@ -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 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user