teaql_runtime/repository/
base.rs1use teaql_core::{
2 DeleteCommand, Entity, InsertCommand, Record, RecoverCommand, SelectQuery, SmartList,
3 UpdateCommand,
4};
5use teaql_sql::{CompiledQuery, SqlDialect};
6
7use crate::{MetadataStore, RepositoryError, RuntimeError};
8
9use super::{QueryExecutor, Repository};
10
11impl<'a, D, M, E> Repository<'a, D, M, E>
12where
13 D: SqlDialect,
14 M: MetadataStore,
15 E: QueryExecutor,
16{
17 pub fn new(dialect: &'a D, metadata: &'a M, executor: &'a E) -> Self {
18 Self {
19 dialect,
20 metadata,
21 executor,
22 }
23 }
24
25 pub fn compile(&self, query: &SelectQuery) -> Result<CompiledQuery, RuntimeError> {
26 let entity = self
27 .metadata
28 .entity(&query.entity)
29 .ok_or_else(|| RuntimeError::MissingEntity(query.entity.clone()))?;
30 Ok(self.dialect.compile_select(entity, query)?)
31 }
32
33 pub fn compile_insert(&self, command: &InsertCommand) -> Result<CompiledQuery, RuntimeError> {
34 let entity = self
35 .metadata
36 .entity(&command.entity)
37 .ok_or_else(|| RuntimeError::MissingEntity(command.entity.clone()))?;
38 Ok(self.dialect.compile_insert(entity, command)?)
39 }
40
41 pub fn compile_update(&self, command: &UpdateCommand) -> Result<CompiledQuery, RuntimeError> {
42 let entity = self
43 .metadata
44 .entity(&command.entity)
45 .ok_or_else(|| RuntimeError::MissingEntity(command.entity.clone()))?;
46 Ok(self.dialect.compile_update(entity, command)?)
47 }
48
49 pub fn compile_delete(&self, command: &DeleteCommand) -> Result<CompiledQuery, RuntimeError> {
50 let entity = self
51 .metadata
52 .entity(&command.entity)
53 .ok_or_else(|| RuntimeError::MissingEntity(command.entity.clone()))?;
54 Ok(self.dialect.compile_delete(entity, command)?)
55 }
56
57 pub fn compile_recover(&self, command: &RecoverCommand) -> Result<CompiledQuery, RuntimeError> {
58 let entity = self
59 .metadata
60 .entity(&command.entity)
61 .ok_or_else(|| RuntimeError::MissingEntity(command.entity.clone()))?;
62 Ok(self.dialect.compile_recover(entity, command)?)
63 }
64
65 pub fn fetch_all(&self, query: &SelectQuery) -> Result<Vec<Record>, RepositoryError<E::Error>> {
66 let compiled = self.compile(query).map_err(RepositoryError::Runtime)?;
67 self.executor
68 .fetch_all(&compiled)
69 .map_err(RepositoryError::Executor)
70 }
71
72 pub fn fetch_smart_list(
73 &self,
74 query: &SelectQuery,
75 ) -> Result<SmartList<Record>, RepositoryError<E::Error>> {
76 self.fetch_all(query).map(SmartList::from)
77 }
78
79 pub fn fetch_entities<T>(
80 &self,
81 query: &SelectQuery,
82 ) -> Result<SmartList<T>, RepositoryError<E::Error>>
83 where
84 T: Entity,
85 {
86 self.fetch_all(query)?
87 .into_iter()
88 .map(T::from_record)
89 .collect::<Result<Vec<_>, _>>()
90 .map(SmartList::from)
91 .map_err(RepositoryError::Entity)
92 }
93
94 pub fn fetch_enhanced_entities<T>(
95 &self,
96 query: &SelectQuery,
97 ) -> Result<SmartList<T>, RepositoryError<E::Error>>
98 where
99 T: Entity,
100 {
101 self.fetch_entities(query)
102 }
103
104 pub fn insert(&self, command: &InsertCommand) -> Result<u64, RepositoryError<E::Error>> {
105 let compiled = self
106 .compile_insert(command)
107 .map_err(RepositoryError::Runtime)?;
108 self.executor
109 .execute(&compiled)
110 .map_err(RepositoryError::Executor)
111 }
112
113 pub fn update(&self, command: &UpdateCommand) -> Result<u64, RepositoryError<E::Error>> {
114 let compiled = self
115 .compile_update(command)
116 .map_err(RepositoryError::Runtime)?;
117 let affected = self
118 .executor
119 .execute(&compiled)
120 .map_err(RepositoryError::Executor)?;
121
122 if command.expected_version.is_some() && affected == 0 {
123 return Err(RepositoryError::Runtime(
124 RuntimeError::OptimisticLockConflict {
125 entity: command.entity.clone(),
126 id: format!("{:?}", command.id),
127 },
128 ));
129 }
130
131 Ok(affected)
132 }
133
134 pub fn delete(&self, command: &DeleteCommand) -> Result<u64, RepositoryError<E::Error>> {
135 let compiled = self
136 .compile_delete(command)
137 .map_err(RepositoryError::Runtime)?;
138 let affected = self
139 .executor
140 .execute(&compiled)
141 .map_err(RepositoryError::Executor)?;
142
143 if command.expected_version.is_some() && affected == 0 {
144 return Err(RepositoryError::Runtime(
145 RuntimeError::OptimisticLockConflict {
146 entity: command.entity.clone(),
147 id: format!("{:?}", command.id),
148 },
149 ));
150 }
151
152 Ok(affected)
153 }
154
155 pub fn recover(&self, command: &RecoverCommand) -> Result<u64, RepositoryError<E::Error>> {
156 let compiled = self
157 .compile_recover(command)
158 .map_err(RepositoryError::Runtime)?;
159 let affected = self
160 .executor
161 .execute(&compiled)
162 .map_err(RepositoryError::Executor)?;
163
164 if affected == 0 {
165 return Err(RepositoryError::Runtime(
166 RuntimeError::OptimisticLockConflict {
167 entity: command.entity.clone(),
168 id: format!("{:?}", command.id),
169 },
170 ));
171 }
172
173 Ok(affected)
174 }
175
176 pub fn insert_many(
177 &self,
178 commands: &[InsertCommand],
179 ) -> Result<u64, RepositoryError<E::Error>> {
180 let mut total = 0;
181 for command in commands {
182 total += self.insert(command)?;
183 }
184 Ok(total)
185 }
186
187 pub fn update_many(
188 &self,
189 commands: &[UpdateCommand],
190 ) -> Result<u64, RepositoryError<E::Error>> {
191 let mut total = 0;
192 for command in commands {
193 total += self.update(command)?;
194 }
195 Ok(total)
196 }
197
198 pub fn delete_many(
199 &self,
200 commands: &[DeleteCommand],
201 ) -> Result<u64, RepositoryError<E::Error>> {
202 let mut total = 0;
203 for command in commands {
204 total += self.delete(command)?;
205 }
206 Ok(total)
207 }
208
209 pub fn recover_many(
210 &self,
211 commands: &[RecoverCommand],
212 ) -> Result<u64, RepositoryError<E::Error>> {
213 let mut total = 0;
214 for command in commands {
215 total += self.recover(command)?;
216 }
217 Ok(total)
218 }
219}