* *result with the results of the search. If an exact match is found,
* result->page_exact and result->index_exact will be set to the page and
* slot where it is located. Otherwise, result->page_exact will be NULL;
- * result->page_next and result->index_next will indicate the location of
- * the following key (unless the proposed first_page would follow everything
- * currently in the tree, in which case result->page_next will be NULL); and
- * result->page_prev and result->index_prev will indicate the preceding
- * key (unless the proposed first_page would precede everything currently
- * in the tree, in which case result->page_prev will be NULL).
- * result->split_pages will contain the number of additional btree pages that
- * will be needed when performing a split to insert a key into
+ * result->page_next and result->index_next will indicate the point at which
+ * the key could be inserted; and result->page_prev and result->index_prev
+ * will indicate the preceding key (unless the proposed first_page would
+ * precede everything currently in the tree, in which case result->page_prev
+ * will be NULL). result->split_pages will contain the number of additional
+ * btree pages that will be needed when performing a split to insert a key into
* result->page_exact or result->page_next. Except as described above, the
* contents of fields in the result object are undefined on return.
*/
/* Search leaf page. */
index = FreePageBtreeSearchLeaf(btp, first_page);
- if (index >= btp->hdr.nused)
- {
- /* Bigger than every key on the page. */
- Assert(index == btp->hdr.nused);
- result->page_exact = NULL;
- result->page_next = NULL;
- }
- else if (first_page == btp->u.leaf_key[index].first_page)
+ if (index < btp->hdr.nused &&
+ first_page == btp->u.leaf_key[index].first_page)
{
/* Exact match. */
result->page_exact = btp;
result->index_exact = index;
return; /* No need to set previous key in this case. */
}
- else
- {
- /* Not equal to any key and before at least one key. */
- result->page_exact = NULL;
- result->page_next = btp;
- result->index_next = index;
- }
+
+ /* No exact match; indicate insertion position. */
+ result->page_exact = NULL;
+ result->page_next = btp;
+ result->index_next = index;
/* Find the previous key. */
if (index > 0)
Assert(result.page_exact == NULL); /* can't already be there */
if (result.page_prev != NULL)
prevkey = &result.page_prev->u.leaf_key[result.index_prev];
- if (result.page_next != NULL)
+ if (result.index_next < result.page_next->hdr.nused)
nextkey = &result.page_next->u.leaf_key[result.index_next];
/* Consolidate with the previous entry if possible. */
/* If we still need to perform a split, do it. */
if (result.split_pages > 0)
{
- FreePageBtree *target = result.page_next;
+ FreePageBtree *split_target = result.page_next;
FreePageBtree *child = NULL;
Size key = first_page;
FreePageBtree *parent;
/* Identify parent page, which must receive downlink. */
- parent = relptr_access(base, target->hdr.parent);
+ parent = relptr_access(base, split_target->hdr.parent);
/* Split the page - downlink not added yet. */
- newsibling = FreePageBtreeSplitPage(fpm, target);
+ newsibling = FreePageBtreeSplitPage(fpm, split_target);
/*
* At this point in the loop, we're always carrying a pending
FreePageBtree *insert_into;
insert_into = key < newsibling->u.leaf_key[0].first_page ?
- target : newsibling;
+ split_target : newsibling;
index = FreePageBtreeSearchLeaf(insert_into, key);
FreePageBtreeInsertLeaf(insert_into, index, key, npages);
- if (index == 0 && insert_into == target)
- FreePageBtreeAdjustAncestorKeys(fpm, target);
+ if (index == 0 && insert_into == split_target)
+ FreePageBtreeAdjustAncestorKeys(fpm, split_target);
}
else
{
insert_into =
key < newsibling->u.internal_key[0].first_page ?
- target : newsibling;
+ split_target : newsibling;
index = FreePageBtreeSearchInternal(insert_into, key);
FreePageBtreeInsertInternal(base, insert_into, index,
key, child);
- if (index == 0 && insert_into == target)
- FreePageBtreeAdjustAncestorKeys(fpm, target);
+ if (index == 0 && insert_into == split_target)
+ FreePageBtreeAdjustAncestorKeys(fpm, split_target);
}
/* If the page we just split has no parent, split the root. */
relptr_store(base, newroot->hdr.parent,
(FreePageBtree *) NULL);
newroot->u.internal_key[0].first_page =
- FreePageBtreeFirstKey(target);
+ FreePageBtreeFirstKey(split_target);
relptr_store(base, newroot->u.internal_key[0].child,
- target);
+ split_target);
+ relptr_store(base, newroot->hdr.parent, newroot);
newroot->u.internal_key[1].first_page =
FreePageBtreeFirstKey(newsibling);
relptr_store(base, newroot->u.internal_key[1].child,
- target);
+ newsibling);
+ relptr_store(base, newsibling->hdr.parent, newroot);
+ relptr_store(base, fpm->btree_root, newroot);
fpm->btree_depth++;
break;
/* The parent also needs to be split, so loop around. */
child = newsibling;
- target = parent;
+ split_target = parent;
}
/*