Skip to main content

icydb_core/db/session/
write.rs

1#[cfg(test)]
2use crate::db::{DataStore, IndexStore};
3use crate::{
4    db::{DbSession, PersistedRow, WriteBatchResponse},
5    error::InternalError,
6    traits::{CanisterKind, EntityValue},
7};
8
9impl<C: CanisterKind> DbSession<C> {
10    /// Insert one entity row.
11    pub fn insert<E>(&self, entity: E) -> Result<E, InternalError>
12    where
13        E: PersistedRow<Canister = C> + EntityValue,
14    {
15        self.execute_save_entity(|save| save.insert(entity))
16    }
17
18    /// Insert a single-entity-type batch atomically in one commit window.
19    ///
20    /// If any item fails pre-commit validation, no row in the batch is persisted.
21    ///
22    /// This API is not a multi-entity transaction surface.
23    pub fn insert_many_atomic<E>(
24        &self,
25        entities: impl IntoIterator<Item = E>,
26    ) -> Result<WriteBatchResponse<E>, InternalError>
27    where
28        E: PersistedRow<Canister = C> + EntityValue,
29    {
30        self.execute_save_batch(|save| save.insert_many_atomic(entities))
31    }
32
33    /// Insert a batch with explicitly non-atomic semantics.
34    ///
35    /// WARNING: fail-fast and non-atomic. Earlier inserts may commit before an error.
36    pub fn insert_many_non_atomic<E>(
37        &self,
38        entities: impl IntoIterator<Item = E>,
39    ) -> Result<WriteBatchResponse<E>, InternalError>
40    where
41        E: PersistedRow<Canister = C> + EntityValue,
42    {
43        self.execute_save_batch(|save| save.insert_many_non_atomic(entities))
44    }
45
46    /// Replace one existing entity row.
47    pub fn replace<E>(&self, entity: E) -> Result<E, InternalError>
48    where
49        E: PersistedRow<Canister = C> + EntityValue,
50    {
51        self.execute_save_entity(|save| save.replace(entity))
52    }
53
54    /// Replace a single-entity-type batch atomically in one commit window.
55    ///
56    /// If any item fails pre-commit validation, no row in the batch is persisted.
57    ///
58    /// This API is not a multi-entity transaction surface.
59    pub fn replace_many_atomic<E>(
60        &self,
61        entities: impl IntoIterator<Item = E>,
62    ) -> Result<WriteBatchResponse<E>, InternalError>
63    where
64        E: PersistedRow<Canister = C> + EntityValue,
65    {
66        self.execute_save_batch(|save| save.replace_many_atomic(entities))
67    }
68
69    /// Replace a batch with explicitly non-atomic semantics.
70    ///
71    /// WARNING: fail-fast and non-atomic. Earlier replaces may commit before an error.
72    pub fn replace_many_non_atomic<E>(
73        &self,
74        entities: impl IntoIterator<Item = E>,
75    ) -> Result<WriteBatchResponse<E>, InternalError>
76    where
77        E: PersistedRow<Canister = C> + EntityValue,
78    {
79        self.execute_save_batch(|save| save.replace_many_non_atomic(entities))
80    }
81
82    /// Update one existing entity row.
83    pub fn update<E>(&self, entity: E) -> Result<E, InternalError>
84    where
85        E: PersistedRow<Canister = C> + EntityValue,
86    {
87        self.execute_save_entity(|save| save.update(entity))
88    }
89
90    /// Update a single-entity-type batch atomically in one commit window.
91    ///
92    /// If any item fails pre-commit validation, no row in the batch is persisted.
93    ///
94    /// This API is not a multi-entity transaction surface.
95    pub fn update_many_atomic<E>(
96        &self,
97        entities: impl IntoIterator<Item = E>,
98    ) -> Result<WriteBatchResponse<E>, InternalError>
99    where
100        E: PersistedRow<Canister = C> + EntityValue,
101    {
102        self.execute_save_batch(|save| save.update_many_atomic(entities))
103    }
104
105    /// Update a batch with explicitly non-atomic semantics.
106    ///
107    /// WARNING: fail-fast and non-atomic. Earlier updates may commit before an error.
108    pub fn update_many_non_atomic<E>(
109        &self,
110        entities: impl IntoIterator<Item = E>,
111    ) -> Result<WriteBatchResponse<E>, InternalError>
112    where
113        E: PersistedRow<Canister = C> + EntityValue,
114    {
115        self.execute_save_batch(|save| save.update_many_non_atomic(entities))
116    }
117
118    /// TEST ONLY: clear all registered data and index stores for this database.
119    #[cfg(test)]
120    #[doc(hidden)]
121    pub fn clear_stores_for_tests(&self) {
122        self.db.with_store_registry(|reg| {
123            // Test cleanup only: clearing all stores is set-like and does not
124            // depend on registry iteration order.
125            for (_, store) in reg.iter() {
126                store.with_data_mut(DataStore::clear);
127                store.with_index_mut(IndexStore::clear);
128            }
129        });
130    }
131}