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,
impl<K, V> Isam<K, V>where
K: Serialize + DeserializeOwned + Ord + Clone + 'static,
V: Serialize + DeserializeOwned + Clone + 'static,
Sourcepub fn create(path: impl AsRef<Path>) -> IsamResult<Self>
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();Sourcepub fn open(path: impl AsRef<Path>) -> IsamResult<Self>
pub fn open(path: impl AsRef<Path>) -> IsamResult<Self>
Sourcepub fn begin_transaction(&self) -> IsamResult<Transaction<'_, K, V>>
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();Sourcepub fn insert(
&self,
txn: &mut Transaction<'_, K, V>,
key: K,
value: &V,
) -> IsamResult<()>
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();Sourcepub fn get(
&self,
txn: &mut Transaction<'_, K, V>,
key: &K,
) -> IsamResult<Option<V>>
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();Sourcepub fn update(
&self,
txn: &mut Transaction<'_, K, V>,
key: K,
value: &V,
) -> IsamResult<()>
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();Sourcepub fn delete(&self, txn: &mut Transaction<'_, K, V>, key: &K) -> IsamResult<()>
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();Sourcepub fn min_key(&self, txn: &mut Transaction<'_, K, V>) -> IsamResult<Option<K>>
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();Sourcepub fn max_key(&self, txn: &mut Transaction<'_, K, V>) -> IsamResult<Option<K>>
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();Sourcepub fn iter<'txn>(
&self,
txn: &'txn mut Transaction<'_, K, V>,
) -> IsamResult<IsamIter<'txn, K, V>>
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();Sourcepub fn range<'txn, R>(
&self,
txn: &'txn mut Transaction<'_, K, V>,
range: R,
) -> IsamResult<RangeIter<'txn, K, V>>where
R: RangeBounds<K>,
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();Sourcepub fn register_secondary_index<E>(
&self,
name: &str,
_extractor: E,
) -> IsamResult<SecondaryIndexHandle<K, V, E::Key>>
pub fn register_secondary_index<E>( &self, name: &str, _extractor: E, ) -> IsamResult<SecondaryIndexHandle<K, V, E::Key>>
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();Sourcepub fn key_schema_version(&self) -> IsamResult<u32>
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);Sourcepub fn val_schema_version(&self) -> IsamResult<u32>
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);Sourcepub fn compact(&self) -> IsamResult<()>
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();Sourcepub fn migrate_values<V2, F>(
self,
new_val_version: u32,
f: F,
) -> IsamResult<Isam<K, V2>>
pub fn migrate_values<V2, F>( self, new_val_version: u32, f: F, ) -> IsamResult<Isam<K, 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);Sourcepub fn migrate_keys<K2, F>(
self,
new_key_version: u32,
f: F,
) -> IsamResult<Isam<K2, V>>
pub fn migrate_keys<K2, F>( self, new_key_version: u32, f: F, ) -> IsamResult<Isam<K2, V>>
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);