1use std::future::Future;
4use std::pin::Pin;
5
6use crate::error::QueryResult;
7use crate::filter::Filter;
8
9pub trait Model: Sized + Send + Sync {
11 const MODEL_NAME: &'static str;
13
14 const TABLE_NAME: &'static str;
16
17 const PRIMARY_KEY: &'static [&'static str];
19
20 const COLUMNS: &'static [&'static str];
22}
23
24pub trait IntoFilter {
26 fn into_filter(self) -> Filter;
28}
29
30impl IntoFilter for Filter {
31 fn into_filter(self) -> Filter {
32 self
33 }
34}
35
36impl<F: FnOnce() -> Filter> IntoFilter for F {
37 fn into_filter(self) -> Filter {
38 self()
39 }
40}
41
42pub trait Executable {
44 type Output;
46
47 fn exec(self) -> impl Future<Output = QueryResult<Self::Output>> + Send;
49}
50
51pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
53
54pub trait QueryEngine: Send + Sync + Clone + 'static {
60 fn query_many<T: Model + Send + 'static>(
62 &self,
63 sql: &str,
64 params: Vec<crate::filter::FilterValue>,
65 ) -> BoxFuture<'_, QueryResult<Vec<T>>>;
66
67 fn query_one<T: Model + Send + 'static>(
69 &self,
70 sql: &str,
71 params: Vec<crate::filter::FilterValue>,
72 ) -> BoxFuture<'_, QueryResult<T>>;
73
74 fn query_optional<T: Model + Send + 'static>(
76 &self,
77 sql: &str,
78 params: Vec<crate::filter::FilterValue>,
79 ) -> BoxFuture<'_, QueryResult<Option<T>>>;
80
81 fn execute_insert<T: Model + Send + 'static>(
83 &self,
84 sql: &str,
85 params: Vec<crate::filter::FilterValue>,
86 ) -> BoxFuture<'_, QueryResult<T>>;
87
88 fn execute_update<T: Model + Send + 'static>(
90 &self,
91 sql: &str,
92 params: Vec<crate::filter::FilterValue>,
93 ) -> BoxFuture<'_, QueryResult<Vec<T>>>;
94
95 fn execute_delete(
97 &self,
98 sql: &str,
99 params: Vec<crate::filter::FilterValue>,
100 ) -> BoxFuture<'_, QueryResult<u64>>;
101
102 fn execute_raw(
104 &self,
105 sql: &str,
106 params: Vec<crate::filter::FilterValue>,
107 ) -> BoxFuture<'_, QueryResult<u64>>;
108
109 fn count(
111 &self,
112 sql: &str,
113 params: Vec<crate::filter::FilterValue>,
114 ) -> BoxFuture<'_, QueryResult<u64>>;
115}
116
117pub trait ModelAccessor<E: QueryEngine>: Send + Sync {
121 type Model: Model;
123
124 fn engine(&self) -> &E;
126
127 fn find_many(&self) -> crate::operations::FindManyOperation<E, Self::Model>;
129
130 fn find_unique(&self) -> crate::operations::FindUniqueOperation<E, Self::Model>;
132
133 fn find_first(&self) -> crate::operations::FindFirstOperation<E, Self::Model>;
135
136 fn create(&self, data: <Self::Model as CreateData>::Data) -> crate::operations::CreateOperation<E, Self::Model>
138 where
139 Self::Model: CreateData;
140
141 fn update(&self) -> crate::operations::UpdateOperation<E, Self::Model>;
143
144 fn delete(&self) -> crate::operations::DeleteOperation<E, Self::Model>;
146
147 fn upsert(
149 &self,
150 create: <Self::Model as CreateData>::Data,
151 update: <Self::Model as UpdateData>::Data,
152 ) -> crate::operations::UpsertOperation<E, Self::Model>
153 where
154 Self::Model: CreateData + UpdateData;
155
156 fn count(&self) -> crate::operations::CountOperation<E, Self::Model>;
158}
159
160pub trait CreateData: Model {
162 type Data: Send + Sync;
164}
165
166pub trait UpdateData: Model {
168 type Data: Send + Sync;
170}
171
172pub trait UpsertData: CreateData + UpdateData {}
174
175impl<T: CreateData + UpdateData> UpsertData for T {}
176
177pub trait WithRelations: Model {
179 type Include;
181
182 type Select;
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 struct TestModel;
191
192 impl Model for TestModel {
193 const MODEL_NAME: &'static str = "TestModel";
194 const TABLE_NAME: &'static str = "test_models";
195 const PRIMARY_KEY: &'static [&'static str] = &["id"];
196 const COLUMNS: &'static [&'static str] = &["id", "name", "email"];
197 }
198
199 #[test]
200 fn test_model_trait() {
201 assert_eq!(TestModel::MODEL_NAME, "TestModel");
202 assert_eq!(TestModel::TABLE_NAME, "test_models");
203 assert_eq!(TestModel::PRIMARY_KEY, &["id"]);
204 }
205
206 #[test]
207 fn test_into_filter() {
208 let filter = Filter::Equals("id".into(), crate::filter::FilterValue::Int(1));
209 let converted = filter.clone().into_filter();
210 assert_eq!(converted, filter);
211 }
212}
213