diff options
Diffstat (limited to 'storage/myisam/mi_rkey.c')
-rw-r--r-- | storage/myisam/mi_rkey.c | 92 |
1 files changed, 50 insertions, 42 deletions
diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c index f20b0366683..47e2ce51a9e 100644 --- a/storage/myisam/mi_rkey.c +++ b/storage/myisam/mi_rkey.c @@ -29,6 +29,7 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, MI_KEYDEF *keyinfo; HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; + int res= 0; DBUG_ENTER("mi_rkey"); DBUG_PRINT("enter", ("base: 0x%lx buf: 0x%lx inx: %d search_flag: %d", (long) info, (long) buf, inx, search_flag)); @@ -105,55 +106,62 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, saved the current data_file_length. Concurrent inserts always go to the end of the file. So we can test if the found key references a new record. + + If we are searching for a partial key (or using >, >=, < or <=) and + the data is outside of the data file, we need to continue searching + for the first key inside the data file. + + We do also continue searching if an index condition check function + is available. */ - if (info->lastpos >= info->state->data_file_length) + while ((info->lastpos >= info->state->data_file_length && + (search_flag != HA_READ_KEY_EXACT || + last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) || + (info->index_cond_func && + !(res= mi_check_index_cond(info, inx, buf)))) { - /* The key references a concurrently inserted record. */ + uint not_used[2]; + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + /* + Check that the found key does still match the search. + _mi_search_next() delivers the next key regardless of its + value. + */ if (search_flag == HA_READ_KEY_EXACT && - last_used_keyseg == keyinfo->seg + keyinfo->keysegs) + ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, not_used)) { - /* Simply ignore the key if it matches exactly. (Bug #29838) */ my_errno= HA_ERR_KEY_NOT_FOUND; info->lastpos= HA_OFFSET_ERROR; + break; } - else - { - /* - If searching for a partial key (or using >, >=, < or <=) and - the data is outside of the data file, we need to continue - searching for the first key inside the data file. - */ - do - { - uint not_used[2]; - /* - Skip rows that are inserted by other threads since we got - a lock. Note that this can only happen if we are not - searching after a full length exact key, because the keys - are sorted according to position. - */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; /* purecov: inspected */ - /* - Check that the found key does still match the search. - _mi_search_next() delivers the next key regardless of its - value. - */ - if (search_flag == HA_READ_KEY_EXACT && - ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, - use_key_length, SEARCH_FIND, not_used)) - { - /* purecov: begin inspected */ - my_errno= HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; - break; - /* purecov: end */ - } - } while (info->lastpos >= info->state->data_file_length); - } + } + if (res == 2) + { + info->lastpos= HA_OFFSET_ERROR; + if (share->concurrent_insert) + rw_unlock(&share->key_root_lock[inx]); + DBUG_RETURN((my_errno= HA_ERR_KEY_NOT_FOUND)); + } + /* + Error if no row found within the data file. (Bug #29838) + Do not overwrite my_errno if already at HA_OFFSET_ERROR. + */ + if (info->lastpos != HA_OFFSET_ERROR && + info->lastpos >= info->state->data_file_length) + { + info->lastpos= HA_OFFSET_ERROR; + my_errno= HA_ERR_KEY_NOT_FOUND; } } } |