19 unstable releases (3 breaking)
0.4.6 | Dec 18, 2023 |
---|---|
0.4.4 | Nov 22, 2023 |
0.3.13 | Jul 17, 2023 |
#70 in Database implementations
120 downloads per month
81KB
1K
SLoC
Important Update: This crate struct_db
has been renamed to native_db
to better reflect its functionality and purpose. Please update your dependencies to use native_db
for the latest features and updates.
Struct DB 🔧🔩
Provides a drop-in, fast, and embedded database solution based on redb, focusing on maintaining coherence between Rust types and stored data with minimal boilerplate. It supports multiple indexes, real-time watch with filters, schema migration, enjoy 😌🍃.
Features
- Almost as fast as the storage engine redb.
- Embedded database (Linux, macOS, Windows, Android, iOS).
- Support multiple indexes (unique secondary keys).
- Compatible with all Rust types (
enum
,struct
,tuple
etc.). - Query data (
get
,watch
,iter
etc.) using explicit type or type inference. - Real-time subscription with filters for
insert
,update
anddelete
operations. - Schema migration using native Rust coercion.
- Fully ACID-compliant transactions.
- Add your own serialization/deserialization logic planned* (e.g: zero-copy).
- Thread-safe.
Status
Early development. Not ready for production. Follow the roadmap for the 1.0 release.
How to use?
See docs.rs.
Example
use serde::{Deserialize, Serialize};
use struct_db::*;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[struct_db(
fn_primary_key(p_key), // required
fn_secondary_key(s_key), // optional
// ... other fn_secondary_key ...
)]
struct Data(u32, String);
impl Data {
// Returns primary key as big-endian bytes for consistent lexicographical ordering.
pub fn p_key(&self) -> Vec<u8> {
self.0.to_be_bytes().to_vec()
}
// Generates a secondary key combining the String field and the big-endian bytes of
// the primary key for versatile queries.
pub fn s_key(&self) -> Vec<u8> {
let mut s_key = self.1.as_bytes().to_vec();
s_key.extend_from_slice(&self.p_key().as_slice());
s_key
}
}
fn main() {
let mut db = Db::init_tmp("my_db_example").unwrap();
// Initialize the schema
db.define::<Data>();
// Insert data
let txn = db.transaction().unwrap();
{
let mut tables = txn.tables();
tables.insert(&txn, Data(1,"red".to_string())).unwrap();
tables.insert(&txn, Data(2,"red".to_string())).unwrap();
tables.insert(&txn, Data(3,"blue".to_string())).unwrap();
}
txn.commit().unwrap();
let txn_read = db.read_transaction().unwrap();
let mut tables = txn_read.tables();
// Retrieve data with p_key=3
let retrieve_data: Data = tables.primary_get(&txn_read, &3_u32.to_be_bytes()).unwrap().unwrap();
println!("data p_key='3' : {:?}", retrieve_data);
// Iterate data with s_key="red" String
for item in tables.secondary_iter_start_with::<Data>(&txn_read, DataKey::s_key, "red".as_bytes()).unwrap() {
println!("data s_key='1': {:?}", item);
}
// Remove data
let txn = db.transaction().unwrap();
{
let mut tables = txn.tables();
tables.remove(&txn, retrieve_data).unwrap();
}
txn.commit().unwrap();
}
Roadmap
The following features are planned before the 1.0 release
- Add benchmarks tests.
- Add documentation.
- Stable release of redb or implement another stable storage engine(s) for Linux, macOS, Windows, Android, iOS.
- Add support for custom serialization/deserialization logic.
- Add CI for Linux, macOS, Windows, Android, iOS.
- Use in a real-world project.
Contributors
Akshith Madhur 💻 |
Dependencies
~1.4–8.5MB
~82K SLoC