aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db_test.go14
-rw-r--r--node.go14
-rw-r--r--rwtransaction.go20
3 files changed, 43 insertions, 5 deletions
diff --git a/db_test.go b/db_test.go
index 50ec3c3..224cfc7 100644
--- a/db_test.go
+++ b/db_test.go
@@ -191,6 +191,20 @@ func TestDBPutRandom(t *testing.T) {
}
}
+// Ensure that a bucket can delete an existing key.
+func TestDBDelete(t *testing.T) {
+ withOpenDB(func(db *DB, path string) {
+ db.CreateBucket("widgets")
+ db.Put("widgets", []byte("foo"), []byte("bar"))
+ err := db.Delete("widgets", []byte("foo"))
+ assert.NoError(t, err)
+ value, err := db.Get("widgets", []byte("foo"))
+ if assert.NoError(t, err) {
+ assert.Nil(t, value)
+ }
+ })
+}
+
// withDB executes a function with a database reference.
func withDB(fn func(*DB, string)) {
f, _ := ioutil.TempFile("", "bolt-")
diff --git a/node.go b/node.go
index 8d03681..2b3fded 100644
--- a/node.go
+++ b/node.go
@@ -61,6 +61,20 @@ func (n *node) put(oldKey, newKey, value []byte, pgid pgid) {
inode.pgid = pgid
}
+// del removes a key from the node.
+func (n *node) del(key []byte) {
+ // Find index of key.
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, key) != -1 })
+
+ // Exit if the key isn't found.
+ if !bytes.Equal(n.inodes[index].key, key) {
+ return
+ }
+
+ // Delete inode from the node.
+ n.inodes = append(n.inodes[:index], n.inodes[index+1:]...)
+}
+
// read initializes the node from a page.
func (n *node) read(p *page) {
n.pgid = p.id
diff --git a/rwtransaction.go b/rwtransaction.go
index 2485c62..7911188 100644
--- a/rwtransaction.go
+++ b/rwtransaction.go
@@ -70,19 +70,29 @@ func (t *RWTransaction) Put(name string, key []byte, value []byte) error {
return &Error{"data too large", nil}
}
- // Insert a new node.
+ // Move cursor to correct position.
c := b.cursor()
c.Get(key)
+
+ // Insert the key/value.
t.node(c.stack).put(key, key, value, 0)
return nil
}
func (t *RWTransaction) Delete(name string, key []byte) error {
- // TODO: Traverse to the correct node.
- // TODO: If missing, exit.
- // TODO: Remove node from page.
- // TODO: If page is empty then add it to the freelist.
+ b := t.Bucket(name)
+ if b == nil {
+ return &Error{"bucket not found", nil}
+ }
+
+ // Move cursor to correct position.
+ c := b.cursor()
+ c.Get(key)
+
+ // Delete the node if we have a matching key.
+ t.node(c.stack).del(key)
+
return nil
}