146132Smao /*- 261196Sbostic * Copyright (c) 1990, 1993 361196Sbostic * The Regents of the University of California. All rights reserved. 446132Smao * 546132Smao * This code is derived from software contributed to Berkeley by 646132Smao * Mike Olson. 746132Smao * 846132Smao * %sccs.include.redist.c% 946132Smao */ 1046132Smao 1146132Smao #if defined(LIBC_SCCS) && !defined(lint) 12*65050Sbostic static char sccsid[] = "@(#)bt_search.c 8.4 (Berkeley) 12/10/93"; 1346132Smao #endif /* LIBC_SCCS and not lint */ 1446132Smao 1546132Smao #include <sys/types.h> 1656739Sbostic 1750989Sbostic #include <stdio.h> 1856739Sbostic 1957932Sbostic #include <db.h> 2046132Smao #include "btree.h" 2146132Smao 22*65050Sbostic static int bt_snext __P((BTREE *, PAGE *, const DBT *, int *)); 23*65050Sbostic static int bt_sprev __P((BTREE *, PAGE *, const DBT *, int *)); 2465021Sbostic 2546132Smao /* 2650989Sbostic * __BT_SEARCH -- Search a btree for a key. 2746132Smao * 2850989Sbostic * Parameters: 2950989Sbostic * t: tree to search 3050989Sbostic * key: key to find 3150989Sbostic * exactp: pointer to exact match flag 3246132Smao * 3350989Sbostic * Returns: 3464484Sbostic * The EPG for matching record, if any, or the EPG for the location 3564484Sbostic * of the key, if it were inserted into the tree, is entered into 3664484Sbostic * the bt_cur field of the tree. A pointer to the field is returned. 3746132Smao */ 3850989Sbostic EPG * 3950989Sbostic __bt_search(t, key, exactp) 4050989Sbostic BTREE *t; 4150989Sbostic const DBT *key; 4250989Sbostic int *exactp; 4346132Smao { 4465021Sbostic PAGE *h, *n; 4565021Sbostic indx_t index; 4650989Sbostic pgno_t pg; 4765021Sbostic int base, cmp, lim; 4846132Smao 4957449Sbostic BT_CLR(t); 5050989Sbostic for (pg = P_ROOT;;) { 5150989Sbostic if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) 5250989Sbostic return (NULL); 5346132Smao 5450989Sbostic /* Do a binary search on the current page. */ 5564484Sbostic t->bt_cur.page = h; 5650989Sbostic for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) { 5764484Sbostic t->bt_cur.index = index = base + (lim >> 1); 5864484Sbostic if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) { 5950989Sbostic if (h->flags & P_BLEAF) { 6050989Sbostic *exactp = 1; 6164484Sbostic return (&t->bt_cur); 6250989Sbostic } 6350989Sbostic goto next; 6446132Smao } 6550989Sbostic if (cmp > 0) { 6650989Sbostic base = index + 1; 6750989Sbostic --lim; 6846132Smao } 6946132Smao } 7046132Smao 7165021Sbostic /* 7265021Sbostic * If it's a leaf page, and duplicates aren't allowed, we're 73*65050Sbostic * done. If duplicates are allowed, it's possible that there 74*65050Sbostic * were duplicate keys on duplicate pages, and they were later 75*65050Sbostic * deleted, so we could be on a page with no matches while 76*65050Sbostic * there are matches on other pages. If we're at the start or 77*65050Sbostic * end of a page, check on both sides. 7865021Sbostic */ 7950989Sbostic if (h->flags & P_BLEAF) { 8064484Sbostic t->bt_cur.index = base; 8150989Sbostic *exactp = 0; 8265021Sbostic if (!ISSET(t, B_NODUPS)) { 83*65050Sbostic if (base == 0 && 84*65050Sbostic bt_sprev(t, h, key, exactp)) 85*65050Sbostic return (&t->bt_cur); 8665021Sbostic if (base == NEXTINDEX(h) && 87*65050Sbostic bt_snext(t, h, key, exactp)) 88*65050Sbostic return (&t->bt_cur); 8965021Sbostic } 9064484Sbostic return (&t->bt_cur); 9146132Smao } 9246132Smao 9357448Sbostic /* 9457448Sbostic * No match found. Base is the smallest index greater than 9557448Sbostic * key and may be zero or a last + 1 index. If it's non-zero, 9657448Sbostic * decrement by one, and record the internal page which should 9757448Sbostic * be a parent page for the key. If a split later occurs, the 9857448Sbostic * inserted page will be to the right of the saved page. 9957448Sbostic */ 10057448Sbostic index = base ? base - 1 : base; 10157448Sbostic 10251105Sbostic next: if (__bt_push(t, h->pgno, index) == RET_ERROR) 10350989Sbostic return (NULL); 10450989Sbostic pg = GETBINTERNAL(h, index)->pgno; 10550989Sbostic mpool_put(t->bt_mp, h, 0); 10646132Smao } 10746132Smao } 10865021Sbostic 109*65050Sbostic /* 110*65050Sbostic * BT_SNEXT -- Check for an exact match after the key. 111*65050Sbostic * 112*65050Sbostic * Parameters: 113*65050Sbostic * t: tree to search 114*65050Sbostic * h: current page. 115*65050Sbostic * key: key to find 116*65050Sbostic * exactp: pointer to exact match flag 117*65050Sbostic * 118*65050Sbostic * Returns: 119*65050Sbostic * If an exact match found. 120*65050Sbostic */ 121*65050Sbostic static int 12265021Sbostic bt_snext(t, h, key, exactp) 12365021Sbostic BTREE *t; 12465021Sbostic PAGE *h; 12565021Sbostic const DBT *key; 12665021Sbostic int *exactp; 12765021Sbostic { 12865021Sbostic EPG e; 12965021Sbostic PAGE *tp; 13065021Sbostic pgno_t pg; 13165021Sbostic 13265021Sbostic /* Skip until reach the end of the tree or a key. */ 13365021Sbostic for (pg = h->nextpg; pg != P_INVALID;) { 13465021Sbostic if ((tp = mpool_get(t->bt_mp, pg, 0)) == NULL) { 13565021Sbostic mpool_put(t->bt_mp, h, 0); 13665021Sbostic return (NULL); 13765021Sbostic } 13865021Sbostic if (NEXTINDEX(tp) != 0) 13965021Sbostic break; 14065021Sbostic pg = tp->prevpg; 14165021Sbostic mpool_put(t->bt_mp, tp, 0); 14265021Sbostic } 14365021Sbostic /* 14465021Sbostic * The key is either an exact match, or not as good as 14565021Sbostic * the one we already have. 14665021Sbostic */ 14765021Sbostic if (pg != P_INVALID) { 14865021Sbostic e.page = tp; 14965021Sbostic e.index = NEXTINDEX(tp) - 1; 15065021Sbostic if (__bt_cmp(t, key, &e) == 0) { 15165021Sbostic mpool_put(t->bt_mp, h, 0); 15265021Sbostic t->bt_cur = e; 15365021Sbostic *exactp = 1; 154*65050Sbostic return (1); 15565021Sbostic } 15665021Sbostic } 157*65050Sbostic return (0); 15865021Sbostic } 15965021Sbostic 160*65050Sbostic /* 161*65050Sbostic * BT_SPREV -- Check for an exact match before the key. 162*65050Sbostic * 163*65050Sbostic * Parameters: 164*65050Sbostic * t: tree to search 165*65050Sbostic * h: current page. 166*65050Sbostic * key: key to find 167*65050Sbostic * exactp: pointer to exact match flag 168*65050Sbostic * 169*65050Sbostic * Returns: 170*65050Sbostic * If an exact match found. 171*65050Sbostic */ 172*65050Sbostic static int 17365021Sbostic bt_sprev(t, h, key, exactp) 17465021Sbostic BTREE *t; 17565021Sbostic PAGE *h; 17665021Sbostic const DBT *key; 17765021Sbostic int *exactp; 17865021Sbostic { 17965021Sbostic EPG e; 18065021Sbostic PAGE *tp; 18165021Sbostic pgno_t pg; 18265021Sbostic 18365021Sbostic /* Skip until reach the beginning of the tree or a key. */ 18465021Sbostic for (pg = h->prevpg; pg != P_INVALID;) { 18565021Sbostic if ((tp = mpool_get(t->bt_mp, pg, 0)) == NULL) { 18665021Sbostic mpool_put(t->bt_mp, h, 0); 18765021Sbostic return (NULL); 18865021Sbostic } 18965021Sbostic if (NEXTINDEX(tp) != 0) 19065021Sbostic break; 19165021Sbostic pg = tp->prevpg; 19265021Sbostic mpool_put(t->bt_mp, tp, 0); 19365021Sbostic } 19465021Sbostic /* 19565021Sbostic * The key is either an exact match, or not as good as 19665021Sbostic * the one we already have. 19765021Sbostic */ 19865021Sbostic if (pg != P_INVALID) { 19965021Sbostic e.page = tp; 20065021Sbostic e.index = NEXTINDEX(tp) - 1; 20165021Sbostic if (__bt_cmp(t, key, &e) == 0) { 20265021Sbostic mpool_put(t->bt_mp, h, 0); 20365021Sbostic t->bt_cur = e; 20465021Sbostic *exactp = 1; 205*65050Sbostic return (1); 20665021Sbostic } 20765021Sbostic } 208*65050Sbostic return (0); 20965021Sbostic } 210