highlandcows_isam/lib.rs
1//! # highlandcows-isam
2//!
3//! An ISAM (Indexed Sequential Access Method) library with ACID transactions
4//! and optional secondary indices.
5//!
6//! ## Quick start
7//!
8//! ```
9//! # use tempfile::TempDir;
10//! use highlandcows_isam::Isam;
11//!
12//! # let dir = TempDir::new().unwrap();
13//! # let path = dir.path().join("db");
14//! let db: Isam<String, String> = Isam::create(&path).unwrap();
15//! let mut txn = db.begin_transaction().unwrap();
16//! db.insert(&mut txn, "hello".to_string(), &"world".to_string()).unwrap();
17//! let v = db.get(&mut txn, &"hello".to_string()).unwrap();
18//! assert_eq!(v, Some("world".to_string()));
19//! txn.commit().unwrap();
20//! ```
21//!
22//! ## Secondary indices
23//!
24//! Secondary indices let you look up records by a field other than the primary
25//! key. Implement [`DeriveKey`] on a marker struct, then register it with
26//! [`Isam::register_secondary_index`] before any writes.
27//!
28//! ```
29//! # use tempfile::TempDir;
30//! use serde::{Serialize, Deserialize};
31//! use highlandcows_isam::{Isam, DeriveKey};
32//!
33//! #[derive(Serialize, Deserialize, Clone)]
34//! struct User { name: String, city: String }
35//!
36//! struct CityIndex;
37//! impl DeriveKey<User> for CityIndex {
38//! type Key = String;
39//! fn derive(u: &User) -> String { u.city.clone() }
40//! }
41//!
42//! # let dir = TempDir::new().unwrap();
43//! # let path = dir.path().join("users");
44//! let db: Isam<u64, User> = Isam::create(&path).unwrap();
45//! let city_idx = db.register_secondary_index("city", CityIndex).unwrap();
46//!
47//! let mut txn = db.begin_transaction().unwrap();
48//! db.insert(&mut txn, 1, &User { name: "Alice".into(), city: "London".into() }).unwrap();
49//! db.insert(&mut txn, 2, &User { name: "Bob".into(), city: "London".into() }).unwrap();
50//! db.insert(&mut txn, 3, &User { name: "Carol".into(), city: "Paris".into() }).unwrap();
51//! txn.commit().unwrap();
52//!
53//! let mut txn = db.begin_transaction().unwrap();
54//! let londoners = city_idx.lookup(&mut txn, &"London".to_string()).unwrap();
55//! assert_eq!(londoners.len(), 2);
56//! txn.commit().unwrap();
57//! ```
58//!
59//! ## Files on disk
60//!
61//! | File | Contents |
62//! |-----------------------|------------------------------------------------|
63//! | `*.idb` | Append-only data records (bincode) |
64//! | `*.idx` | On-disk B-tree index (page-based) |
65//! | `*_<name>.sidb` | Secondary index data store (one per index) |
66//! | `*_<name>.sidx` | Secondary index B-tree (one per index) |
67
68pub mod error;
69pub mod index;
70pub mod isam;
71pub mod manager;
72pub mod secondary_index;
73pub mod storage;
74pub mod store;
75pub mod transaction;
76
77// Re-export the main types at the crate root for convenience.
78pub use error::{IsamError, IsamResult};
79pub use isam::{Isam, IsamIter, RangeIter, SecondaryIndexHandle};
80pub use secondary_index::DeriveKey;
81pub use transaction::Transaction;