1pub mod executor;
2pub mod primitives;
3pub mod query;
4pub mod response;
5pub mod store;
6
7use crate::{
8 Error,
9 db::{
10 executor::{
11 Context, DeleteExecutor, ExecutorError, LoadExecutor, PrimaryKeyFromKey, SaveExecutor,
12 UpsertExecutor,
13 },
14 query::QueryError,
15 response::ResponseError,
16 store::{DataStoreRegistry, IndexStoreRegistry, StoreError},
17 },
18 serialize::SerializeError,
19 traits::{CanisterKind, EntityKind},
20 visitor::VisitorError,
21};
22use std::{marker::PhantomData, thread::LocalKey};
23use thiserror::Error as ThisError;
24
25#[derive(Debug, ThisError)]
30pub enum DbError {
31 #[error(transparent)]
32 ExecutorError(#[from] ExecutorError),
33
34 #[error(transparent)]
35 QueryError(#[from] QueryError),
36
37 #[error(transparent)]
38 ResponseError(#[from] ResponseError),
39
40 #[error(transparent)]
41 SerializeError(#[from] SerializeError),
42
43 #[error(transparent)]
44 StoreError(#[from] StoreError),
45
46 #[error(transparent)]
47 VisitorError(#[from] VisitorError),
48}
49
50pub struct Db<C: CanisterKind> {
62 data: &'static LocalKey<DataStoreRegistry>,
63 index: &'static LocalKey<IndexStoreRegistry>,
64 _marker: PhantomData<C>,
65}
66
67impl<C: CanisterKind> Db<C> {
68 #[must_use]
69 pub const fn new(
70 data: &'static LocalKey<DataStoreRegistry>,
71 index: &'static LocalKey<IndexStoreRegistry>,
72 ) -> Self {
73 Self {
74 data,
75 index,
76 _marker: PhantomData,
77 }
78 }
79
80 #[must_use]
81 pub const fn context<E>(&self) -> Context<'_, E>
82 where
83 E: EntityKind<Canister = C>,
84 {
85 Context::new(self)
86 }
87
88 pub fn with_data<R>(&self, f: impl FnOnce(&DataStoreRegistry) -> R) -> R {
90 self.data.with(|reg| f(reg))
91 }
92
93 pub fn with_index<R>(&self, f: impl FnOnce(&IndexStoreRegistry) -> R) -> R {
95 self.index.with(|reg| f(reg))
96 }
97}
98
99impl<C: CanisterKind> Copy for Db<C> {}
103
104impl<C: CanisterKind> Clone for Db<C> {
105 fn clone(&self) -> Self {
106 *self
107 }
108}
109
110pub struct DbSession<C: CanisterKind> {
116 db: Db<C>,
117 debug: bool,
118}
119
120impl<C: CanisterKind> DbSession<C> {
121 #[must_use]
122 pub const fn new(db: Db<C>) -> Self {
124 Self { db, debug: false }
125 }
126
127 #[must_use]
128 pub const fn debug(mut self) -> Self {
130 self.debug = true;
131 self
132 }
133
134 #[must_use]
140 pub const fn load<E>(&self) -> LoadExecutor<E>
141 where
142 E: EntityKind<Canister = C>,
143 {
144 LoadExecutor::new(self.db, self.debug)
145 }
146
147 #[must_use]
151 pub const fn save<E>(&self) -> SaveExecutor<E>
152 where
153 E: EntityKind<Canister = C>,
154 {
155 SaveExecutor::new(self.db, self.debug)
156 }
157
158 #[must_use]
160 pub const fn upsert<E>(&self) -> UpsertExecutor<E>
161 where
162 E: EntityKind<Canister = C>,
163 E::PrimaryKey: PrimaryKeyFromKey,
164 {
165 UpsertExecutor::new(self.db, self.debug)
166 }
167
168 #[must_use]
170 pub const fn delete<E>(&self) -> DeleteExecutor<E>
171 where
172 E: EntityKind<Canister = C>,
173 {
174 DeleteExecutor::new(self.db, self.debug)
175 }
176
177 pub fn insert<E>(&self, entity: E) -> Result<E, Error>
183 where
184 E: EntityKind<Canister = C>,
185 {
186 self.save::<E>().insert(entity)
187 }
188
189 pub fn insert_many<E>(&self, entities: impl IntoIterator<Item = E>) -> Result<Vec<E>, Error>
191 where
192 E: EntityKind<Canister = C>,
193 {
194 self.save::<E>().insert_many(entities)
195 }
196
197 pub fn replace<E>(&self, entity: E) -> Result<E, Error>
199 where
200 E: EntityKind<Canister = C>,
201 {
202 self.save::<E>().replace(entity)
203 }
204
205 pub fn replace_many<E>(&self, entities: impl IntoIterator<Item = E>) -> Result<Vec<E>, Error>
207 where
208 E: EntityKind<Canister = C>,
209 {
210 self.save::<E>().replace_many(entities)
211 }
212
213 pub fn update<E>(&self, entity: E) -> Result<E, Error>
215 where
216 E: EntityKind<Canister = C>,
217 {
218 self.save::<E>().update(entity)
219 }
220
221 pub fn update_many<E>(&self, entities: impl IntoIterator<Item = E>) -> Result<Vec<E>, Error>
223 where
224 E: EntityKind<Canister = C>,
225 {
226 self.save::<E>().update_many(entities)
227 }
228
229 pub fn insert_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
231 where
232 E: EntityKind<Canister = C>,
233 {
234 self.save::<E>().insert_view(view)
235 }
236
237 pub fn replace_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
239 where
240 E: EntityKind<Canister = C>,
241 {
242 self.save::<E>().replace_view(view)
243 }
244
245 pub fn update_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
247 where
248 E: EntityKind<Canister = C>,
249 {
250 self.save::<E>().update_view(view)
251 }
252}