Isam

Struct Isam 

Source
pub struct Isam<K, V> { /* private fields */ }
Expand description

The public ISAM database handle.

Isam is Clone — every clone is another handle to the same underlying storage. Thread safety is provided by TransactionManager.

Implementations§

Source§

impl<K, V> Isam<K, V>
where K: Serialize + DeserializeOwned + Ord + Clone + 'static, V: Serialize + DeserializeOwned + Clone + 'static,

Source

pub fn create(path: impl AsRef<Path>) -> IsamResult<Self>

Create a new, empty database at path.

Two files are created: <path>.idb (data) and <path>.idx (index). Any existing files at those paths are truncated.

§Example
let db: Isam<u32, String> = Isam::create(&path).unwrap();
Source

pub fn open(path: impl AsRef<Path>) -> IsamResult<Self>

Open an existing database at path.

§Example
let db: Isam<u32, String> = Isam::open(&path).unwrap();
Source

pub fn begin_transaction(&self) -> IsamResult<Transaction<'_, K, V>>

Begin a new transaction.

The returned Transaction holds an exclusive lock on the database until it is committed, rolled back, or dropped. Dropping without committing automatically rolls back all changes made in the transaction.

§Example
let mut txn = db.begin_transaction().unwrap();
// ... perform operations ...
txn.commit().unwrap();
Source

