1 | /* Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc. |
2 | Use is subject to license terms. |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
16 | |
17 | #include "myisamdef.h" |
18 | #include "rt_index.h" |
19 | |
20 | /* |
21 | Read next row with the same key as previous read, but abort if |
22 | the key changes. |
23 | One may have done a write, update or delete of the previous row. |
24 | NOTE! Even if one changes the previous row, the next read is done |
25 | based on the position of the last used key! |
26 | */ |
27 | |
28 | int mi_rnext_same(MI_INFO *info, uchar *buf) |
29 | { |
30 | int error; |
31 | uint inx,not_used[2]; |
32 | MI_KEYDEF *keyinfo; |
33 | ICP_RESULT icp_res= ICP_MATCH; |
34 | DBUG_ENTER("mi_rnext_same" ); |
35 | |
36 | if ((int) (inx=info->lastinx) < 0 || info->lastpos == HA_OFFSET_ERROR) |
37 | DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); |
38 | keyinfo=info->s->keyinfo+inx; |
39 | if (fast_mi_readinfo(info)) |
40 | DBUG_RETURN(my_errno); |
41 | |
42 | if (info->s->concurrent_insert) |
43 | mysql_rwlock_rdlock(&info->s->key_root_lock[inx]); |
44 | |
45 | switch (keyinfo->key_alg) |
46 | { |
47 | #ifdef HAVE_RTREE_KEYS |
48 | case HA_KEY_ALG_RTREE: |
49 | if ((error=rtree_find_next(info,inx, |
50 | myisam_read_vec[info->last_key_func]))) |
51 | { |
52 | error=1; |
53 | my_errno=HA_ERR_END_OF_FILE; |
54 | info->lastpos= HA_OFFSET_ERROR; |
55 | break; |
56 | } |
57 | break; |
58 | #endif |
59 | case HA_KEY_ALG_BTREE: |
60 | default: |
61 | if (!(info->update & HA_STATE_RNEXT_SAME)) |
62 | { |
63 | /* First rnext_same; Store old key */ |
64 | memcpy(info->lastkey2,info->lastkey,info->last_rkey_length); |
65 | } |
66 | for (;;) |
67 | { |
68 | /* |
69 | If we are at the last key on the key page, allow writers to |
70 | access the index. |
71 | */ |
72 | if (info->int_keypos >= info->int_maxpos && |
73 | mi_yield_and_check_if_killed(info, inx)) |
74 | { |
75 | error=1; |
76 | break; |
77 | } |
78 | |
79 | if ((error=_mi_search_next(info,keyinfo,info->lastkey, |
80 | info->lastkey_length,SEARCH_BIGGER, |
81 | info->s->state.key_root[inx]))) |
82 | break; |
83 | if (ha_key_cmp(keyinfo->seg, info->lastkey, info->lastkey2, |
84 | info->last_rkey_length, SEARCH_FIND, not_used)) |
85 | { |
86 | error=1; |
87 | my_errno=HA_ERR_END_OF_FILE; |
88 | info->lastpos= HA_OFFSET_ERROR; |
89 | break; |
90 | } |
91 | /* |
92 | Skip |
93 | - rows that are inserted by other threads since we got a lock |
94 | - rows that don't match index condition |
95 | */ |
96 | if (info->lastpos < info->state->data_file_length && |
97 | (!info->index_cond_func || |
98 | (icp_res= mi_check_index_cond(info, inx, buf)) != ICP_NO_MATCH)) |
99 | break; |
100 | } |
101 | } |
102 | if (info->s->concurrent_insert) |
103 | mysql_rwlock_unlock(&info->s->key_root_lock[inx]); |
104 | |
105 | |
106 | /* Don't clear if database-changed */ |
107 | info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); |
108 | info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME; |
109 | |
110 | if (error || icp_res != ICP_MATCH) |
111 | { |
112 | fast_mi_writeinfo(info); |
113 | if (my_errno == HA_ERR_KEY_NOT_FOUND) |
114 | my_errno=HA_ERR_END_OF_FILE; |
115 | } |
116 | else if (!buf) |
117 | { |
118 | fast_mi_writeinfo(info); |
119 | DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); |
120 | } |
121 | else if (!(*info->read_record)(info,info->lastpos,buf)) |
122 | { |
123 | info->update|= HA_STATE_AKTIV; /* Record is read */ |
124 | DBUG_RETURN(0); |
125 | } |
126 | DBUG_RETURN(my_errno); |
127 | } /* mi_rnext_same */ |
128 | |