mirror of https://github.com/hak5/bolt.git
Return bucket from CreateBucket() functions.
This commit changes the API for: Tx.CreateBucket() Tx.CreateBucketIfNotExists() Bucket.CreateBucket() Bucket.CreateBucketIfNotExists() These functions now return the *Bucket and error instead of just the error.master
parent
02cd971daa
commit
2505b9a7dc
12
bolt_test.go
12
bolt_test.go
|
@ -154,18 +154,16 @@ func simulateGetHandler(tx *Tx, qdb *QuickDB) {
|
|||
|
||||
// Inserts a key into the database.
|
||||
func simulatePutHandler(tx *Tx, qdb *QuickDB) {
|
||||
var err error
|
||||
keys, value := randKeys(), randValue()
|
||||
|
||||
// Retrieve root bucket.
|
||||
b := tx.Bucket(keys[0])
|
||||
if b == nil {
|
||||
if err := tx.CreateBucket(keys[0]); err != nil {
|
||||
b, err = tx.CreateBucket(keys[0])
|
||||
if err != nil {
|
||||
panic("create bucket: " + err.Error())
|
||||
}
|
||||
b = tx.Bucket(keys[0])
|
||||
if b == nil {
|
||||
panic(fmt.Sprintf("bucket[0] nil: %v", keys[0]))
|
||||
}
|
||||
}
|
||||
|
||||
// Create nested buckets, if necessary.
|
||||
|
@ -174,10 +172,10 @@ func simulatePutHandler(tx *Tx, qdb *QuickDB) {
|
|||
if child != nil {
|
||||
b = child
|
||||
} else {
|
||||
if err := b.CreateBucket(key); err != nil {
|
||||
b, err = b.CreateBucket(key)
|
||||
if err != nil {
|
||||
panic("create bucket: " + err.Error())
|
||||
}
|
||||
b = b.Bucket(key)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
32
bucket.go
32
bucket.go
|
@ -107,15 +107,15 @@ func (b *Bucket) Bucket(name []byte) *Bucket {
|
|||
return &child
|
||||
}
|
||||
|
||||
// CreateBucket creates a new bucket at the given key.
|
||||
// CreateBucket creates a new bucket at the given key and returns the new bucket.
|
||||
// Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long.
|
||||
func (b *Bucket) CreateBucket(key []byte) error {
|
||||
func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
|
||||
if b.tx.db == nil {
|
||||
return ErrTxClosed
|
||||
return nil, ErrTxClosed
|
||||
} else if !b.tx.writable {
|
||||
return ErrTxNotWritable
|
||||
return nil, ErrTxNotWritable
|
||||
} else if len(key) == 0 {
|
||||
return ErrBucketNameRequired
|
||||
return nil, ErrBucketNameRequired
|
||||
}
|
||||
|
||||
// Move cursor to correct position.
|
||||
|
@ -125,16 +125,16 @@ func (b *Bucket) CreateBucket(key []byte) error {
|
|||
// Return an error if there is an existing key.
|
||||
if bytes.Equal(key, k) {
|
||||
if (flags & bucketLeafFlag) != 0 {
|
||||
return ErrBucketExists
|
||||
return nil, ErrBucketExists
|
||||
} else {
|
||||
return ErrIncompatibleValue
|
||||
return nil, ErrIncompatibleValue
|
||||
}
|
||||
}
|
||||
|
||||
// Create a blank root leaf page.
|
||||
p, err := b.tx.allocate(1)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
p.flags = leafPageFlag
|
||||
|
||||
|
@ -146,17 +146,19 @@ func (b *Bucket) CreateBucket(key []byte) error {
|
|||
// Insert into node.
|
||||
c.node().put(key, key, value, 0, bucketLeafFlag)
|
||||
|
||||
return nil
|
||||
return b.Bucket(key), nil
|
||||
}
|
||||
|
||||
// CreateBucketIfNotExists creates a new bucket if it doesn't already exist.
|
||||
// CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it.
|
||||
// Returns an error if the bucket name is blank, or if the bucket name is too long.
|
||||
func (b *Bucket) CreateBucketIfNotExists(key []byte) error {
|
||||
err := b.CreateBucket(key)
|
||||
if err != nil && err != ErrBucketExists {
|
||||
return err
|
||||
func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) {
|
||||
child, err := b.CreateBucket(key)
|
||||
if err == ErrBucketExists {
|
||||
return b.Bucket(key), nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
return child, nil
|
||||
}
|
||||
|
||||
// DeleteBucket deletes a bucket at the given key.
|
||||
|
|
|
@ -44,7 +44,8 @@ func TestBucket_Get_IncompatibleValue(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")))
|
||||
_, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, tx.Bucket([]byte("widgets")).Get([]byte("foo")))
|
||||
return nil
|
||||
})
|
||||
|
@ -109,7 +110,8 @@ func TestBucket_Put_IncompatibleValue(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")))
|
||||
_, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ErrIncompatibleValue, tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")))
|
||||
return nil
|
||||
})
|
||||
|
@ -131,7 +133,8 @@ func TestBucket_Put_Closed(t *testing.T) {
|
|||
func TestBucket_Put_ReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
db.View(func(tx *Tx) error {
|
||||
|
@ -164,7 +167,8 @@ func TestBucket_Delete_Bucket(t *testing.T) {
|
|||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket([]byte("widgets"))
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
assert.NoError(t, b.CreateBucket([]byte("foo")))
|
||||
_, err := b.CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ErrIncompatibleValue, b.Delete([]byte("foo")))
|
||||
return nil
|
||||
})
|
||||
|
@ -203,8 +207,10 @@ func TestBucket_DeleteBucket_Nested(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).Bucket([]byte("foo")).CreateBucket([]byte("bar")))
|
||||
_, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
_, err = tx.Bucket([]byte("widgets")).Bucket([]byte("foo")).CreateBucket([]byte("bar"))
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).Bucket([]byte("foo")).Bucket([]byte("bar")).Put([]byte("baz"), []byte("bat")))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")))
|
||||
return nil
|
||||
|
@ -217,8 +223,10 @@ func TestBucket_DeleteBucket_Nested2(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).Bucket([]byte("foo")).CreateBucket([]byte("bar")))
|
||||
_, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
_, err = tx.Bucket([]byte("widgets")).Bucket([]byte("foo")).CreateBucket([]byte("bar"))
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).Bucket([]byte("foo")).Bucket([]byte("bar")).Put([]byte("baz"), []byte("bat")))
|
||||
return nil
|
||||
})
|
||||
|
@ -241,8 +249,10 @@ func TestBucket_DeleteBucket_Nested2(t *testing.T) {
|
|||
func TestBucket_DeleteBucket_Large(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
_, err = tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
b := tx.Bucket([]byte("widgets")).Bucket([]byte("foo"))
|
||||
for i := 0; i < 1000; i++ {
|
||||
assert.NoError(t, b.Put([]byte(fmt.Sprintf("%d", i)), []byte(fmt.Sprintf("%0100d", i))))
|
||||
|
@ -274,9 +284,11 @@ func TestBucket_Bucket_IncompatibleValue(t *testing.T) {
|
|||
func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")))
|
||||
assert.Equal(t, ErrIncompatibleValue, tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")))
|
||||
_, err = tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo"))
|
||||
assert.Equal(t, ErrIncompatibleValue, err)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
@ -286,7 +298,8 @@ func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) {
|
|||
func TestBucket_DeleteBucket_IncompatibleValue(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")))
|
||||
assert.Equal(t, ErrIncompatibleValue, tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")))
|
||||
return nil
|
||||
|
@ -464,7 +477,8 @@ func TestBucket_Stat(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
// Add bucket with fewer keys but one big value.
|
||||
assert.NoError(t, tx.CreateBucket([]byte("woojits")))
|
||||
_, err := tx.CreateBucket([]byte("woojits"))
|
||||
assert.NoError(t, err)
|
||||
b := tx.Bucket([]byte("woojits"))
|
||||
for i := 0; i < 500; i++ {
|
||||
b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i)))
|
||||
|
@ -472,8 +486,8 @@ func TestBucket_Stat(t *testing.T) {
|
|||
b.Put([]byte("really-big-value"), []byte(strings.Repeat("*", 10000)))
|
||||
|
||||
// Add a bucket that fits on a single root leaf.
|
||||
assert.NoError(t, tx.CreateBucket([]byte("whozawhats")))
|
||||
b = tx.Bucket([]byte("whozawhats"))
|
||||
b, err = tx.CreateBucket([]byte("whozawhats"))
|
||||
assert.NoError(t, err)
|
||||
b.Put([]byte("foo"), []byte("bar"))
|
||||
|
||||
return nil
|
||||
|
@ -543,7 +557,8 @@ func TestBucket_Put_Single(t *testing.T) {
|
|||
m := make(map[string][]byte)
|
||||
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
for _, item := range items {
|
||||
db.Update(func(tx *Tx) error {
|
||||
|
@ -588,7 +603,8 @@ func TestBucket_Put_Multiple(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
// Bulk insert all values.
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
|
@ -628,7 +644,8 @@ func TestBucket_Delete_Quick(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
// Bulk insert all values.
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
|
|
|
@ -45,7 +45,8 @@ func TestGetKeyNotFound(t *testing.T) {
|
|||
SetTestMode(true)
|
||||
open(func(db *bolt.DB, path string) {
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
db.Close()
|
||||
output := run("get", path, "widgets", "foo")
|
||||
|
|
|
@ -41,7 +41,8 @@ func Import(path string, input string) {
|
|||
}
|
||||
|
||||
// Create the bucket if it doesn't exist.
|
||||
if err := tx.CreateBucketIfNotExists(message.Key); err != nil {
|
||||
b, err := tx.CreateBucketIfNotExists(message.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create bucket: %s", err)
|
||||
}
|
||||
|
||||
|
@ -52,7 +53,6 @@ func Import(path string, input string) {
|
|||
}
|
||||
|
||||
// Import all the values into the bucket.
|
||||
b := tx.Bucket(message.Key)
|
||||
if err := importBucket(b, children); err != nil {
|
||||
return fmt.Errorf("import bucket: %s", err)
|
||||
}
|
||||
|
@ -70,7 +70,8 @@ func importBucket(b *bolt.Bucket, children []*rawMessage) error {
|
|||
// Bucket messages are handled recursively.
|
||||
if child.Type == "bucket" {
|
||||
// Create the bucket if it doesn't exist.
|
||||
if err := b.CreateBucketIfNotExists(child.Key); err != nil {
|
||||
subbucket, err := b.CreateBucketIfNotExists(child.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create bucket: %s", err)
|
||||
}
|
||||
|
||||
|
@ -81,7 +82,6 @@ func importBucket(b *bolt.Bucket, children []*rawMessage) error {
|
|||
}
|
||||
|
||||
// Import subbucket.
|
||||
subbucket := b.Bucket(child.Key)
|
||||
if err := importBucket(subbucket, subchildren); err != nil {
|
||||
return fmt.Errorf("import bucket: %s", err)
|
||||
}
|
||||
|
|
|
@ -12,12 +12,13 @@ import (
|
|||
func TestCursor_Seek(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, b.Put([]byte("foo"), []byte("0001")))
|
||||
assert.NoError(t, b.Put([]byte("bar"), []byte("0002")))
|
||||
assert.NoError(t, b.Put([]byte("baz"), []byte("0003")))
|
||||
assert.NoError(t, b.CreateBucket([]byte("bkt")))
|
||||
_, err = b.CreateBucket([]byte("bkt"))
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
db.View(func(tx *Tx) error {
|
||||
|
@ -57,7 +58,8 @@ func TestCursor_Seek(t *testing.T) {
|
|||
func TestCursor_EmptyBucket(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
db.View(func(tx *Tx) error {
|
||||
c := tx.Bucket([]byte("widgets")).Cursor()
|
||||
|
@ -73,7 +75,8 @@ func TestCursor_EmptyBucket(t *testing.T) {
|
|||
func TestCursor_EmptyBucketReverse(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
db.View(func(tx *Tx) error {
|
||||
c := tx.Bucket([]byte("widgets")).Cursor()
|
||||
|
@ -262,11 +265,14 @@ func TestCursor_Iterate_Reverse(t *testing.T) {
|
|||
func TestCursor_Iterate_BucketsOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
assert.NoError(t, b.CreateBucket([]byte("foo")))
|
||||
assert.NoError(t, b.CreateBucket([]byte("bar")))
|
||||
assert.NoError(t, b.CreateBucket([]byte("baz")))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
_, err = b.CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
_, err = b.CreateBucket([]byte("bar"))
|
||||
assert.NoError(t, err)
|
||||
_, err = b.CreateBucket([]byte("baz"))
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
db.View(func(tx *Tx) error {
|
||||
|
@ -286,11 +292,14 @@ func TestCursor_Iterate_BucketsOnly(t *testing.T) {
|
|||
func TestCursor_Iterate_BucketsOnly_Reverse(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
assert.NoError(t, b.CreateBucket([]byte("foo")))
|
||||
assert.NoError(t, b.CreateBucket([]byte("bar")))
|
||||
assert.NoError(t, b.CreateBucket([]byte("baz")))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NoError(t, err)
|
||||
_, err = b.CreateBucket([]byte("foo"))
|
||||
assert.NoError(t, err)
|
||||
_, err = b.CreateBucket([]byte("bar"))
|
||||
assert.NoError(t, err)
|
||||
_, err = b.CreateBucket([]byte("baz"))
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
db.View(func(tx *Tx) error {
|
||||
|
|
25
db_test.go
25
db_test.go
|
@ -128,10 +128,12 @@ func TestDB_Open_MetaChecksumError(t *testing.T) {
|
|||
db, err := Open(path, 0600)
|
||||
pageSize := db.pageSize
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("woojits"))
|
||||
_, err := tx.CreateBucket([]byte("woojits"))
|
||||
return err
|
||||
})
|
||||
db.Close()
|
||||
|
||||
|
@ -272,7 +274,8 @@ func TestDB_Commit_WriteFail(t *testing.T) {
|
|||
func TestDB_Stats(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
stats := db.Stats()
|
||||
assert.Equal(t, 3, stats.TxStats.PageCount)
|
||||
|
@ -295,7 +298,8 @@ func TestDB_mmapSize(t *testing.T) {
|
|||
func TestDB_Consistency(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
|
@ -357,7 +361,8 @@ func BenchmarkDB_Put_Sequential(b *testing.B) {
|
|||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
for i := 0; i < b.N; i++ {
|
||||
db.Update(func(tx *Tx) error {
|
||||
|
@ -373,7 +378,8 @@ func BenchmarkDB_Put_Random(b *testing.B) {
|
|||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
for i := 0; i < b.N; i++ {
|
||||
db.Update(func(tx *Tx) error {
|
||||
|
@ -391,10 +397,10 @@ func ExampleDB_Update() {
|
|||
|
||||
// Execute several commands within a write transaction.
|
||||
err := db.Update(func(tx *Tx) error {
|
||||
if err := tx.CreateBucket([]byte("widgets")); err != nil {
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := tx.Bucket([]byte("widgets"))
|
||||
if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -448,7 +454,8 @@ func ExampleDB_Begin_ReadOnly() {
|
|||
|
||||
// Create a bucket.
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
|
||||
// Create several keys in a transaction.
|
||||
|
|
4
tx.go
4
tx.go
|
@ -88,13 +88,13 @@ func (tx *Tx) Bucket(name []byte) *Bucket {
|
|||
|
||||
// CreateBucket creates a new bucket.
|
||||
// Returns an error if the bucket already exists, if the bucket name is blank, or if the bucket name is too long.
|
||||
func (tx *Tx) CreateBucket(name []byte) error {
|
||||
func (tx *Tx) CreateBucket(name []byte) (*Bucket, error) {
|
||||
return tx.root.CreateBucket(name)
|
||||
}
|
||||
|
||||
// CreateBucketIfNotExists creates a new bucket if it doesn't already exist.
|
||||
// Returns an error if the bucket name is blank, or if the bucket name is too long.
|
||||
func (tx *Tx) CreateBucketIfNotExists(name []byte) error {
|
||||
func (tx *Tx) CreateBucketIfNotExists(name []byte) (*Bucket, error) {
|
||||
return tx.root.CreateBucketIfNotExists(name)
|
||||
}
|
||||
|
||||
|
|
59
tx_test.go
59
tx_test.go
|
@ -43,7 +43,9 @@ func TestTx_Commit_ReadOnly(t *testing.T) {
|
|||
func TestTx_CreateBucket_ReadOnly(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.View(func(tx *Tx) error {
|
||||
assert.Equal(t, tx.CreateBucket([]byte("foo")), ErrTxNotWritable)
|
||||
b, err := tx.CreateBucket([]byte("foo"))
|
||||
assert.Nil(t, b)
|
||||
assert.Equal(t, ErrTxNotWritable, err)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
@ -54,7 +56,9 @@ func TestTx_CreateBucket_Closed(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
tx, _ := db.Begin(true)
|
||||
tx.Commit()
|
||||
assert.Equal(t, tx.CreateBucket([]byte("foo")), ErrTxClosed)
|
||||
b, err := tx.CreateBucket([]byte("foo"))
|
||||
assert.Nil(t, b)
|
||||
assert.Equal(t, ErrTxClosed, err)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -88,7 +92,9 @@ func TestTx_CreateBucket(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
// Create a bucket.
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NotNil(t, b)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
||||
|
@ -105,10 +111,21 @@ func TestTx_CreateBucket(t *testing.T) {
|
|||
func TestTx_CreateBucketIfNotExists(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucketIfNotExists([]byte("widgets")))
|
||||
assert.NoError(t, tx.CreateBucketIfNotExists([]byte("widgets")))
|
||||
assert.Equal(t, ErrBucketNameRequired, tx.CreateBucketIfNotExists([]byte{}))
|
||||
assert.Equal(t, ErrBucketNameRequired, tx.CreateBucketIfNotExists(nil))
|
||||
b, err := tx.CreateBucketIfNotExists([]byte("widgets"))
|
||||
assert.NotNil(t, b)
|
||||
assert.NoError(t, err)
|
||||
|
||||
b, err = tx.CreateBucketIfNotExists([]byte("widgets"))
|
||||
assert.NotNil(t, b)
|
||||
assert.NoError(t, err)
|
||||
|
||||
b, err = tx.CreateBucketIfNotExists([]byte{})
|
||||
assert.Nil(t, b)
|
||||
assert.Equal(t, ErrBucketNameRequired, err)
|
||||
|
||||
b, err = tx.CreateBucketIfNotExists(nil)
|
||||
assert.Nil(t, b)
|
||||
assert.Equal(t, ErrBucketNameRequired, err)
|
||||
return nil
|
||||
})
|
||||
|
||||
|
@ -126,13 +143,17 @@ func TestTx_CreateBucket_Exists(t *testing.T) {
|
|||
withOpenDB(func(db *DB, path string) {
|
||||
// Create a bucket.
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NotNil(t, b)
|
||||
assert.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
||||
// Create the same bucket again.
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.Equal(t, ErrBucketExists, tx.CreateBucket([]byte("widgets")))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.Nil(t, b)
|
||||
assert.Equal(t, ErrBucketExists, err)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
@ -142,7 +163,9 @@ func TestTx_CreateBucket_Exists(t *testing.T) {
|
|||
func TestTx_CreateBucket_NameRequired(t *testing.T) {
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
assert.Equal(t, ErrBucketNameRequired, tx.CreateBucket(nil))
|
||||
b, err := tx.CreateBucket(nil)
|
||||
assert.Nil(t, b)
|
||||
assert.Equal(t, ErrBucketNameRequired, err)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
@ -177,7 +200,9 @@ func TestTx_DeleteBucket(t *testing.T) {
|
|||
assert.Equal(t, []pgid{7, 6, root, 2}, db.freelist.all())
|
||||
|
||||
// Create the bucket again and make sure there's not a phantom value.
|
||||
assert.NoError(t, tx.CreateBucket([]byte("widgets")))
|
||||
b, err := tx.CreateBucket([]byte("widgets"))
|
||||
assert.NotNil(t, b)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, tx.Bucket([]byte("widgets")).Get([]byte("foo")))
|
||||
return nil
|
||||
})
|
||||
|
@ -220,7 +245,8 @@ func TestTx_OnCommit(t *testing.T) {
|
|||
db.Update(func(tx *Tx) error {
|
||||
tx.OnCommit(func() { x += 1 })
|
||||
tx.OnCommit(func() { x += 2 })
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
})
|
||||
assert.Equal(t, 3, x)
|
||||
|
@ -292,7 +318,8 @@ func benchmarkTxPutRandom(b *testing.B, total int) {
|
|||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
var tx *Tx
|
||||
var bucket *Bucket
|
||||
|
@ -323,7 +350,8 @@ func benchmarkTxPutSequential(b *testing.B, total int) {
|
|||
value := []byte(strings.Repeat("0", 64))
|
||||
withOpenDB(func(db *DB, path string) {
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
db.Update(func(tx *Tx) error {
|
||||
bucket := tx.Bucket([]byte("widgets"))
|
||||
|
@ -345,7 +373,8 @@ func ExampleTx_Rollback() {
|
|||
|
||||
// Create a bucket.
|
||||
db.Update(func(tx *Tx) error {
|
||||
return tx.CreateBucket([]byte("widgets"))
|
||||
_, err := tx.CreateBucket([]byte("widgets"))
|
||||
return err
|
||||
})
|
||||
|
||||
// Set a value for a key.
|
||||
|
|
Loading…
Reference in New Issue