Cursor.Get is now Cursor.Seek, and returns the first possible key.

This makes range and prefix queries possible.

Closes: #44
master
Tommi Virtanen 2014-02-20 10:55:04 -08:00
parent 8864050f87
commit 8438c6ebc3
3 changed files with 21 additions and 16 deletions

View File

@ -48,32 +48,28 @@ func (c *Cursor) Next() (key []byte, value []byte) {
return c.keyValue()
}
// Get moves the cursor to a given key and returns its value.
// If the key does not exist then the cursor is left at the closest key and a nil value is returned.
func (c *Cursor) Get(key []byte) (value []byte) {
// Seek moves the cursor to a given key and returns it.
// If the key does not exist then the next key is used. If no keys
// follow, a nil value is returned.
func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) {
// Start from root page and traverse to correct page.
c.stack = c.stack[:0]
c.search(key, c.transaction.page(c.root))
c.search(seek, c.transaction.page(c.root))
p, index := c.top()
// If the cursor is pointing to the end of page then return nil.
if index == p.count {
return nil
return nil, nil
}
// If our target node isn't the same key as what's passed in then return nil.
if !bytes.Equal(key, c.element().key()) {
return nil
}
return c.element().value()
return c.element().key(), c.element().value()
}
// first moves the cursor to the first leaf element under the last page in the stack.
func (c *Cursor) first() {
p := c.stack[len(c.stack)-1].page
for {
// Exit when we hit a leaf page.
// Exit when we hit a leaf page.
if (p.flags & leafPageFlag) != 0 {
break
}

View File

@ -20,7 +20,7 @@ func (t *RWTransaction) init(db *DB) {
t.Transaction.init(db)
t.pages = make(map[pgid]*page)
// Increment the transaction id.
// Increment the transaction id.
t.meta.txnid += txnid(1)
}
@ -114,7 +114,7 @@ func (t *RWTransaction) Put(name string, key []byte, value []byte) error {
// Move cursor to correct position.
c := b.cursor()
c.Get(key)
c.Seek(key)
// Insert the key/value.
c.node(t).put(key, key, value, 0)
@ -133,7 +133,7 @@ func (t *RWTransaction) Delete(name string, key []byte) error {
// Move cursor to correct position.
c := b.cursor()
c.Get(key)
c.Seek(key)
// Delete the node if we have a matching key.
c.node(t).del(key)

View File

@ -1,5 +1,9 @@
package bolt
import (
"bytes"
)
// Transaction represents a read-only transaction on the database.
// It can be used for retrieving values for keys as well as creating cursors for
// iterating over the data.
@ -90,7 +94,12 @@ func (t *Transaction) Get(name string, key []byte) (value []byte, err error) {
if err != nil {
return nil, err
}
return c.Get(key), nil
k, v := c.Seek(key)
// If our target node isn't the same key as what's passed in then return nil.
if !bytes.Equal(key, k) {
return nil, nil
}
return v, nil
}
// ForEach executes a function for each key/value pair in a bucket.