diff options
Diffstat (limited to 'myisam/mi_rkey.c')
-rw-r--r-- | myisam/mi_rkey.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 4a3c76809e8..ddfac0a39a2 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -23,10 +23,12 @@ /* Ordinary search_flag is 0 ; Give error if no record with key */ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, - enum ha_rkey_function search_flag) + enum ha_rkey_function search_flag) { uchar *key_buff; MYISAM_SHARE *share=info->s; + MI_KEYDEF *keyinfo; + HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("mi_rkey"); DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d", @@ -36,25 +38,29 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, DBUG_RETURN(my_errno); info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - info->last_key_func=search_flag; + info->last_key_func= search_flag; + keyinfo= share->keyinfo + inx; if (info->once_flags & USE_PACKED_KEYS) { - /* key is already packed! */ + info->once_flags&= ~USE_PACKED_KEYS; /* Reset flag */ + /* + key is already packed!; This happens when we are using a MERGE TABLE + */ key_buff=info->lastkey+info->s->base.max_key_length; - info->last_rkey_length=pack_key_length=key_len; + pack_key_length= key_len; bmove(key_buff,key,key_len); - info->once_flags&= ~USE_PACKED_KEYS; + last_used_keyseg= 0; } else { if (key_len == 0) key_len=USE_WHOLE_KEY; key_buff=info->lastkey+info->s->base.max_key_length; - pack_key_length=_mi_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len); - info->last_rkey_length=pack_key_length; - DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg, - key_buff,pack_key_length);); + pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key, + key_len, &last_used_keyseg); + DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, + key_buff, pack_key_length);); } if (fast_mi_readinfo(info)) @@ -67,9 +73,9 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) use_key_length=USE_WHOLE_KEY; - switch(info->s->keyinfo[inx].key_alg){ + switch (info->s->keyinfo[inx].key_alg) { case HA_KEY_ALG_RTREE: - if(rtree_find_first(info,inx,key_buff,use_key_length,nextflag)<0) + if (rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0) { my_errno=HA_ERR_CRASHED; goto err; @@ -77,8 +83,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, break; case HA_KEY_ALG_BTREE: default: - if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length, - myisam_read_vec[search_flag],info->s->state.key_root[inx])) + if (!_mi_search(info, keyinfo, key_buff, use_key_length, + myisam_read_vec[search_flag], info->s->state.key_root[inx])) { while (info->lastpos >= info->state->data_file_length) { @@ -88,7 +94,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, exact key, because the keys are sorted according to position */ - if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey, + if (_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length, myisam_readnext_vec[search_flag], info->s->state.key_root[inx])) @@ -99,8 +105,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); + /* Calculate length of the found key; Used by mi_rnext_same */ + if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg && + info->lastpos != HA_OFFSET_ERROR) + info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey, + last_used_keyseg); + else + info->last_rkey_length= pack_key_length; + + /* Check if we don't want to have record back, only error message */ if (!buf) - DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); + DBUG_RETURN(info->lastpos == HA_OFFSET_ERROR ? my_errno : 0); if (!(*info->read_record)(info,info->lastpos,buf)) { @@ -110,8 +125,9 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, info->lastpos = HA_OFFSET_ERROR; /* Didn't find key */ - /* Store key for read next */ + /* Store last used key as a base for read next */ memcpy(info->lastkey,key_buff,pack_key_length); + info->last_rkey_length= pack_key_length; bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength); info->lastkey_length=pack_key_length+info->s->base.rec_reflength; |