pub fn insert( &self, txn: &mut Transaction<'_, K, V>, key: K, value: &V, ) -> IsamResult<()>

Insert a new key-value pair.

Returns IsamError::DuplicateKey if the key already exists.

§Example
let mut txn = db.begin_transaction().unwrap();
db.insert(&mut txn, 1u32, &"hello".to_string()).unwrap();
txn.commit().unwrap();
Source

pub fn get( &self, txn: &mut Transaction<'_, K, V>, key: &K, ) -> IsamResult<Option<V>>

Look up a key and return its value, or None if the key does not exist.

§Example
let mut txn = db.begin_transaction().unwrap();
assert_eq!(db.get(&mut txn, &1u32).unwrap(), Some("hello".to_string()));
assert_eq!(db.get(&mut txn, &99u32).unwrap(), None);
txn.commit().unwrap();
Source

pub fn update( &self, txn: &mut Transaction<'_, K, V>, key: K, value: &V, ) -> IsamResult<()>

Replace the value for an existing key.

Returns IsamError::KeyNotFound if the key does not exist.

§Example
let mut txn = db.begin_transaction().unwrap();
db.update(&mut txn, 1u32, &"new".to_string()).unwrap();
assert_eq!(db.get(&mut txn, &1u32).unwrap(), Some("new".to_string()));
txn.commit().unwrap();
Source

pub fn delete(&self, txn: &mut Transaction<'_, K, V>, key: &K) -> IsamResult<()>

Remove a key and its associated value.

Returns IsamError::KeyNotFound if the key does not exist.

§Example
let mut txn = db.begin_transaction().unwrap();
db.delete(&mut txn, &1u32).unwrap();
assert_eq!(db.get(&mut txn, &1u32).unwrap(), None);
txn.commit().unwrap();
Source

pub fn min_key(&self, txn: &mut Transaction<'_, K, V>) -> IsamResult<Option<K>>

Return the smallest key in the database, or None if empty.

§Example
let mut txn = db.begin_transaction().unwrap();
assert_eq!(db.min_key(&mut txn).unwrap(), Some(1u32));
txn.commit().unwrap();
Source

pub fn max_key(&self, txn: &mut Transaction<'_, K, V>) -> IsamResult<Option<K>>

Return the largest key in the database, or None if empty.

§Example
let mut txn = db.begin_transaction().unwrap();
assert_eq!(db.max_key(&mut txn).unwrap(), Some(3u32));
txn.commit().unwrap();
Source

pub fn iter<'txn>( &self, txn: &'txn mut Transaction<'_, K, V>, ) -> IsamResult<IsamIter<'txn, K, V>>

Return a key-ordered iterator over all records.

The iterator borrows txn for its lifetime, so no other operations can be performed on the database until the iterator is dropped.

§Example
let mut txn = db.begin_transaction().unwrap();
let keys: Vec<u32> = db.iter(&mut txn).unwrap()
    .map(|r| r.unwrap().0)
    .collect();
assert_eq!(keys, vec![1, 2, 3]);
txn.commit().unwrap();
Source

pub fn range<'txn, R>( &self, txn: &'txn mut Transaction<'_, K, V>, range: R, ) -> IsamResult<RangeIter<'txn, K, V>>
where R: RangeBounds<K>,

Return a key-ordered iterator over records whose keys fall within range.

Accepts any of Rust’s built-in range expressions: a..b, a..=b, a.., ..b, ..=b, ...

The iterator borrows txn for its lifetime, so no other operations can be performed on the database until the iterator is dropped.

§Example
let mut txn = db.begin_transaction().unwrap();
let keys: Vec<u32> = db.range(&mut txn, 3u32..=7).unwrap()
    .map(|r| r.unwrap().0)
    .collect();
assert_eq!(keys, vec![3, 4, 5, 6, 7]);
txn.commit().unwrap();
Source

pub fn register_secondary_index<E>( &self, name: &str, _extractor: E, ) -> IsamResult<SecondaryIndexHandle<K, V, E::Key>>
where E: DeriveKey<V>, K: Send, V: Send,

Register a secondary index on this database.

Must be called before any writes. All secondary indices must be re-registered each time the database is opened.

Returns a SecondaryIndexHandle that can be used to query the index.

§Deadlock warning

Acquires the database lock internally. Must not be called while a Transaction is live on the same thread.

§Example
use serde::{Serialize, Deserialize};
use highlandcows_isam::{Isam, DeriveKey};

#[derive(Serialize, Deserialize, Clone)]
struct User { name: String, city: String }

struct CityIndex;
impl DeriveKey<User> for CityIndex {
    type Key = String;
    fn derive(u: &User) -> String { u.city.clone() }
}

let db: Isam<u64, User> = Isam::create(&path).unwrap();

// Register before any writes; re-register on every open.
let city_idx = db.register_secondary_index("city", CityIndex).unwrap();

let mut txn = db.begin_transaction().unwrap();
db.insert(&mut txn, 1, &User { name: "Alice".into(), city: "London".into() }).unwrap();
txn.commit().unwrap();

let mut txn = db.begin_transaction().unwrap();
let results = city_idx.lookup(&mut txn, &"London".to_string()).unwrap();
assert_eq!(results.len(), 1);
txn.commit().unwrap();
Source

pub fn key_schema_version(&self) -> IsamResult<u32>

Return the key schema version stored in the index metadata.

Schema versions are set by migrate_keys and default to 0 for newly created databases.

§Deadlock warning

Acquires the database lock internally. Must not be called while a Transaction is live on the same thread.

§Example
assert_eq!(db.key_schema_version().unwrap(), 0);
Source

pub fn val_schema_version(&self) -> IsamResult<u32>

Return the value schema version stored in the index metadata.

Schema versions are set by migrate_values and default to 0 for newly created databases.

§Deadlock warning

Acquires the database lock internally. Must not be called while a Transaction is live on the same thread.

§Example
assert_eq!(db.val_schema_version().unwrap(), 0);
Source

pub fn compact(&self) -> IsamResult<()>

Compact the database, removing tombstones and stale values.

Rewrites the data and index files atomically via temp-file rename, then re-opens them in place.

§Deadlock warning

Acquires the database lock internally. Must not be called while a Transaction is live on the same thread. These operations are intended for offline administration — commit or roll back all open transactions before calling them.

§Example
// All transactions committed — safe to compact.
db.compact().unwrap();
Source

pub fn migrate_values<V2, F>( self, new_val_version: u32, f: F, ) -> IsamResult<Isam<K, V2>>
where V2: Serialize + DeserializeOwned + Clone + 'static, F: FnMut(V) -> IsamResult<V2>,

Rewrite every value through f, bump the val schema version, and return a ready-to-use Isam<K, V2>. Consumes self.

Records are rewritten to new temp files and atomically renamed into place. The key schema version is preserved.

§Deadlock warning

Acquires the database lock internally. Must not be called while a Transaction is live on the same thread. These operations are intended for offline administration — commit or roll back all open transactions before calling them.

§Example
let db: Isam<u32, String> = Isam::create(&path).unwrap();
// Migrate String values → u64, setting val schema version to 1.
let db2: Isam<u32, u64> = db
    .migrate_values(1, |s: String| Ok(s.parse::<u64>().unwrap()))
    .unwrap();
assert_eq!(db2.val_schema_version().unwrap(), 1);
Source

pub fn migrate_keys<K2, F>( self, new_key_version: u32, f: F, ) -> IsamResult<Isam<K2, V>>
where K2: Serialize + DeserializeOwned + Ord + Clone + 'static, F: FnMut(K) -> IsamResult<K2>,

Rewrite every key through f, bump the key schema version, re-sort by K2::Ord, rebuild the index, and return a ready-to-use Isam<K2, V>. Consumes self.

Records are rewritten to new temp files and atomically renamed into place. The value schema version is preserved.

§Deadlock warning

Acquires the database lock internally. Must not be called while a Transaction is live on the same thread. These operations are intended for offline administration — commit or roll back all open transactions before calling them.

§Example
let db: Isam<u32, String> = Isam::create(&path).unwrap();
// Migrate u32 keys → String, setting key schema version to 1.
let db2: Isam<String, String> = db
    .migrate_keys(1, |k: u32| Ok(format!("{k}")))
    .unwrap();
assert_eq!(db2.key_schema_version().unwrap(), 1);

Trait Implementations§

Source§

impl<K, V> Clone for Isam<K, V>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<K, V> Freeze for Isam<K, V>

§

impl<K, V> RefUnwindSafe for Isam<K, V>

§

impl<K, V> Send for Isam<K, V>
where V: Send, K: Send,

§

impl<K, V> Sync for Isam<K, V>
where V: Send, K: Send,

§

impl<K, V> Unpin for Isam<K, V>

§

impl<K, V> UnwindSafe for Isam<K, V>

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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 T
where 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

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 T
where U: TryFrom<T>,

Source§

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.