Struct jammdb::Bucket

source ·
pub struct Bucket<'b, 'tx: 'b> { /* private fields */ }
Expand description

A collection of data

Buckets contain a collection of data, sorted by key. The data can either be key / value pairs, or nested buckets. You can use buckets to get and put data, as well as get and create nested buckets.

You can use a Cursor to iterate over all the data in a bucket.

Buckets have an inner auto-incremented counter that keeps track of how many unique keys have been inserted into the bucket. You can access that using the next_int() function.

Examples

use jammdb::{DB, Data};

let db = DB::open("my.db")?;
let mut tx = db.tx(true)?;

// create a root-level bucket
let bucket = tx.create_bucket("my-bucket")?;

// create nested bucket
bucket.create_bucket("nested-bucket")?;

// insert a key / value pair (using &str)
bucket.put("key", "value");

// insert a key / value pair (using [u8])
bucket.put([1,2,3], [4,5,6]);

for data in bucket.cursor() {
    match data {
        Data::Bucket(b) => println!("found a bucket with the name {:?}", b.name()),
        Data::KeyValue(kv) => println!("found a kv pair {:?} {:?}", kv.key(), kv.value()),
    }
}

println!("Bucket next_int {:?}", bucket.next_int());

In order to keep the database flexible, it is possible to obtain references to multiple sub-buckets from a single parent. That means it is possible to obtain a reference to a bucket, then delete that bucket from the parent. Do not do this. If you try to use a bucket that has been deleted it will panic, and nobody wants that 🙃. The same is true for any iterator over a bucket as well, like a Cursor, [Buckets], or [KVPairs].

Implementations§

source§

impl<'b, 'tx> Bucket<'b, 'tx>

source

pub fn put<'a, T: ToBytes<'tx>, S: ToBytes<'tx>>( &'a self, key: T, value: S ) -> Result<Option<KVPair<'b, 'tx>>, Error>

Adds to or replaces key / value data in the bucket. Returns an error if the key currently exists but is a bucket instead of a key / value pair.

Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
let mut tx = db.tx(true)?;

// create a root-level bucket
let bucket = tx.create_bucket("my-bucket")?;

// insert data
bucket.put("123", "456")?;

// update data
bucket.put("123", "789")?;

bucket.create_bucket("nested-bucket")?;

assert!(bucket.put("nested-bucket", "data").is_err());
source

pub fn get<'a, T: AsRef<[u8]>>(&'a self, key: T) -> Option<Data<'b, 'tx>>

source

pub fn get_kv<'a, T: AsRef<[u8]>>(&'a self, key: T) -> Option<KVPair<'b, 'tx>>

source

pub fn delete<T: AsRef<[u8]>>(&self, key: T) -> Result<KVPair<'_, '_>, Error>

Deletes a key / value pair from the bucket

Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
let mut tx = db.tx(false)?;

let bucket = tx.get_bucket("my-bucket")?;
// check if data is there
assert!(bucket.get_kv("some-key").is_some());
// delete the key / value pair
bucket.delete("some-key")?;
// data should no longer exist
assert!(bucket.get_kv("some-key").is_none());
source

