From a0e6bba801c7c00da918257d229d2969a33cdea5 Mon Sep 17 00:00:00 2001 From: Devashish Dixit Date: Thu, 4 Jul 2024 16:28:35 +0800 Subject: [PATCH] Add bulk operations on object store --- src/transaction/store.rs | 41 ++++++++++++++++++++++++++++++++++- tests/web.rs | 47 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/transaction/store.rs b/src/transaction/store.rs index b100331..5fa92aa 100644 --- a/src/transaction/store.rs +++ b/src/transaction/store.rs @@ -151,11 +151,50 @@ impl Store { self.object_store.add(value, key)?.await.map_err(Into::into) } - /// Puts (adds or updates) a key value pair in the store. + /// Adds all key value pairs (`(value, Option)`) in the store. Note that the keys can be `None` if store has + /// auto increment enabled. + pub async fn add_all( + &self, + iter: impl Iterator)>, + ) -> Result<()> { + let mut request = None; + + for (value, key) in iter { + request = Some(self.object_store.add(value.as_ref(), key.as_ref())?); + } + + if let Some(request) = request { + request.await.map(|_| ()).map_err(Into::into) + } else { + Ok(()) + } + } + + /// Puts (adds or updates) a key value pair in the store. Note that the keys can be `None` if store has auto + /// increment enabled. pub async fn put(&self, value: &JsValue, key: Option<&JsValue>) -> Result { self.object_store.put(value, key)?.await.map_err(Into::into) } + /// Puts (adds or updates) a key value pairs (`(value, Option)`) in the store. Note that the keys can be `None` + /// if store has auto increment enabled. + pub async fn put_all( + &self, + iter: impl Iterator)>, + ) -> Result<()> { + let mut request = None; + + for (value, key) in iter { + request = Some(self.object_store.put(value.as_ref(), key.as_ref())?); + } + + if let Some(request) = request { + request.await.map(|_| ()).map_err(Into::into) + } else { + Ok(()) + } + } + /// Deletes a key value pair from the store pub async fn delete(&self, key: JsValue) -> Result<()> { self.object_store.delete(key)?.await.map_err(Into::into) diff --git a/tests/web.rs b/tests/web.rs index 4cb56f4..13666ed 100644 --- a/tests/web.rs +++ b/tests/web.rs @@ -4,7 +4,7 @@ extern crate wasm_bindgen_test; -use std::{assert, assert_eq, option::Option}; +use std::{assert, assert_eq, option::Option, vec}; use js_sys::Array; use rexie::{Direction, Index, KeyPath, KeyRange, ObjectStore, Result, Rexie, TransactionMode}; @@ -126,6 +126,27 @@ async fn add_employee(rexie: &Rexie, name: &str, email: &str) -> Result { Ok(num_traits::cast(employee_id.as_f64().unwrap()).unwrap()) } +async fn add_all_employees(rexie: &Rexie, iter: impl Iterator) -> Result<()> { + let transaction = rexie.transaction(&["employees"], TransactionMode::ReadWrite); + assert!(transaction.is_ok()); + let transaction = transaction.unwrap(); + + let employees = transaction.store("employees"); + assert!(employees.is_ok()); + let employees = employees.unwrap(); + + let requests = iter.map(|(name, email)| { + let request = EmployeeRequest { name, email }; + let request = serde_wasm_bindgen::to_value(&request).unwrap(); + (request, None) + }); + + employees.add_all(requests).await?; + + transaction.commit().await?; + Ok(()) +} + async fn get_employee(rexie: &Rexie, id: u32) -> Result> { let transaction = rexie.transaction(&["employees"], TransactionMode::ReadOnly); assert!(transaction.is_ok()); @@ -479,3 +500,27 @@ async fn check_transaction_abort() { close_and_delete_db(rexie).await; } + +#[wasm_bindgen_test] +async fn test_add_all_pass() { + let rexie = create_db().await; + + // Write values to the database. + add_all_employees( + &rexie, + vec![ + ("John Doe", "john@example.com"), + ("Scooby Doo", "scooby@example.com"), + ] + .into_iter(), + ) + .await + .unwrap(); + + let employees = get_all_employees(&rexie, None).await; + assert!(employees.is_ok()); + let employees = employees.unwrap(); + assert_eq!(employees.len(), 2); + + close_and_delete_db(rexie).await; +}