diff --git a/pkg/btree/bptree.go b/pkg/btree/bptree.go index 5c9fa57c..030f9048 100644 --- a/pkg/btree/bptree.go +++ b/pkg/btree/bptree.go @@ -239,6 +239,13 @@ func (t *BPTree) traverse(key ReferencedValue, node *BPTreeNode, ptr MemoryPoint } func (t *BPTree) Insert(key ReferencedValue, value MemoryPointer) error { + + if t.Width != uint16(0) { + if uint16(len(key.Value)) != t.Width-1 { + return fmt.Errorf("key to insert does not match with bptree width. Expected width: %v, got: %v", t.Width, len(key.Value)) + } + } + root, rootOffset, err := t.root() if err != nil { return fmt.Errorf("read root node: %w", err) @@ -268,7 +275,8 @@ func (t *BPTree) Insert(key ReferencedValue, value MemoryPointer) error { n := path[0].node j, found := slices.BinarySearchFunc(n.Keys, key, CompareReferencedValues) if found { - return fmt.Errorf("key already exists") + + return fmt.Errorf("key already exists. Data pointer: %v", key.DataPointer) } if j == len(n.Keys) { n.Keys = append(n.Keys, key) diff --git a/pkg/btree/bptree_test.go b/pkg/btree/bptree_test.go index 8dffba6a..51376666 100644 --- a/pkg/btree/bptree_test.go +++ b/pkg/btree/bptree_test.go @@ -569,6 +569,35 @@ func TestBPTree_Iteration_FirstLast(t *testing.T) { }) } +func TestBPTree_IncorrectWidth(t *testing.T) { + + t.Run("float tree", func(t *testing.T) { + b := buftest.NewSeekableBuffer() + p, err := pagefile.NewPageFile(b) + if err != nil { + t.Fatal(err) + } + floatTree := &BPTree{PageFile: p, MetaPage: newTestMetaPage(t, p), Width: uint16(9)} + + if err := floatTree.Insert(ReferencedValue{Value: []byte{1}, DataPointer: MemoryPointer{Offset: uint64(0)}}, MemoryPointer{Offset: uint64(0), Length: uint32(39)}); err == nil { + t.Fatalf("should error %v", err) + } + }) + + t.Run("nil tree", func(t *testing.T) { + b := buftest.NewSeekableBuffer() + p, err := pagefile.NewPageFile(b) + if err != nil { + t.Fatal(err) + } + nilTree := &BPTree{PageFile: p, MetaPage: newTestMetaPage(t, p), Width: uint16(1)} + + if err := nilTree.Insert(ReferencedValue{Value: []byte{1}, DataPointer: MemoryPointer{Offset: uint64(0)}}, MemoryPointer{Offset: uint64(0), Length: uint32(39)}); err == nil { + t.Fatalf("should error %v", err) + } + }) +} + func TestBPTree_Iteration_Overcount(t *testing.T) { b := buftest.NewSeekableBuffer() p, err := pagefile.NewPageFile(b) @@ -588,7 +617,7 @@ func TestBPTree_Iteration_Overcount(t *testing.T) { } } - t.Run("finds exactly 10 occurences of 23", func(t *testing.T) { + t.Run("finds exactly 10 occurrences of 23", func(t *testing.T) { buf := make([]byte, 8) binary.BigEndian.PutUint64(buf, math.Float64bits(23))