From 0bd47d31ad77db4c41336f02928b7cb47274b2ab Mon Sep 17 00:00:00 2001 From: Alex Gaetano Padula Date: Tue, 24 Sep 2024 07:36:34 -0400 Subject: [PATCH] NRange() function implementation and tests --- btree.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ btree_test.go | 32 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/btree.go b/btree.go index 93f084c..81255d8 100644 --- a/btree.go +++ b/btree.go @@ -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() diff --git a/btree_test.go b/btree_test.go index c3ef713..42ceeaa 100644 --- a/btree_test.go +++ b/btree_test.go @@ -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")