Function: findleaf in b-tree-storage-engine/btree.py

Date: 2026-05-29

Time: 07:43

findleaf — Leaf Page Locator

Purpose

findleaf traverses the B-tree from a given internal node down to the leaf level, returning the page number of the leaf page that would contain the given key. It does not check whether the key actually exists — it finds where the key *would* live.

This exists to support rangescan, which needs to start iterating from a specific leaf page and then follow sibling pointers. Unlike search (which reads the leaf and returns a value), findleaf stops one step earlier: it returns the leaf's page number so the caller can manage the leaf-level scan itself.

Contract

Preconditions:

Postcondition: Returns the page number of the leaf page whose key range includes key — specifically, the leaf reachable by following the same child-pointer path that _search would take.

Invariant: Each recursive call decrements depth by exactly 1, guaranteeing termination in depth - 1 recursive steps.

Parameters

| Parameter | Type | Description |

|-----------|------|-------------|

| page_num | int | Page number of the current node being examined. On the initial call, this is the root page. |

| key | str | The search key. Used to choose which child pointer to follow at each internal level. |

| depth | int | Remaining depth from pagenum to the leaf level. 1 means pagenum is itself a leaf. |

Edge cases:

Return Value

Returns an int — the page number of the leaf that would contain key. The caller (range_scan) then reads this page directly and begins scanning.

There is no "not found" return. The method always succeeds if the tree is well-formed.

Algorithm

1. Base case (depth == 1): The current page is a leaf. Return its page number immediately.

2. Recursive case (depth > 1):

The choice of bisectright (not bisectleft) matters: for a key equal to a separator, bisectright directs to the right child, which is consistent with how insert and search route — the separator key belongs to the right subtree (visible in the leaf split logic where midkey = right_keys[0]).

Side Effects

Error Handling

None. The method assumes:

A corrupted page or incorrect depth would produce silently wrong results rather than raising an exception.

Usage Patterns

Called exclusively by range_scan:


leaf_num = self._find_leaf(root, start_key, height)

The caller then reads that leaf, scans its keys, and follows next_sib pointers to walk through subsequent leaves. The caller is responsible for:

Dependencies