1 : /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2 :
3 : This program is free software; you can redistribute it and/or modify
4 : it under the terms of the GNU General Public License as published by
5 : the Free Software Foundation; version 2 of the License.
6 :
7 : This program is distributed in the hope that it will be useful,
8 : but WITHOUT ANY WARRANTY; without even the implied warranty of
9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 : GNU General Public License for more details.
11 :
12 : You should have received a copy of the GNU General Public License
13 : along with this program; if not, write to the Free Software
14 : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15 :
16 : #include "maria_def.h"
17 :
18 : /*
19 : Read previous row with the same key as previous read
20 : One may have done a write, update or delete of the previous row.
21 : NOTE! Even if one changes the previous row, the next read is done
22 : based on the position of the last used key!
23 : */
24 :
25 : int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
26 0 : {
27 : int error,changed;
28 : register uint flag;
29 0 : MARIA_SHARE *share= info->s;
30 : MARIA_KEYDEF *keyinfo;
31 0 : DBUG_ENTER("maria_rprev");
32 :
33 0 : if ((inx = _ma_check_index(info,inx)) < 0)
34 0 : DBUG_RETURN(my_errno);
35 0 : flag=SEARCH_SMALLER; /* Read previous */
36 0 : if (info->cur_row.lastpos == HA_OFFSET_ERROR &&
37 : info->update & HA_STATE_NEXT_FOUND)
38 0 : flag=0; /* Read last */
39 :
40 0 : if (fast_ma_readinfo(info))
41 0 : DBUG_RETURN(my_errno);
42 0 : keyinfo= share->keyinfo + inx;
43 0 : changed= _ma_test_if_changed(info);
44 0 : if (share->lock_key_trees)
45 0 : rw_rdlock(&keyinfo->root_lock);
46 0 : if (!flag)
47 0 : error= _ma_search_last(info, keyinfo, share->state.key_root[inx]);
48 0 : else if (!changed)
49 0 : error= _ma_search_next(info, &info->last_key,
50 : flag | info->last_key.flag,
51 : share->state.key_root[inx]);
52 : else
53 0 : error= _ma_search(info, &info->last_key, flag | info->last_key.flag,
54 : share->state.key_root[inx]);
55 :
56 0 : if (!error)
57 : {
58 0 : while (!(*share->row_is_visible)(info))
59 : {
60 : /* Skip rows that are inserted by other threads since we got a lock */
61 0 : if ((error= _ma_search_next(info, &info->last_key,
62 : SEARCH_SMALLER,
63 : share->state.key_root[inx])))
64 0 : break;
65 : }
66 : }
67 0 : if (share->lock_key_trees)
68 0 : rw_unlock(&keyinfo->root_lock);
69 0 : info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
70 0 : info->update|= HA_STATE_PREV_FOUND;
71 0 : if (error)
72 : {
73 0 : if (my_errno == HA_ERR_KEY_NOT_FOUND)
74 0 : my_errno=HA_ERR_END_OF_FILE;
75 : }
76 0 : else if (!buf)
77 : {
78 0 : DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0);
79 : }
80 0 : else if (!(*info->read_record)(info, buf, info->cur_row.lastpos))
81 : {
82 0 : info->update|= HA_STATE_AKTIV; /* Record is read */
83 0 : DBUG_RETURN(0);
84 : }
85 0 : DBUG_RETURN(my_errno);
86 : } /* maria_rprev */
|