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};
20use std::{marker::PhantomData, thread::LocalKey};
21use thiserror::Error as ThisError;
22
23#[derive(Debug, ThisError)]
28pub enum DbError {
29 #[error(transparent)]
30 ExecutorError(#[from] ExecutorError),
31
32 #[error(transparent)]
33 QueryError(#[from] QueryError),
34
35 #[error(transparent)]
36 ResponseError(#[from] ResponseError),
37
38 #[error(transparent)]
39 SerializeError(#[from] SerializeError),
40
41 #[error(transparent)]
42 StoreError(#[from] StoreError),
43}
44
45pub struct Db<C: CanisterKind> {
57 data: &'static LocalKey<DataStoreRegistry>,
58 index: &'static LocalKey<IndexStoreRegistry>,
59 _marker: PhantomData<C>,
60}
61
62impl<C: CanisterKind> Db<C> {
63 #[must_use]
64 pub const fn new(
65 data: &'static LocalKey<DataStoreRegistry>,
66 index: &'static LocalKey<IndexStoreRegistry>,
67 ) -> Self {
68 Self {
69 data,
70 index,
71 _marker: PhantomData,
72 }
73 }
74
75 #[must_use]
76 pub const fn context<E>(&self) -> Context<'_, E>
77 where
78 E: EntityKind<Canister = C>,
79 {
80 Context::new(self)
81 }
82
83 pub fn with_data<R>(&self, f: impl FnOnce(&DataStoreRegistry) -> R) -> R {
85 self.data.with(|reg| f(reg))
86 }
87
88 pub fn with_index<R>(&self, f: impl FnOnce(&IndexStoreRegistry) -> R) -> R {
90 self.index.with(|reg| f(reg))
91 }
92}
93
94impl<C: CanisterKind> Copy for Db<C> {}
98
99impl<C: CanisterKind> Clone for Db<C> {
100 fn clone(&self) -> Self {
101 *self
102 }
103}
104
105pub struct DbSession<C: CanisterKind> {
111 db: Db<C>,
112 debug: bool,
113}
114
115impl<C: CanisterKind> DbSession<C> {
116 #[must_use]
117 pub const fn new(db: Db<C>) -> Self {
119 Self { db, debug: false }
120 }
121
122 #[must_use]
123 pub const fn debug(mut self) -> Self {
125 self.debug = true;
126 self
127 }
128
129 #[must_use]
135 pub const fn load<E>(&self) -> LoadExecutor<E>
136 where
137 E: EntityKind<Canister = C>,
138 {
139 LoadExecutor::new(self.db, self.debug)
140 }
141
142 #[must_use]
146 pub const fn save<E>(&self) -> SaveExecutor<E>
147 where
148 E: EntityKind<Canister = C>,
149 {
150 SaveExecutor::new(self.db, self.debug)
151 }
152
153 #[must_use]
155 pub const fn upsert<E>(&self) -> UpsertExecutor<E>
156 where
157 E: EntityKind<Canister = C>,
158 E::PrimaryKey: FromKey,
159 {
160 UpsertExecutor::new(self.db, self.debug)
161 }
162
163 #[must_use]
165 pub const fn delete<E>(&self) -> DeleteExecutor<E>
166 where
167 E: EntityKind<Canister = C>,
168 {
169 DeleteExecutor::new(self.db, self.debug)
170 }
171
172 pub fn insert<E>(&self, entity: E) -> Result<E, Error>
178 where
179 E: EntityKind<Canister = C>,
180 {
181 self.save::<E>().insert(entity)
182 }
183
184 pub fn insert_many<E>(&self, entities: impl IntoIterator<Item = E>) -> Result<Vec<E>, Error>
186 where
187 E: EntityKind<Canister = C>,
188 {
189 self.save::<E>().insert_many(entities)
190 }
191
192 pub fn replace<E>(&self, entity: E) -> Result<E, Error>
194 where
195 E: EntityKind<Canister = C>,
196 {
197 self.save::<E>().replace(entity)
198 }
199
200 pub fn replace_many<E>(&self, entities: impl IntoIterator<Item = E>) -> Result<Vec<E>, Error>
202 where
203 E: EntityKind<Canister = C>,
204 {
205 self.save::<E>().replace_many(entities)
206 }
207
208 pub fn update<E>(&self, entity: E) -> Result<E, Error>
210 where
211 E: EntityKind<Canister = C>,
212 {
213 self.save::<E>().update(entity)
214 }
215
216 pub fn update_many<E>(&self, entities: impl IntoIterator<Item = E>) -> Result<Vec<E>, Error>
218 where
219 E: EntityKind<Canister = C>,
220 {
221 self.save::<E>().update_many(entities)
222 }
223
224 pub fn insert_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
226 where
227 E: EntityKind<Canister = C>,
228 {
229 self.save::<E>().insert_view(view)
230 }
231
232 pub fn replace_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
234 where
235 E: EntityKind<Canister = C>,
236 {
237 self.save::<E>().replace_view(view)
238 }
239
240 pub fn update_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
242 where
243 E: EntityKind<Canister = C>,
244 {
245 self.save::<E>().update_view(view)
246 }
247}