pub fn get_bucket<'a, T: ToBytes<'tx>>( &'a self, name: T ) -> Result<Bucket<'b, 'tx>, Error>

Gets an already created bucket.

Returns an error if

  1. the given key does not exist
  2. the key is for key / value data, not a bucket
Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
let mut tx = db.tx(false)?;

// get a root-level bucket
let bucket = tx.get_bucket("my-bucket")?;

// get nested bucket
let mut sub_bucket = bucket.get_bucket("nested-bucket")?;

// get nested bucket
let sub_sub_bucket = sub_bucket.get_bucket("double-nested-bucket")?;
source

pub fn create_bucket<'a, T: ToBytes<'tx>>( &'a self, name: T ) -> Result<Bucket<'b, 'tx>, Error>

Creates a new bucket.

Returns an error if

  1. the given key already exists
  2. It is in a read-only transaction
Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
let mut tx = db.tx(true)?;

// create a root-level bucket
let bucket = tx.create_bucket("my-bucket")?;

// create nested bucket
let mut sub_bucket = bucket.create_bucket("nested-bucket")?;

// create nested bucket
let mut sub_sub_bucket = sub_bucket.create_bucket("double-nested-bucket")?;
source

pub fn get_or_create_bucket<'a, T: ToBytes<'tx>>( &'a self, name: T ) -> Result<Bucket<'b, 'tx>, Error>

Creates a new bucket if it doesn’t exist

Returns an error if

  1. It is in a read-only transaction
Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
{
    let mut tx = db.tx(true)?;
    // create a root-level bucket
    let bucket = tx.get_or_create_bucket("my-bucket")?;
    tx.commit()?;
}
{
    let mut tx = db.tx(true)?;
    // get the existing a root-level bucket
    let bucket = tx.get_or_create_bucket("my-bucket")?;
}
source

pub fn delete_bucket<T: ToBytes<'tx>>(&self, key: T) -> Result<(), Error>

Deletes an bucket.

Returns an error if

  1. the given key does not exist
  2. the key is for key / value data, not a bucket
  3. It is in a read-only transaction
Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
let mut tx = db.tx(true)?;

// get a root-level bucket
let bucket = tx.get_bucket("my-bucket")?;

// delete nested bucket
bucket.delete_bucket("nested-bucket")?;
source

pub fn cursor<'a>(&'a self) -> Cursor<'b, 'tx>

Get a cursor to iterate over the bucket.

Examples
use jammdb::{DB, Data};

let db = DB::open("my.db")?;
let mut tx = db.tx(false)?;

let bucket = tx.get_bucket("my-bucket")?;

for data in bucket.cursor() {
    match data {
        Data::Bucket(b) => println!("found a bucket with the name {:?}", b.name()),
        Data::KeyValue(kv) => println!("found a kv pair {:?} {:?}", kv.key(), kv.value()),
    }
}
source

pub fn next_int(&self) -> u64

Returns the next integer for the bucket. The integer is automatically incremented each time a new key is added to the bucket. You can it as a unique key for the bucket, since it will increment each time you add something new. It will not increment if you put a key that already exists

Examples
use jammdb::{DB};

let db = DB::open("my.db")?;
let mut tx = db.tx(true)?;

// create a root-level bucket
let bucket = tx.create_bucket("my-bucket")?;
// starts at 0
assert_eq!(bucket.next_int(), 0);

let next_int = bucket.next_int();
bucket.put(next_int.to_be_bytes(), [0]);
// auto-incremented after inserting a key / value pair
assert_eq!(bucket.next_int(), 1);

bucket.put(0_u64.to_be_bytes(), [0, 0]);
// not incremented after updating a key / value pair
assert_eq!(bucket.next_int(), 1);

bucket.create_bucket("nested-bucket")?;
// auto-incremented after creating a nested bucket
assert_eq!(bucket.next_int(), 2);
source

pub fn buckets<'a>( &'a self ) -> impl Iterator<Item = (BucketName<'b, 'tx>, Bucket<'b, 'tx>)>

Iterator over the sub-buckets in this bucket.

source

pub fn kv_pairs<'a>(&'a self) -> impl Iterator<Item = KVPair<'b, 'tx>>

Iterator over the key / value pairs in this bucket.

source

pub fn range<'a, R>(&'a self, r: R) -> Range<'a, 'b, 'tx, R>where R: RangeBounds<&'a [u8]>,

Trait Implementations§

source§

impl<'b, 'tx> IntoIterator for Bucket<'b, 'tx>

§

type Item = Data<'b, 'tx>

The type of the elements being iterated over.
§

type IntoIter = Cursor<'b, 'tx>

Which kind of iterator are we turning this into?
source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more

Auto Trait Implementations§

§

impl<'b, 'tx> !RefUnwindSafe for Bucket<'b, 'tx>

§

impl<'b, 'tx> !Send for Bucket<'b, 'tx>

§

impl<'b, 'tx> !Sync for Bucket<'b, 'tx>

§

impl<'b, 'tx> Unpin for Bucket<'b, 'tx>

§

impl<'b, 'tx> !UnwindSafe for Bucket<'b, 'tx>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.