...
This commit is contained in:
parent
e3ec26a6ef
commit
a8ef07bb3f
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "herodb"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
description = "A database library built on top of ourdb with model support"
|
||||
license = "MIT"
|
||||
authors = ["HeroCode Team"]
|
||||
|
83
herodb/examples/minimal_ourdb_example.rs
Normal file
83
herodb/examples/minimal_ourdb_example.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use herodb::db::{DB, DBBuilder, Model};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use chrono::Utc;
|
||||
|
||||
// Define a simple Product model
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct SimpleProduct {
|
||||
id: u32,
|
||||
name: String,
|
||||
description: String,
|
||||
price: f64,
|
||||
created_at: chrono::DateTime<Utc>,
|
||||
}
|
||||
|
||||
// Implement the Model trait for SimpleProduct
|
||||
impl Model for SimpleProduct {
|
||||
fn get_id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn db_prefix() -> &'static str {
|
||||
"simple_product"
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("OurDB Minimal Example");
|
||||
println!("====================\n");
|
||||
|
||||
// Create a temporary directory for the database
|
||||
let db_path = std::env::temp_dir().join("herodb_minimal_example");
|
||||
std::fs::create_dir_all(&db_path)?;
|
||||
|
||||
println!("Creating database at: {}", db_path.display());
|
||||
|
||||
// Create a new database with SimpleProduct model registered
|
||||
let db = DBBuilder::new(db_path.clone())
|
||||
.register_model::<SimpleProduct>()
|
||||
.build()?;
|
||||
|
||||
println!("Database created successfully");
|
||||
|
||||
// Create a product
|
||||
let product = SimpleProduct {
|
||||
id: 1,
|
||||
name: "Test Product".to_string(),
|
||||
description: "A test product for our minimal OurDB example".to_string(),
|
||||
price: 99.99,
|
||||
created_at: Utc::now(),
|
||||
};
|
||||
|
||||
println!("\nCreated product: {}", product.name);
|
||||
println!("Product ID: {}", product.get_id());
|
||||
|
||||
// Insert the product into the database
|
||||
db.set(&product)?;
|
||||
println!("Product saved to database");
|
||||
|
||||
// Retrieve the product from the database
|
||||
let retrieved_product = db.get::<SimpleProduct>(product.get_id())?;
|
||||
println!("\nRetrieved product from database:");
|
||||
println!(" Name: {}", retrieved_product.name);
|
||||
println!(" Description: {}", retrieved_product.description);
|
||||
println!(" Price: ${}", retrieved_product.price);
|
||||
|
||||
// Delete the product
|
||||
db.delete::<SimpleProduct>(product.get_id())?;
|
||||
println!("\nProduct deleted from database");
|
||||
|
||||
// Try to retrieve the deleted product (should fail)
|
||||
match db.get::<SimpleProduct>(product.get_id()) {
|
||||
Ok(_) => println!("Product still exists (unexpected)"),
|
||||
Err(e) => println!("Verified deletion: {}", e),
|
||||
}
|
||||
|
||||
println!("\nExample completed successfully!");
|
||||
|
||||
// Clean up
|
||||
std::fs::remove_dir_all(&db_path)?;
|
||||
println!("Cleaned up database directory");
|
||||
|
||||
Ok(())
|
||||
}
|
@ -21,6 +21,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Create a currency for pricing
|
||||
let usd = CurrencyBuilder::new()
|
||||
.id(1) // Add an ID for the currency
|
||||
.amount(99.99)
|
||||
.currency_code("USD")
|
||||
.build()
|
||||
|
@ -1,144 +0,0 @@
|
||||
use bincode;
|
||||
use brotli::{CompressorReader, Decompressor};
|
||||
use rhai::CustomType;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sled;
|
||||
use std::fmt::Debug;
|
||||
use std::io::Read;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::Path;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors that can occur during Sled database operations
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SledDBError {
|
||||
#[error("Sled database error: {0}")]
|
||||
SledError(#[from] sled::Error),
|
||||
#[error("Serialization/Deserialization error: {0}")]
|
||||
SerdeError(#[from] bincode::Error),
|
||||
#[error("Compression/Decompression error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
#[error("Record not found for ID: {0}")]
|
||||
NotFound(String),
|
||||
#[error("Type mismatch during deserialization")]
|
||||
TypeError,
|
||||
#[error("General database error: {0}")]
|
||||
GeneralError(String),
|
||||
}
|
||||
|
||||
/// Result type for Sled DB operations
|
||||
pub type SledDBResult<T> = Result<T, SledDBError>;
|
||||
|
||||
/// Trait for models that can be stored in the Sled database.
|
||||
/// Requires `Serialize` and `Deserialize` for the underlying storage mechanism.
|
||||
pub trait Storable: Serialize + for<'de> Deserialize<'de> + Sized {
|
||||
/// Serializes and compresses the instance using bincode and brotli.
|
||||
fn dump(&self) -> SledDBResult<Vec<u8>> {
|
||||
let encoded: Vec<u8> = bincode::serialize(self)?;
|
||||
|
||||
let mut compressed = Vec::new();
|
||||
// Default Brotli parameters: quality 5, lgwin 22 (window size)
|
||||
const BROTLI_QUALITY: u32 = 5;
|
||||
const BROTLI_LGWIN: u32 = 22;
|
||||
const BUFFER_SIZE: usize = 4096; // 4KB buffer
|
||||
|
||||
let mut compressor =
|
||||
CompressorReader::new(&encoded[..], BUFFER_SIZE, BROTLI_QUALITY, BROTLI_LGWIN);
|
||||
compressor.read_to_end(&mut compressed)?;
|
||||
|
||||
Ok(compressed)
|
||||
}
|
||||
|
||||
/// Deserializes and decompresses data from bytes into an instance.
|
||||
fn load_from_bytes(data: &[u8]) -> SledDBResult<Self> {
|
||||
let mut decompressed = Vec::new();
|
||||
const BUFFER_SIZE: usize = 4096; // 4KB buffer
|
||||
|
||||
let mut decompressor = Decompressor::new(data, BUFFER_SIZE);
|
||||
decompressor.read_to_end(&mut decompressed)?;
|
||||
|
||||
let decoded: Self = bincode::deserialize(&decompressed)?;
|
||||
Ok(decoded)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait identifying a model suitable for the Sled database.
|
||||
/// The 'static lifetime bound is required for type identification via Any
|
||||
pub trait SledModel: Storable + Debug + Clone + Send + Sync + 'static {
|
||||
/// Returns the unique ID for this model instance, used as the key in Sled.
|
||||
fn get_id(&self) -> String;
|
||||
|
||||
/// Returns a prefix used for this model type in the Sled database.
|
||||
/// Helps to logically separate different model types.
|
||||
fn db_prefix() -> &'static str;
|
||||
}
|
||||
|
||||
/// A generic database layer on top of Sled.
|
||||
#[derive(Clone)]
|
||||
pub struct SledDB<T: SledModel> {
|
||||
db: sled::Db,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: SledModel> SledDB<T> {
|
||||
/// Opens or creates a Sled database at the specified path.
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> SledDBResult<Self> {
|
||||
let db = sled::open(path)?;
|
||||
Ok(Self {
|
||||
db,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
/// Generates the full Sled key using the model's prefix and ID.
|
||||
fn get_full_key(id: &str) -> Vec<u8> {
|
||||
format!("{}:{}", T::db_prefix(), id).into_bytes()
|
||||
}
|
||||
|
||||
/// Inserts or updates a model instance in the database.
|
||||
pub fn insert(&self, model: &T) -> SledDBResult<()> {
|
||||
let key = Self::get_full_key(&model.get_id());
|
||||
let value = model.dump()?;
|
||||
self.db.insert(key, value)?;
|
||||
// Optionally force a disk flush for durability, but it impacts performance.
|
||||
// self.db.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieves a model instance by its ID.
|
||||
pub fn get(&self, id: &str) -> SledDBResult<T> {
|
||||
let key = Self::get_full_key(id);
|
||||
match self.db.get(&key)? {
|
||||
Some(ivec) => T::load_from_bytes(&ivec),
|
||||
None => Err(SledDBError::NotFound(id.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes a model instance by its ID.
|
||||
pub fn delete(&self, id: &str) -> SledDBResult<()> {
|
||||
let key = Self::get_full_key(id);
|
||||
match self.db.remove(&key)? {
|
||||
Some(_) => Ok(()),
|
||||
None => Err(SledDBError::NotFound(id.to_string())),
|
||||
}
|
||||
// Optionally flush after delete
|
||||
// self.db.flush()?;
|
||||
}
|
||||
|
||||
/// Lists all models of this type.
|
||||
/// Warning: This can be inefficient for large datasets as it loads all models into memory.
|
||||
pub fn list(&self) -> SledDBResult<Vec<T>> {
|
||||
let prefix = format!("{}:", T::db_prefix());
|
||||
let mut models = Vec::new();
|
||||
for result in self.db.scan_prefix(prefix.as_bytes()) {
|
||||
let (_key, value) = result?;
|
||||
models.push(T::load_from_bytes(&value)?);
|
||||
}
|
||||
Ok(models)
|
||||
}
|
||||
|
||||
/// Provides access to the underlying Sled Db instance for advanced operations.
|
||||
pub fn raw_db(&self) -> &sled::Db {
|
||||
&self.db
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
ere/// Macro to implement typed access methods on the DB struct for a given model
|
||||
//! Macros for implementing model methods
|
||||
|
||||
/// Macro to implement typed access methods on the DB struct for a given model
|
||||
#[macro_export]
|
||||
macro_rules! impl_model_methods {
|
||||
($model:ty, $singular:ident, $plural:ident) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
s using// Export the error module
|
||||
// Export the error module
|
||||
pub mod error;
|
||||
pub use error::{DbError, DbResult};
|
||||
|
||||
@ -14,5 +14,8 @@ pub use store::{DbOperations, OurDbStore};
|
||||
pub mod db;
|
||||
pub use db::{DB, DBBuilder, ModelRegistration, ModelRegistrar};
|
||||
|
||||
// Export the base module (compatibility layer for migration)
|
||||
pub mod base;
|
||||
|
||||
// Export macros for model methods
|
||||
pub mod macros;
|
||||
|
178
ourdb_example/Cargo.lock
generated
Normal file
178
ourdb_example/Cargo.lock
generated
Normal file
@ -0,0 +1,178 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "ourdb"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"log",
|
||||
"rand",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ourdb_example"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ourdb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
7
ourdb_example/Cargo.toml
Normal file
7
ourdb_example/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "ourdb_example"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ourdb = { path = "../ourdb" }
|
74
ourdb_example/src/main.rs
Normal file
74
ourdb_example/src/main.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use ourdb::{OurDB, OurDBConfig, OurDBSetArgs};
|
||||
use std::env::temp_dir;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Standalone OurDB Example");
|
||||
println!("=======================\n");
|
||||
|
||||
// Create a temporary directory for the database
|
||||
let timestamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
let db_path = temp_dir().join(format!("ourdb_example_{}", timestamp));
|
||||
std::fs::create_dir_all(&db_path)?;
|
||||
|
||||
println!("Creating database at: {}", db_path.display());
|
||||
|
||||
// Create a new OurDB instance
|
||||
let config = OurDBConfig {
|
||||
path: db_path.clone(),
|
||||
incremental_mode: true,
|
||||
file_size: None,
|
||||
keysize: None,
|
||||
reset: Some(false),
|
||||
};
|
||||
|
||||
let mut db = OurDB::new(config)?;
|
||||
println!("Database created successfully");
|
||||
|
||||
// Store some data
|
||||
let test_data = b"Hello, OurDB!";
|
||||
let id = db.set(OurDBSetArgs { id: None, data: test_data })?;
|
||||
println!("\nStored data with ID: {}", id);
|
||||
|
||||
// Retrieve the data
|
||||
let retrieved = db.get(id)?;
|
||||
println!("Retrieved data: {}", String::from_utf8_lossy(&retrieved));
|
||||
|
||||
// Update the data
|
||||
let updated_data = b"Updated data in OurDB!";
|
||||
db.set(OurDBSetArgs { id: Some(id), data: updated_data })?;
|
||||
println!("\nUpdated data with ID: {}", id);
|
||||
|
||||
// Retrieve the updated data
|
||||
let retrieved = db.get(id)?;
|
||||
println!("Retrieved updated data: {}", String::from_utf8_lossy(&retrieved));
|
||||
|
||||
// Get history
|
||||
let history = db.get_history(id, 2)?;
|
||||
println!("\nHistory for ID {}:", id);
|
||||
for (i, data) in history.iter().enumerate() {
|
||||
println!(" Version {}: {}", i + 1, String::from_utf8_lossy(data));
|
||||
}
|
||||
|
||||
// Delete the data
|
||||
db.delete(id)?;
|
||||
println!("\nDeleted data with ID: {}", id);
|
||||
|
||||
// Try to retrieve the deleted data (should fail)
|
||||
match db.get(id) {
|
||||
Ok(_) => println!("Data still exists (unexpected)"),
|
||||
Err(e) => println!("Verified deletion: {}", e),
|
||||
}
|
||||
|
||||
println!("\nExample completed successfully!");
|
||||
|
||||
// Clean up
|
||||
db.close()?;
|
||||
std::fs::remove_dir_all(&db_path)?;
|
||||
println!("Cleaned up database directory");
|
||||
|
||||
Ok(())
|
||||
}
|
74
standalone_ourdb_example.rs
Normal file
74
standalone_ourdb_example.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use ourdb::{OurDB, OurDBConfig, OurDBSetArgs};
|
||||
use std::env::temp_dir;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Standalone OurDB Example");
|
||||
println!("=======================\n");
|
||||
|
||||
// Create a temporary directory for the database
|
||||
let timestamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
let db_path = temp_dir().join(format!("ourdb_example_{}", timestamp));
|
||||
std::fs::create_dir_all(&db_path)?;
|
||||
|
||||
println!("Creating database at: {}", db_path.display());
|
||||
|
||||
// Create a new OurDB instance
|
||||
let config = OurDBConfig {
|
||||
path: db_path.clone(),
|
||||
incremental_mode: true,
|
||||
file_size: None,
|
||||
keysize: None,
|
||||
reset: Some(false),
|
||||
};
|
||||
|
||||
let mut db = OurDB::new(config)?;
|
||||
println!("Database created successfully");
|
||||
|
||||
// Store some data
|
||||
let test_data = b"Hello, OurDB!";
|
||||
let id = db.set(OurDBSetArgs { id: None, data: test_data })?;
|
||||
println!("\nStored data with ID: {}", id);
|
||||
|
||||
// Retrieve the data
|
||||
let retrieved = db.get(id)?;
|
||||
println!("Retrieved data: {}", String::from_utf8_lossy(&retrieved));
|
||||
|
||||
// Update the data
|
||||
let updated_data = b"Updated data in OurDB!";
|
||||
db.set(OurDBSetArgs { id: Some(id), data: updated_data })?;
|
||||
println!("\nUpdated data with ID: {}", id);
|
||||
|
||||
// Retrieve the updated data
|
||||
let retrieved = db.get(id)?;
|
||||
println!("Retrieved updated data: {}", String::from_utf8_lossy(&retrieved));
|
||||
|
||||
// Get history
|
||||
let history = db.get_history(id, 2)?;
|
||||
println!("\nHistory for ID {}:", id);
|
||||
for (i, data) in history.iter().enumerate() {
|
||||
println!(" Version {}: {}", i + 1, String::from_utf8_lossy(data));
|
||||
}
|
||||
|
||||
// Delete the data
|
||||
db.delete(id)?;
|
||||
println!("\nDeleted data with ID: {}", id);
|
||||
|
||||
// Try to retrieve the deleted data (should fail)
|
||||
match db.get(id) {
|
||||
Ok(_) => println!("Data still exists (unexpected)"),
|
||||
Err(e) => println!("Verified deletion: {}", e),
|
||||
}
|
||||
|
||||
println!("\nExample completed successfully!");
|
||||
|
||||
// Clean up
|
||||
db.close()?;
|
||||
std::fs::remove_dir_all(&db_path)?;
|
||||
println!("Cleaned up database directory");
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user