From c66158101b0c7e9550e7d47379b53b312d8d7c10 Mon Sep 17 00:00:00 2001 From: Gwo Tzu-Hsing Date: Tue, 30 Jul 2024 14:14:52 +0800 Subject: [PATCH] feat: complete example --- .github/workflows/ci.yml | 2 +- examples/declare.rs | 69 ++++++++++++++++++++++++++++++++-------- src/lib.rs | 5 +-- src/ondisk/sstable.rs | 6 ++-- src/stream/mod.rs | 2 +- src/transaction.rs | 44 +++++++++++-------------- 6 files changed, 83 insertions(+), 45 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f254f11f..454ce1b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: - name: Run cargo test uses: actions-rs/cargo@v1 with: - command: test + command: test --all-features # 2 fmt: name: Rust fmt diff --git a/examples/declare.rs b/examples/declare.rs index 91e2c4d3..fe0fbacb 100644 --- a/examples/declare.rs +++ b/examples/declare.rs @@ -1,21 +1,64 @@ -use morseldb::morsel_record; +use std::ops::Bound; + +use futures_util::stream::StreamExt; + +use morseldb::executor::tokio::TokioExecutor; +use morseldb::{morsel_record, Projection, DB}; // Tips: must be public #[morsel_record] -pub struct Post { +pub struct User { #[primary_key] name: String, - vu8: u8, - vu16: u16, - vu32: u32, - vu64: u64, - vi8: i8, - vi16: i16, - vi32: i32, - vi64: i64, - vbool: bool, + // email: Option, + age: u8, } -fn main() { - println!("Hello, world!"); +#[tokio::main] +async fn main() { + let db = DB::::new("./db_path/users".into(), TokioExecutor::default()) + .await + .unwrap(); + + { + // morseldb supports transaction + let mut txn = db.transaction().await; + + // set with owned value + txn.set(User { + name: "Alice".into(), + // email: None, + age: 22, + }); + + // get from primary key + let name = "Alice".into(); + let user = txn.get(&name, Projection::All).await.unwrap(); + assert!(user.is_some()); + assert_eq!(user.unwrap().get().age, Some(22)); + + let upper = "Blob".into(); + let mut scan = txn + .scan((Bound::Included(&name), Bound::Excluded(&upper))) + .await + .projection(vec![1]) + .take() + .await + .unwrap(); + loop { + let user = scan.next().await.transpose().unwrap(); + match user { + Some(entry) => { + assert_eq!( + entry.value(), + Some(UserRef { + name: "Alice", + age: Some(22), + }) + ); + } + None => break, + } + } + } } diff --git a/src/lib.rs b/src/lib.rs index 90b25942..bd3f8581 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,8 @@ where R: Record + Send, E: Executor, { - pub async fn new(option: Arc, executor: E) -> Result> { + pub async fn new(option: DbOption, executor: E) -> Result> { + let option = Arc::new(option); E::create_dir_all(&option.path).await?; let schema = Arc::new(RwLock::new(Schema::default())); @@ -507,7 +508,7 @@ pub(crate) mod tests { } pub(crate) async fn get_test_record_batch( - option: Arc, + option: DbOption, executor: E, ) -> RecordBatch { let db: DB = DB::new(option, executor).await.unwrap(); diff --git a/src/ondisk/sstable.rs b/src/ondisk/sstable.rs index de6e7ba2..69a71f6e 100644 --- a/src/ondisk/sstable.rs +++ b/src/ondisk/sstable.rs @@ -157,7 +157,7 @@ pub(crate) mod tests { async fn write_sstable() { let temp_dir = tempfile::tempdir().unwrap(); let record_batch = get_test_record_batch::( - Arc::new(DbOption::from(temp_dir.path())), + DbOption::from(temp_dir.path()), TokioExecutor::new(), ) .await; @@ -184,7 +184,7 @@ pub(crate) mod tests { async fn projection_query() { let temp_dir = tempfile::tempdir().unwrap(); let record_batch = get_test_record_batch::( - Arc::new(DbOption::from(temp_dir.path())), + DbOption::from(temp_dir.path()), TokioExecutor::new(), ) .await; @@ -255,7 +255,7 @@ pub(crate) mod tests { async fn projection_scan() { let temp_dir = tempfile::tempdir().unwrap(); let record_batch = get_test_record_batch::( - Arc::new(DbOption::from(temp_dir.path())), + DbOption::from(temp_dir.path()), TokioExecutor::new(), ) .await; diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 45e06746..b5ed8f2d 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -55,7 +55,7 @@ where } } - pub(crate) fn value(&self) -> Option> { + pub fn value(&self) -> Option> { match self { Entry::Transaction((_, value)) => value.as_ref().map(R::as_record_ref), Entry::Mutable(entry) => entry.value().as_ref().map(R::as_record_ref), diff --git a/src/transaction.rs b/src/transaction.rs index 542cf062..0b7ebc97 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -85,7 +85,7 @@ where if entry.value().is_none() { None } else { - TransactionEntry::Stream(entry).into() + Some(TransactionEntry::Stream(entry)) } }), }) @@ -159,12 +159,12 @@ impl<'entry, R> TransactionEntry<'entry, R> where R: Record, { - pub fn get(&self) -> Option> { + pub fn get(&self) -> R::Ref<'_> { match self { - TransactionEntry::Stream(entry) => entry.value(), + TransactionEntry::Stream(entry) => entry.value().unwrap(), TransactionEntry::Local(value) => { // Safety: shorter lifetime must be safe - Some(unsafe { transmute::, R::Ref<'_>>(*value) }) + unsafe { transmute::, R::Ref<'_>>(*value) } } } } @@ -202,12 +202,10 @@ mod tests { async fn transaction_read_write() { let temp_dir = TempDir::new().unwrap(); - let db = DB::::new( - Arc::new(DbOption::from(temp_dir.path())), - TokioExecutor::new(), - ) - .await - .unwrap(); + let db = + DB::::new(DbOption::from(temp_dir.path()), TokioExecutor::new()) + .await + .unwrap(); { let mut txn1 = db.transaction().await; txn1.set("foo".to_string()); @@ -238,12 +236,10 @@ mod tests { async fn write_conflicts() { let temp_dir = TempDir::new().unwrap(); - let db = DB::::new( - Arc::new(DbOption::from(temp_dir.path())), - TokioExecutor::new(), - ) - .await - .unwrap(); + let db = + DB::::new(DbOption::from(temp_dir.path()), TokioExecutor::new()) + .await + .unwrap(); let mut txn = db.transaction().await; txn.set(0.to_string()); @@ -273,12 +269,10 @@ mod tests { async fn transaction_projection() { let temp_dir = TempDir::new().unwrap(); - let db = DB::::new( - Arc::new(DbOption::from(temp_dir.path())), - TokioExecutor::new(), - ) - .await - .unwrap(); + let db = + DB::::new(DbOption::from(temp_dir.path()), TokioExecutor::new()) + .await + .unwrap(); let mut txn1 = db.transaction().await; txn1.set(Test { @@ -290,9 +284,9 @@ mod tests { let key = 0.to_string(); let entry = txn1.get(&key, Projection::All).await.unwrap().unwrap(); - assert_eq!(entry.get().unwrap().vstring, 0.to_string()); - assert_eq!(entry.get().unwrap().vu32, Some(0)); - assert_eq!(entry.get().unwrap().vbool, Some(true)); + assert_eq!(entry.get().vstring, 0.to_string()); + assert_eq!(entry.get().vu32, Some(0)); + assert_eq!(entry.get().vbool, Some(true)); drop(entry); txn1.commit().await.unwrap();