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