aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bucket.go1
-rw-r--r--buckets.go5
-rw-r--r--db.go19
-rw-r--r--rwtransaction.go14
-rw-r--r--rwtransaction_test.go26
5 files changed, 64 insertions, 1 deletions
diff --git a/bucket.go b/bucket.go
index 414d260..9c9ee29 100644
--- a/bucket.go
+++ b/bucket.go
@@ -13,6 +13,7 @@ type Bucket struct {
// bucket represents the on-file representation of a bucket.
type bucket struct {
root pgid
+ sequence uint64
}
// Name returns the name of the bucket.
diff --git a/buckets.go b/buckets.go
index bb4b960..6d9f27c 100644
--- a/buckets.go
+++ b/buckets.go
@@ -63,7 +63,10 @@ func (b *buckets) read(p *page) {
// Associate keys and items.
for index, key := range keys {
- b.items[key] = &bucket{items[index].root}
+ b.items[key] = &bucket{
+ root: items[index].root,
+ sequence: items[index].sequence,
+ }
}
}
diff --git a/db.go b/db.go
index bb9bbf6..a25e41a 100644
--- a/db.go
+++ b/db.go
@@ -384,6 +384,25 @@ func (db *DB) DeleteBucket(name string) error {
return t.Commit()
}
+// NextSequence returns an autoincrementing integer for the bucket.
+// This function can return an error if the bucket does not exist.
+func (db *DB) NextSequence(name string) (int, error) {
+ t, err := db.RWTransaction()
+ if err != nil {
+ return 0, err
+ }
+
+ seq, err := t.NextSequence(name)
+ if err != nil {
+ t.Rollback()
+ return 0, err
+ }
+ if err := t.Commit(); err != nil {
+ return 0, err
+ }
+ return seq, nil
+}
+
// Get retrieves the value for a key in a bucket.
// Returns an error if the key does not exist.
func (db *DB) Get(name string, key []byte) ([]byte, error) {
diff --git a/rwtransaction.go b/rwtransaction.go
index 92d05a8..568960a 100644
--- a/rwtransaction.go
+++ b/rwtransaction.go
@@ -66,6 +66,20 @@ func (t *RWTransaction) DeleteBucket(name string) error {
return nil
}
+// NextSequence returns an autoincrementing integer for the bucket.
+func (t *RWTransaction) NextSequence(name string) (int, error) {
+ // Check if bucket already exists.
+ b := t.Bucket(name)
+ if b == nil {
+ return 0, BucketNotFoundError
+ }
+
+ // Increment and return the sequence.
+ b.bucket.sequence++
+
+ return int(b.bucket.sequence), nil
+}
+
// Put sets the value for a key inside of the named bucket.
// If the key exist then its previous value will be overwritten.
// Returns an error if the bucket is not found, if the key is blank, if the key is too large, or if the value is too large.
diff --git a/rwtransaction_test.go b/rwtransaction_test.go
index 1ce3f70..fa254d8 100644
--- a/rwtransaction_test.go
+++ b/rwtransaction_test.go
@@ -72,6 +72,32 @@ func TestRWTransactionDeleteBucket(t *testing.T) {
t.Skip("pending") // TODO(benbjohnson)
}
+// Ensure that a bucket can return an autoincrementing sequence.
+func TestRWTransactionNextSequence(t *testing.T) {
+ withOpenDB(func(db *DB, path string) {
+ db.CreateBucket("widgets")
+ db.CreateBucket("woojits")
+
+ // Make sure sequence increments.
+ seq, err := db.NextSequence("widgets")
+ assert.NoError(t, err)
+ assert.Equal(t, seq, 1)
+ seq, err = db.NextSequence("widgets")
+ assert.NoError(t, err)
+ assert.Equal(t, seq, 2)
+
+ // Buckets should be separate.
+ seq, err = db.NextSequence("woojits")
+ assert.NoError(t, err)
+ assert.Equal(t, seq, 1)
+
+ // Missing buckets return an error.
+ seq, err = db.NextSequence("no_such_bucket")
+ assert.Equal(t, err, BucketNotFoundError)
+ assert.Equal(t, seq, 0)
+ })
+}
+
// Ensure that an error is returned when inserting into a bucket that doesn't exist.
func TestRWTransactionPutBucketNotFound(t *testing.T) {
t.Skip("pending") // TODO(benbjohnson)