system.indexes.btree module¶
B+-tree index implementation with node splitting.
- class system.indexes.btree.NoSplit[source]¶
Bases:
PutInfoResult of a put that did not cause a node to split.
- class system.indexes.btree.SplitHappens(left_node: BPlusTree.AbstractNode, right_node: BPlusTree.AbstractNode, pivot: Key)[source]¶
Bases:
PutInfo,GenericResult of a put that caused a node to split into two.
Wraps the two nodes produced by the split and the pivot key that separates them:
left_nodeholds the keys below the pivot,right_nodeholds the keys at or above it, andpivotis the separating key propagated up to the parent.- left_node: BPlusTree.AbstractNode¶
- right_node: BPlusTree.AbstractNode¶
- pivot: Key¶
- class system.indexes.btree.BPlusTree(inner_capacity: int = 3, leaf_capacity: int = 4)[source]¶
Bases:
AbstractBTree,GenericA simple, educational B+tree implementation with support for inserts, splits, as well as point, and range queries. Deletes and merges are not supported. Note that this outside class is simply a wrapper around the actual tree which is held as a reference. So this is a Decorator Design Pattern. The only purpose of the outside wrapper is to keep track of basic capacity parameters AND handle the root node in case of a split.
- class AbstractNode(capacity: int)[source]¶
Bases:
AbstractBTree,ABCAbstract node API of a b+-tree. An abstract node can be either implemented as an inner node or a leaf node. An abstract node and all its subclasses are valid B-Tree Indexes.
- abstractmethod put(key: Key, value: Value) None | PutInfo[source]¶
Insert the given key and value into the abstract node.
- Parameters:
key – The key to insert.
value – The value to insert.
- Returns:
A PutInfo instance: NoSplit if the pair fit without splitting, or SplitHappens (wrapping the two new nodes and the pivot) if this insertion caused a split.
- abstractmethod split() SplitHappens[Key][source]¶
Split-operation for nodes. Splits the keys and values of this node into two nodes.
- Returns:
A SplitHappens instance wrapping the left node, the right node, and the new pivot if a split occurred
- abstractmethod get_all_in_range(min_key: Key, max_key: Key) Iterator[Value][source]¶
See
RangeQueryMixIn.get_all_in_range().
- abstractmethod consistency_check() None[source]¶
Check if the node is consistent, i.e., all keys are sorted and the number of children is correct.
- class Inner(capacity: int, keys: list[Key], children: list[BPlusTree.AbstractNode])[source]¶
Bases:
AbstractNodeInner node of a b+-tree. Inner nodes have keys and references to children subtrees, i.e. Nodes or Leaves. Inner Nodes in inself are an index structure.
- split() SplitHappens[Key][source]¶
Split-operation for inner nodes. Splits the keys and children of this node into two inner nodes plus pivot. Note: No re-use of this instance, we are creating two new Inner-instances.
- Returns:
A SplitHappens wrapping the left node, the right node, and the new pivot.
- put(key: Key, value: Value) PutInfo[source]¶
Insert the given key and value into the inner node.
- Parameters:
key – The key to insert.
value – The value to insert.
- Returns:
A PutInfo instance: NoSplit if the pair fit without splitting, or SplitHappens (wrapping the two new nodes and the pivot) if this insertion caused a split.
- get(key: Key) Iterator[Value][source]¶
Finds the appropriate subtree to search for the given key and calls get on that subtree. :param key: The key to search for.
- get_all_in_range(min_key: Key, max_key: Key) Iterator[Value][source]¶
Finds the appropriate subtree to search for the given key range and calls get_all_in_range on that subtree.
- Parameters:
min_key – The minimum key to search for.
max_key – The maximum key to search for.
- Returns:
A list of values for all keys in the given range.
- class Leaf(capacity: int, keys: list[Key] | None = None, values: list[Value] | None = None)[source]¶
Bases:
AbstractNodeLeaf node of a b-tree. Leaf nodes have keys and values.
- split() SplitHappens[Key][source]¶
Split-operation for leaf nodes. Splits the keys and values of this Leaf into two Leaves. Note: No re-use of this instance, we are creating two new Leaf instances.
- Returns:
A SplitHappens wrapping the left leaf, the right leaf, and the new pivot.
- put(key: Key, value: Value) PutInfo[source]¶
Insert the given key and value into the leaf.
- Parameters:
key – The key to insert.
value – The value to insert.
- Returns:
A PutInfo instance: NoSplit if the pair fit without splitting, or SplitHappens (wrapping the two new nodes and the pivot) if this insertion caused a split.
- get(key: Key) Iterator[Value][source]¶
Returns the value for the given key if it exists. :param key: The key to search for.
- get_all_in_range(min_key: Key, max_key: Key) Iterator[Value][source]¶
Returns a list of values for all keys in the given range. Implements ISAM-like sequential scanning.
- Parameters:
min_key – The minimum key to search for.
max_key – The maximum key to search for.
- Returns:
A list of values for all keys in the given range.
- class CountingLeaf[source]¶
Bases:
AbstractNodeA leaf node that does not store values but counts the number of put-calls.
- put(key: Key, value: Value) PutInfo | None[source]¶
See
Index.put().Does not store the value; only increments the counter of put calls.
- split() SplitHappens[Key][source]¶
Counting leaves are never split: always raises
NotImplementedError.
- get(key: Key) Iterator[Value][source]¶
See
PointQueryMixIn.get().Not supported for counting leaves: always raises
NotImplementedError.
- get_all_in_range(min_key: Key, max_key: Key) Iterator[Value][source]¶
See
RangeQueryMixIn.get_all_in_range().Not supported for counting leaves: always raises
NotImplementedError.
- put(key: Key, value: Value) None | PutInfo[source]¶
See
Index.put().Copies the value before storing it and, if the root node split, replaces the root with a new inner node holding the two halves and the separating pivot.
- get(key: Key) Iterator[Value][source]¶
See
PointQueryMixIn.get().Note: this simple B+tree does not support multiple values for the same key.
- get_all_in_range(min_key: Key, max_key: Key) Iterator[Value][source]¶
See
RangeQueryMixIn.get_all_in_range().
- delete(key: Key, value: Value = None)[source]¶
See
Index.delete().Not implemented in this simple B+tree.
- flush(key: Key | None = None) None[source]¶
See
Index.flush().Not implemented in this simple B+tree.
- bulkload(input_data: Iterator[tuple[Key, Value]])[source]¶
Bulkloads the given list of key->value mappings into the index. Not overridden in this simple B+tree.