int heap_scan(register HP_INFO *info, uchar *record) { HP_SHARE *share=info->s; ulong pos; DBUG_ENTER("heap_scan"); pos= ++info->current_record; if (pos >= share->recordspace.chunk_count) { info->update= 0; DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); } hp_find_record(info, pos); if (get_chunk_status(&share->recordspace, info->current_ptr) != CHUNK_STATUS_ACTIVE) { DBUG_PRINT("warning",("Found deleted record or secondary chunk")); info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND; DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); } info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV; if (hp_extract_record(info, record, info->current_ptr)) { DBUG_RETURN(my_errno); } info->current_hash_ptr=0; /* Can't use read_next */ DBUG_RETURN(0); } /* heap_scan */
int heap_rlast(HP_INFO *info, uchar *record, int inx) { HP_SHARE *share= info->s; HP_KEYDEF *keyinfo= share->keydef + inx; DBUG_ENTER("heap_rlast"); info->lastinx= inx; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) { uchar *pos; if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents, &info->last_pos, offsetof(TREE_ELEMENT, right)))) { memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), sizeof(uchar*)); info->current_ptr = pos; if (hp_extract_record(info, record, pos)) { DBUG_RETURN(my_errno); } info->update = HA_STATE_AKTIV; } else { my_errno = HA_ERR_END_OF_FILE; DBUG_RETURN(my_errno); } DBUG_RETURN(0); } else { info->current_ptr=0; info->current_hash_ptr=0; info->update=HA_STATE_NEXT_FOUND; DBUG_RETURN(heap_rprev(info,record)); } }
int heap_rsame(register HP_INFO *info, uchar *record, int inx) { HP_SHARE *share=info->s; DBUG_ENTER("heap_rsame"); test_active(info); if (get_chunk_status(&share->recordspace, info->current_ptr) == CHUNK_STATUS_ACTIVE) { if (inx < -1 || inx >= (int) share->keys) { DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); } else if (inx != -1) { info->lastinx=inx; hp_make_key(share->keydef + inx, info->lastkey, record); if (!hp_search(info, share->keydef + inx, info->lastkey, 3)) { info->update=0; DBUG_RETURN(my_errno); } } if (hp_extract_record(info, record, info->current_ptr)) { DBUG_RETURN(my_errno); } DBUG_RETURN(0); } /* treat deleted and linked chunks as deleted */ info->update=0; DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED); }
int heap_rprev(HP_INFO *info, uchar *record) { uchar *pos; HP_SHARE *share=info->s; HP_KEYDEF *keyinfo; DBUG_ENTER("heap_rprev"); if (info->lastinx < 0) DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); keyinfo = share->keydef + info->lastinx; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) { heap_rb_param custom_arg; if (info->last_pos) pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos, offsetof(TREE_ELEMENT, right), offsetof(TREE_ELEMENT, left)); else { custom_arg.keyseg = keyinfo->seg; custom_arg.key_length = keyinfo->length; custom_arg.search_flag = SEARCH_SAME; pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents, &info->last_pos, info->last_find_flag, &custom_arg); } if (pos) { memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), sizeof(uchar*)); info->current_ptr = pos; } else { my_errno = HA_ERR_KEY_NOT_FOUND; } } else { if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND)) { if ((info->update & HA_STATE_DELETED)) pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 3); else pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 2); } else { pos=0; /* Read next after last */ my_errno=HA_ERR_KEY_NOT_FOUND; } } if (!pos) { info->update=HA_STATE_PREV_FOUND; /* For heap_rprev */ if (my_errno == HA_ERR_KEY_NOT_FOUND) my_errno=HA_ERR_END_OF_FILE; DBUG_RETURN(my_errno); } if (hp_extract_record(info, record, pos)) { DBUG_RETURN(my_errno); } info->update=HA_STATE_AKTIV | HA_STATE_PREV_FOUND; DBUG_RETURN(0); }
int heap_rnext(HP_INFO *info, uchar *record) { uchar *pos; HP_SHARE *share=info->s; HP_KEYDEF *keyinfo; DBUG_ENTER("heap_rnext"); if (info->lastinx < 0) DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); keyinfo = share->keydef + info->lastinx; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) { heap_rb_param custom_arg; if (info->last_pos) { /* We enter this branch for non-DELETE queries after heap_rkey() or heap_rfirst(). As last key position (info->last_pos) is available, we only need to climb the tree using tree_search_next(). */ pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos, offsetof(TREE_ELEMENT, left), offsetof(TREE_ELEMENT, right)); } else if (!info->lastkey_len) { /* We enter this branch only for DELETE queries after heap_rfirst(). E.g. DELETE FROM t1 WHERE a<10. As last key position is not available (last key is removed by heap_delete()), we must restart search as it is done in heap_rfirst(). It should be safe to handle this situation without this branch. That is branch below should find smallest element in a tree as lastkey_len is zero. tree_search_edge() is a kind of optimisation here as it should be faster than tree_search_key(). */ pos= tree_search_edge(&keyinfo->rb_tree, info->parents, &info->last_pos, offsetof(TREE_ELEMENT, left)); } else { /* We enter this branch only for DELETE queries after heap_rkey(). E.g. DELETE FROM t1 WHERE a=10. As last key position is not available (last key is removed by heap_delete()), we must restart search as it is done in heap_rkey(). */ custom_arg.keyseg = keyinfo->seg; custom_arg.key_length = info->lastkey_len; custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND; pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents, &info->last_pos, info->last_find_flag, &custom_arg); } if (pos) { memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos), sizeof(uchar*)); info->current_ptr = pos; } else { my_errno = HA_ERR_KEY_NOT_FOUND; } } else { if (info->current_hash_ptr) pos= hp_search_next(info, keyinfo, info->lastkey, info->current_hash_ptr); else { if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND)) { pos=0; /* Read next after last */ my_errno=HA_ERR_KEY_NOT_FOUND; } else if (!info->current_ptr) /* Deleted or first call */ pos= hp_search(info, keyinfo, info->lastkey, 0); else pos= hp_search(info, keyinfo, info->lastkey, 1); } } if (!pos) { info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */ if (my_errno == HA_ERR_KEY_NOT_FOUND) my_errno=HA_ERR_END_OF_FILE; DBUG_RETURN(my_errno); } if (hp_extract_record(info, record, pos)) { DBUG_RETURN(my_errno); } info->update=HA_STATE_AKTIV | HA_STATE_NEXT_FOUND; DBUG_RETURN(0); }