summaryrefslogtreecommitdiff
path: root/lib/libc/db/btree/bt_search.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/db/btree/bt_search.c')
-rw-r--r--lib/libc/db/btree/bt_search.c152
1 files changed, 134 insertions, 18 deletions
diff --git a/lib/libc/db/btree/bt_search.c b/lib/libc/db/btree/bt_search.c
index 06aba1126bda8..a164173d01738 100644
--- a/lib/libc/db/btree/bt_search.c
+++ b/lib/libc/db/btree/bt_search.c
@@ -35,7 +35,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_search.c 8.1 (Berkeley) 6/4/93";
+static char sccsid[] = "@(#)bt_search.c 8.4 (Berkeley) 12/10/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -45,6 +45,9 @@ static char sccsid[] = "@(#)bt_search.c 8.1 (Berkeley) 6/4/93";
#include <db.h>
#include "btree.h"
+static int bt_snext __P((BTREE *, PAGE *, const DBT *, int *));
+static int bt_sprev __P((BTREE *, PAGE *, const DBT *, int *));
+
/*
* __BT_SEARCH -- Search a btree for a key.
*
@@ -54,12 +57,9 @@ static char sccsid[] = "@(#)bt_search.c 8.1 (Berkeley) 6/4/93";
* exactp: pointer to exact match flag
*
* Returns:
- * EPG for matching record, if any, or the EPG for the location of the
- * key, if it were inserted into the tree.
- *
- * Warnings:
- * The EPG returned is in static memory, and will be overwritten by the
- * next search of any kind in any tree.
+ * The EPG for matching record, if any, or the EPG for the location
+ * of the key, if it were inserted into the tree, is entered into
+ * the bt_cur field of the tree. A pointer to the field is returned.
*/
EPG *
__bt_search(t, key, exactp)
@@ -67,11 +67,10 @@ __bt_search(t, key, exactp)
const DBT *key;
int *exactp;
{
- register indx_t index;
- register int base, cmp, lim;
- register PAGE *h;
+ PAGE *h, *n;
+ indx_t index;
pgno_t pg;
- static EPG e;
+ int base, cmp, lim;
BT_CLR(t);
for (pg = P_ROOT;;) {
@@ -79,13 +78,13 @@ __bt_search(t, key, exactp)
return (NULL);
/* Do a binary search on the current page. */
- e.page = h;
+ t->bt_cur.page = h;
for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
- e.index = index = base + (lim >> 1);
- if ((cmp = __bt_cmp(t, key, &e)) == 0) {
+ t->bt_cur.index = index = base + (lim >> 1);
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
if (h->flags & P_BLEAF) {
*exactp = 1;
- return (&e);
+ return (&t->bt_cur);
}
goto next;
}
@@ -95,11 +94,26 @@ __bt_search(t, key, exactp)
}
}
- /* If it's a leaf page, we're done. */
+ /*
+ * If it's a leaf page, and duplicates aren't allowed, we're
+ * done. If duplicates are allowed, it's possible that there
+ * were duplicate keys on duplicate pages, and they were later
+ * deleted, so we could be on a page with no matches while
+ * there are matches on other pages. If we're at the start or
+ * end of a page, check on both sides.
+ */
if (h->flags & P_BLEAF) {
- e.index = base;
+ t->bt_cur.index = base;
*exactp = 0;
- return (&e);
+ if (!ISSET(t, B_NODUPS)) {
+ if (base == 0 &&
+ bt_sprev(t, h, key, exactp))
+ return (&t->bt_cur);
+ if (base == NEXTINDEX(h) &&
+ bt_snext(t, h, key, exactp))
+ return (&t->bt_cur);
+ }
+ return (&t->bt_cur);
}
/*
@@ -117,3 +131,105 @@ next: if (__bt_push(t, h->pgno, index) == RET_ERROR)
mpool_put(t->bt_mp, h, 0);
}
}
+
+/*
+ * BT_SNEXT -- Check for an exact match after the key.
+ *
+ * Parameters:
+ * t: tree to search
+ * h: current page.
+ * key: key to find
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * If an exact match found.
+ */
+static int
+bt_snext(t, h, key, exactp)
+ BTREE *t;
+ PAGE *h;
+ const DBT *key;
+ int *exactp;
+{
+ EPG e;
+ PAGE *tp;
+ pgno_t pg;
+
+ /* Skip until reach the end of the tree or a key. */
+ for (pg = h->nextpg; pg != P_INVALID;) {
+ if ((tp = mpool_get(t->bt_mp, pg, 0)) == NULL) {
+ mpool_put(t->bt_mp, h, 0);
+ return (NULL);
+ }
+ if (NEXTINDEX(tp) != 0)
+ break;
+ pg = tp->prevpg;
+ mpool_put(t->bt_mp, tp, 0);
+ }
+ /*
+ * The key is either an exact match, or not as good as
+ * the one we already have.
+ */
+ if (pg != P_INVALID) {
+ e.page = tp;
+ e.index = NEXTINDEX(tp) - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ t->bt_cur = e;
+ *exactp = 1;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * BT_SPREV -- Check for an exact match before the key.
+ *
+ * Parameters:
+ * t: tree to search
+ * h: current page.
+ * key: key to find
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * If an exact match found.
+ */
+static int
+bt_sprev(t, h, key, exactp)
+ BTREE *t;
+ PAGE *h;
+ const DBT *key;
+ int *exactp;
+{
+ EPG e;
+ PAGE *tp;
+ pgno_t pg;
+
+ /* Skip until reach the beginning of the tree or a key. */
+ for (pg = h->prevpg; pg != P_INVALID;) {
+ if ((tp = mpool_get(t->bt_mp, pg, 0)) == NULL) {
+ mpool_put(t->bt_mp, h, 0);
+ return (NULL);
+ }
+ if (NEXTINDEX(tp) != 0)
+ break;
+ pg = tp->prevpg;
+ mpool_put(t->bt_mp, tp, 0);
+ }
+ /*
+ * The key is either an exact match, or not as good as
+ * the one we already have.
+ */
+ if (pg != P_INVALID) {
+ e.page = tp;
+ e.index = NEXTINDEX(tp) - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ t->bt_cur = e;
+ *exactp = 1;
+ return (1);
+ }
+ }
+ return (0);
+}