summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMattias Jonsson <mattias.jonsson@oracle.com>2013-10-01 10:05:45 +0200
committerMattias Jonsson <mattias.jonsson@oracle.com>2013-10-01 10:05:45 +0200
commit6ca4be9c03cd8d51b326389eeac6e767a36ec188 (patch)
tree0de3fbb2755f4072b0ebeb0953a7234ef326313d /storage
parent99146a50560a282973615addf47c4287fc226e7f (diff)
downloadmariadb-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.c12
-rw-r--r--storage/innobase/row/row0sel.c24
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;
}