Skip to content

Commit

Permalink
NRange() function implementation and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Gaetano Padula committed Sep 24, 2024
1 parent e62d109 commit 0bd47d3
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
58 changes: 58 additions & 0 deletions btree.go
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,64 @@ func (k *Key) Iterator() func() ([]byte, bool) {
}
}

// NRange returns all keys not within the range [start, end]
func (b *BTree) NRange(start, end []byte) ([]*Key, error) {
root, err := b.getRoot()
if err != nil {
return nil, err
}

return b.nrange(root, start, end)
}

// nrange returns all keys not within the range [start, end]
// nrange returns all keys not within the range [start, end]
func (b *BTree) nrange(x *Node, start, end []byte) ([]*Key, error) {
keys := make([]*Key, 0)
if x != nil {
for i := 0; i < len(x.Keys); i++ {
if !x.Leaf {
childBytes, err := b.Pager.GetPage(x.Children[i])
if err != nil {
return nil, err
}

child, err := decodeNode(childBytes)
if err != nil {
return nil, err
}

childKeys, err := b.nrange(child, start, end)
if err != nil {
return nil, err
}
keys = append(keys, childKeys...)
}
if lessThan(x.Keys[i].K, start) || greaterThan(x.Keys[i].K, end) {
keys = append(keys, x.Keys[i])
}
}
if !x.Leaf {
childBytes, err := b.Pager.GetPage(x.Children[len(x.Children)-1])
if err != nil {
return nil, err
}

child, err := decodeNode(childBytes)
if err != nil {
return nil, err
}

childKeys, err := b.nrange(child, start, end)
if err != nil {
return nil, err
}
keys = append(keys, childKeys...)
}
}
return keys, nil
}

// Range returns all keys in the BTree that are within the range [start, end]
func (b *BTree) Range(start, end []byte) ([]interface{}, error) {
root, err := b.getRoot()
Expand Down
32 changes: 32 additions & 0 deletions btree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,38 @@ func TestBTree_GreaterThan(t *testing.T) {
}
}

func TestBTree_NRange(t *testing.T) {

defer os.Remove("btree.db")
defer os.Remove("btree.db.del")

btree, err := Open("btree.db", os.O_CREATE|os.O_RDWR, 0644, 3)
if err != nil {
t.Fatal(err)
}

defer btree.Close()

for i := 0; i < 500; i++ {
key := fmt.Sprintf("%03d", i) // pad the key with leading zeros
err := btree.Put([]byte(key), []byte(key))
if err != nil {
t.Fatal(err)
}
}

keys, err := btree.NRange([]byte("010"), []byte("020")) // use padded keys
if err != nil {
t.Fatal(err)
}

// Expect 489 keys
if len(keys) != 489 {
t.Fatalf("expected 489 keys, got %d", len(keys))

}
}

func TestBTree_LessThan(t *testing.T) {
defer os.Remove("btree.db")
defer os.Remove("btree.db.del")
Expand Down

0 comments on commit 0bd47d3

Please sign in to comment.