2 * Copyright (c) 1990 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid
[] = "@(#)seq.c 5.4 (Berkeley) 3/3/91";
39 #endif /* LIBC_SCCS and not lint */
41 #include <sys/types.h>
48 * _BT_SEQINIT -- Initialize a sequential scan on the btree.
50 * Sets the tree's notion of the current scan location correctly
51 * given a key and a direction.
54 * t -- tree in which to initialize scan
55 * key -- key for initial scan position
56 * flags -- R_NEXT, R_PREV
59 * RET_SUCCESS, RET_ERROR, or RET_SPECIAL if there's no data
60 * in the tree to scan.
63 * Changes current scan position for the tree. Almost certainly
64 * changes current page, as well. Sets BTF_SEQINIT bit in tree
65 * flags, so that we know we've initialized a scan.
69 _bt_seqinit(t
, key
, flags
)
81 * Figure out if we really have to search for the key that the
82 * user supplied. If key is null, then this is an unkeyed scan
83 * and we can just start from an endpoint.
88 if (flags
== R_CURSOR
) {
89 if (key
->data
!= (u_char
*) NULL
) {
91 /* key supplied, find first instance of it */
92 item
= _bt_first(t
, key
);
93 c
->c_index
= item
->bti_index
;
94 c
->c_pgno
= t
->bt_curpage
->h_pgno
;
103 * Unkeyed scan. For backward scans, find the last item
104 * in the tree; for forward scans, find the first item.
107 if (_bt_getpage(t
, (pgno_t
) P_ROOT
) == RET_ERROR
)
110 if (flags
== R_LAST
|| flags
== R_PREV
) {
113 while (!(h
->h_flags
& F_LEAF
)) {
114 last
= NEXTINDEX(h
) - 1;
115 id
= (IDATUM
*) GETDATUM(h
,last
);
116 if (_bt_getpage(t
, id
->i_pgno
) == RET_ERROR
)
121 /* skip empty pages */
122 while (NEXTINDEX(h
) == 0 && h
->h_prevpg
!= P_NONE
) {
123 if (_bt_getpage(t
, h
->h_prevpg
) == RET_ERROR
)
128 c
->c_pgno
= h
->h_pgno
;
129 if (NEXTINDEX(h
) > 0)
130 c
->c_index
= NEXTINDEX(h
) - 1;
133 } else if (flags
== R_FIRST
|| flags
== R_NEXT
) {
135 while (!(h
->h_flags
& F_LEAF
)) {
136 id
= (IDATUM
*) GETDATUM(h
,0);
137 if (_bt_getpage(t
, id
->i_pgno
) == RET_ERROR
)
142 /* skip empty pages */
143 while (NEXTINDEX(h
) == 0 && h
->h_nextpg
!= P_NONE
) {
144 if (_bt_getpage(t
, h
->h_nextpg
) == RET_ERROR
)
149 c
->c_pgno
= h
->h_pgno
;
152 /* no flags passed in */
158 /* okay, scan is initialized */
159 t
->bt_flags
|= BTF_SEQINIT
;
161 /* don't need the descent stack anymore */
162 while (_bt_pop(t
) != P_NONE
)
165 if (c
->c_index
== NEXTINDEX(t
->bt_curpage
))
166 return (RET_SPECIAL
);
168 return (RET_SUCCESS
);
172 * _BT_SEQADVANCE -- Advance the sequential scan on this tree.
174 * Moves the current location pointer for the scan on this tree one
175 * spot in the requested direction.
178 * t -- btree being scanned
179 * flags -- for R_NEXT, R_PREV
182 * RET_SUCCESS, RET_ERROR, or RET_SPECIAL if there is no
183 * more data in the specified direction.
186 * May change current page.
190 _bt_seqadvance(t
, flags
)
201 if (_bt_getpage(t
, c
->c_pgno
) == RET_ERROR
)
205 /* by the time we get here, don't need the cursor key anymore */
206 if (c
->c_key
!= (char *) NULL
)
207 (void) free(c
->c_key
);
209 if (flags
== R_NEXT
) {
212 * This is a forward scan. If the cursor is pointing
213 * at a virtual record (that is, it was pointing at
214 * a record that got deleted), then we should return
215 * the record it's pointing at now. Otherwise, we
216 * should advance the scan. In either case, we need
217 * to be careful not to run off the end of the current
221 if (c
->c_flags
& CRSR_BEFORE
) {
223 if (index
>= NEXTINDEX(h
)) {
224 /* out of items on this page, get next page */
225 if (h
->h_nextpg
== P_NONE
) {
226 /* tell caller we're done... */
227 c
->c_index
= NEXTINDEX(h
);
228 return (RET_SPECIAL
);
231 /* skip empty pages */
233 if (_bt_getpage(t
, h
->h_nextpg
)
235 c
->c_index
= NEXTINDEX(h
);
239 c
->c_pgno
= h
->h_pgno
;
240 } while (NEXTINDEX(h
) == 0
241 && h
->h_nextpg
!= P_NONE
);
243 if (NEXTINDEX(h
) == 0) {
244 /* tell caller we're done */
245 c
->c_index
= NEXTINDEX(h
);
246 return (RET_SPECIAL
);
250 c
->c_flags
&= ~CRSR_BEFORE
;
252 } else if (++index
>= NEXTINDEX(h
)) {
254 /* out of items on this page, get next page */
255 if (h
->h_nextpg
== P_NONE
) {
256 /* tell caller we're done... */
257 c
->c_index
= NEXTINDEX(h
);
258 return (RET_SPECIAL
);
261 /* skip empty pages */
263 if (_bt_getpage(t
, h
->h_nextpg
) == RET_ERROR
) {
264 c
->c_index
= NEXTINDEX(h
);
268 c
->c_pgno
= h
->h_pgno
;
269 } while (NEXTINDEX(h
) == 0 && h
->h_nextpg
!= P_NONE
);
271 if (NEXTINDEX(h
) == 0) {
272 /* tell caller we're done */
273 c
->c_index
= NEXTINDEX(h
);
274 return (RET_SPECIAL
);
278 } else if (flags
== R_PREV
) {
280 /* for backward scans, life is substantially easier */
281 c
->c_flags
&= ~CRSR_BEFORE
;
282 if (c
->c_key
!= (char *) NULL
) {
283 (void) free(c
->c_key
);
284 c
->c_key
= (char *) NULL
;
292 /* out of items on this page, get next page */
293 if (h
->h_prevpg
== P_NONE
)
294 return (RET_SPECIAL
);
296 /* skip empty pages */
298 if (_bt_getpage(t
, h
->h_prevpg
) == RET_ERROR
)
301 c
->c_pgno
= h
->h_pgno
;
302 } while (NEXTINDEX(h
) == 0 && h
->h_prevpg
!= P_NONE
);
304 if (NEXTINDEX(h
) == 0)
305 return (RET_SPECIAL
);
307 index
= NEXTINDEX(h
) - 1;
311 /* must specify a direction */
317 return (RET_SUCCESS
);