Skip to main content

flyer_orm/
lib.rs

1use std::{collections::HashMap, marker::PhantomData, str, sync::LazyLock};
2
3use anyhow::{Ok, Result};
4use sqlx::{Arguments, Encode, FromRow, Pool, types::Type};
5
6use crate::query::{Order, Pagination, Statement, Transaction, logic::{Condition, Join, JoinType, OrderQuery, Where}};
7
8pub mod databases;
9pub mod query;
10
11pub(crate) static mut CONNECTIONS: LazyLock<HashMap<&str, String>> = LazyLock::new(|| HashMap::new());
12
13#[allow(async_fn_in_trait)]
14pub trait Executor {
15    type T: sqlx::Database;
16
17    async fn new(url: &str) -> Self where Self: Sized;
18
19    fn db<'q>(&'q self) -> &'q Pool<Self::T>; 
20
21    fn to_sql<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<String>;
22
23    async fn execute<'q>(&self, sql: &'q str) -> Result<()>;
24
25    async fn insert<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<()>;
26
27    async fn update<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<()>;
28
29    async fn count<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<u64>;
30
31    async fn delete<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<()>;
32
33    async fn insert_as<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<O>
34    where
35        O: for<'r> FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized;
36
37    async fn query_all<'q, O, T: 'q + Encode<'q, Self::T> + Type<Self::T>>(&self, sql: &str, args: Vec<T>) -> Result<Vec<O>>
38    where
39        O: for<'r> FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized;
40
41    async fn query_one<'q, O, T: 'q + Encode<'q, Self::T> + Type<Self::T>>(&self, sql: &str, args: Vec<T>) -> Result<O>
42    where
43        O: for<'r> FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized;
44
45    async fn all<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<Vec<O>>
46    where
47        O: for<'r> FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized;
48
49    async fn first<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<O>
50    where
51        O: for<'r> FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized;
52
53    async fn paginate<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<Pagination<O>>
54    where
55        O: for<'r> FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized;
56
57}
58
59pub struct DB;
60
61impl DB {
62    #[allow(static_mut_refs)]
63    pub fn add(connection: &'static str, url: &str) {
64        unsafe { CONNECTIONS.insert(connection, url.to_string()); }
65    }
66
67    #[allow(static_mut_refs)]
68    pub fn remove(connection: &str) {
69        unsafe { CONNECTIONS.remove(connection); }
70    }
71
72    #[allow(static_mut_refs)]
73    pub async fn db<E: Executor>(connection: &str) -> Database::<E> {
74        return unsafe { Database::new(CONNECTIONS.get(connection).unwrap()).await };
75    }
76
77    pub async fn db_with_url<E: Executor>(url: &str) -> Database::<E> {
78        return Database::new(url).await;
79    }
80}
81
82#[derive(Debug)]
83pub struct Database<E: Executor> {
84    executor: E,
85}
86
87impl <E: Executor>Database<E> {
88    pub async fn new(url: &str) -> Self {
89        return Self {
90            executor: E::new(url).await,
91        }
92    }
93
94    pub async fn transaction<'q>(&self) -> Result<Transaction<'q, E::T>> {
95        return Ok(Transaction::new(self.executor.db().begin().await.unwrap()));
96    }
97
98    pub async fn execute(&self, sql: &str) -> Result<()> {
99        todo!();
100    }
101
102    pub fn query<'q>(&'q self, table: &str) -> Query<'q, E> {
103        return Query::new(table, &self.executor);
104    }
105
106    pub async fn close(&self) -> Result<()> {
107        return Ok(self.executor.db().close().await);
108    }
109}
110
111pub struct Query<'q, E: Executor> {
112    db: &'q E,
113    statement: Statement<'q, E::T>,
114    _marker: PhantomData<E>
115}
116
117impl <'q, E>Query<'q, E>
118where
119    E: Executor
120{
121    pub fn new(table: &str, exc: &'q E) -> Self {
122        return Self {
123            db: exc,
124            statement: Statement::<'q, E::T>::new(table),
125            _marker: PhantomData,
126        }
127    }
128
129    pub fn table(&mut self, name: &'q str) -> &mut Self {
130        self.statement.query.table = name.to_string();
131
132        return self;
133    }
134
135    pub fn select(&mut self, columns: Vec<&str>) -> &mut Self {
136        self.statement.query.select = columns.iter().map(|c| c.to_string()).collect();
137
138        return self;
139    }
140
141    pub fn r#where<T: 'q + Encode<'q, E::T> + Type<E::T>>(&mut self, column: &str, operator: &str, val: T) -> &mut Self {
142        if self.statement.query.where_queries.len() != 0 {
143            return self.and_where(column, operator, val);
144        }
145
146        // TODO: find better name...
147        self.statement.query.where_queries.push(Where {
148            column: Some(column.to_string()),
149            operator: Some(operator.to_string()),
150            position: None,
151            group: None
152        });
153
154        self.statement.arguments.add(val).unwrap();
155        
156        return self;
157    }
158
159    pub fn and_where<T: 'q + Encode<'q, E::T> + Type<E::T>>(&mut self, column: &str, operator: &str, val: T) -> &mut Self {
160        if self.statement.query.where_queries.len() == 0 {
161            return self.r#where(column, operator, val);
162        }
163
164        self.statement.query.where_queries.push(Where {
165            column: Some(column.to_string()),
166            operator: Some(operator.to_string()),
167            position: Some(Condition::AND),
168            group: None
169        });
170
171        self.statement.arguments.add(val).unwrap();
172        
173        return self;
174    }
175
176    pub fn or_where<T: 'q + Encode<'q, E::T> + Type<E::T>>(&mut self, column: &str, operator: &str, val: T) -> &mut Self {
177        if self.statement.query.where_queries.len() == 0 {
178            return self.r#where(column, operator, val);
179        }
180
181        self.statement.query.where_queries.push(Where {
182            column: Some(column.to_string()),
183            operator: Some(operator.to_string()),
184            position: Some(Condition::OR),
185            group: None
186        });
187
188        self.statement.arguments.add(val).unwrap();
189
190        return self;
191    }
192
193    // pub fn where_group(&mut self, callback: fn(group: WhereQueryGroup<'q, E::T>) -> WhereQueryGroup<'q, E::T>) -> &mut Self {        
194    //     return self;
195    // }
196
197    // pub fn and_where_group(&mut self, callback: fn(group: WhereQueryGroup<'q, E::T>) -> WhereQueryGroup<'q, E::T>) -> &mut Self {        
198    //     return self;
199    // }
200
201    // pub fn or_where_group(&mut self, callback: fn(group: WhereQueryGroup<'q, E::T>) -> WhereQueryGroup<'q, E::T>) -> &mut Self {        
202    //     return self;
203    // }
204
205    pub fn order_by(&mut self, column: &str, order: Order) -> &mut Self {
206        self.statement.query.order_by.push(OrderQuery {
207            column: column.to_string(),
208            order: order
209        });
210
211        return self;
212    }
213
214    pub fn join(&mut self, table: &str, column: &str, column_table: &str) -> &mut Self {
215        self.statement.query.join.push(Join {
216            table: table.to_string(),
217            column: column.to_string(),
218            operator: "=".to_string(),
219            column_table: column_table.to_string(),
220            join_type: JoinType::LeftJoin 
221        });
222
223        return self;
224    }
225
226    pub fn limit(&mut self, limit: u64) -> &mut Self {
227        self.statement.query.limit = Some(limit);
228
229        return self;
230    }
231
232    pub fn bind<T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, value: T) -> &'q mut Self {
233        self.statement.arguments.add(value).unwrap();
234
235        return self;
236    }
237
238    pub async fn query<O, T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, sql: &str, args: Vec<T>) -> Result<Vec<O>>
239    where
240        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
241    {
242        return Ok(self.db.query_all::<O, T>(sql, args).await.unwrap());
243    }
244
245    pub async fn query_all<O, T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, sql: &str, args: Vec<T>) -> Result<Vec<O>>
246    where
247        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
248    {
249        return Ok(self.db.query_all::<O, T>(sql, args).await.unwrap());
250    }
251
252    pub async fn query_one<O, T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, sql: &str, args: Vec<T>) -> Result<O>
253    where
254        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
255    {
256        return Ok(self.db.query_one::<O, T>(sql, args).await.unwrap())
257    }
258
259    pub fn insert_as<O>(&'q mut self, columns: Vec<&str>) -> InsertAs<'q, E, O>
260    where
261        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
262    {
263        self.statement.query.columns = Some(columns.iter().map(|c| c.to_string()).collect());
264
265        return InsertAs::new(self.db, &mut self.statement);
266    }
267
268    pub fn insert(&'q mut self, columns: Vec<&str>) -> Insert<'q, E> {
269        self.statement.query.columns = Some(columns.iter().map(|c| c.to_string()).collect());
270
271        return Insert::new(&self.db, &mut self.statement);
272    }
273
274    pub fn update<T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, columns: Vec<&str>) -> Update<'q, E, T> {
275        self.statement.query.columns = Some(columns.iter().map(|c| c.to_string()).collect());
276
277        return Update::new(&self.db, &mut self.statement);
278    }
279
280    pub async fn delete(&'q mut self) -> Result<()>
281    {
282        return Ok(self.db.delete(&self.statement).await.unwrap())
283    }
284
285    pub async fn first<O>(&'q mut self) -> Result<O>
286    where
287        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
288    {
289        return Ok(self.db.first::<O>(&self.statement).await.unwrap())
290    }
291
292    pub async fn all<O>(&'q mut self) -> Result<Vec<O>>
293    where
294        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
295    {
296        return Ok(self.db.all::<O>(&self.statement).await.unwrap())
297    }
298
299    pub async fn count(&'q mut self) -> Result<u64> {
300        return Ok(self.db.count(&self.statement).await.unwrap())
301    }
302
303    pub async fn exists(&'q mut self) -> Result<bool> {
304        return Ok(self.db.count(&self.statement).await.unwrap() > 0)
305    }
306
307    pub async fn paginate<O>(&'q mut self, limit: u64, page: u64) -> Result<Pagination<O>>
308    where
309        O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
310    {
311        self.statement.query.limit = Some(limit);
312        self.statement.query.page = Some(page); // TODO: calc offset using offset
313
314        return Ok(self.db.paginate::<O>(&self.statement).await.unwrap());
315    }
316
317    pub fn to_sql(&'q mut self) -> Result<String> {
318        return Ok(self.db.to_sql(&self.statement).unwrap())
319    }
320}
321
322pub struct InsertAs<'q, E: Executor, O> {
323    db: &'q E,
324    statement: &'q mut Statement<'q, E::T>,
325    _marker: PhantomData<E>,
326    _type: PhantomData<O>
327}
328
329impl <'q, E, O>InsertAs<'q, E, O>
330where
331    E: Executor,
332    O: for<'r> FromRow<'r, <E::T as sqlx::Database>::Row> + Send + Unpin + Sized
333{
334    pub(crate) fn new(db: &'q E, statement: &'q mut Statement<'q, E::T>) -> Self {
335        return Self {
336            db: db,
337            statement: statement,
338            _marker: PhantomData,
339            _type: PhantomData
340        }
341    }
342
343    pub fn bind<T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, value: T) -> &'q mut Self {
344        self.statement.arguments.add(value).unwrap();
345
346        return self;
347    }
348
349    pub async fn execute(&'q mut self) -> Result<O> {
350        return Ok(self.db.insert_as::<O>(self.statement).await.unwrap());
351    }
352}
353
354pub struct Insert<'q, E: Executor> {
355    db: &'q E,
356    statement: &'q mut Statement<'q, E::T>,
357    _marker: PhantomData<E>
358}
359
360impl <'q, E>Insert<'q, E>
361where
362    E: Executor
363{
364    pub(crate) fn new(db: &'q E, statement: &'q mut Statement<'q, E::T>) -> Self {
365        return Self {
366            db: db,
367            statement: statement,
368            _marker: PhantomData,
369        }
370    }
371
372    pub fn bind<T: 'q + Encode<'q, E::T> + Type<E::T>>(&'q mut self, value: T) -> &'q mut Self {
373        self.statement.arguments.add(value).unwrap();
374
375        return self;
376    }
377
378    pub async fn execute(&'q mut self) -> Result<()> {
379        return self.db.insert(self.statement).await;
380    }
381}
382
383pub struct Update<'q, E: Executor, T: 'q + Encode<'q, E::T> + Type<E::T>> {
384    db: &'q E,
385    statement: &'q mut Statement<'q, E::T>,
386    // insert_arguments: <E::T as SqlxDatabase>::Arguments<'q>,
387    // where_arguments: <E::T as SqlxDatabase>::Arguments<'q>,
388
389    
390    insert_arguments: Vec<T>,
391    where_arguments: Vec<T>,
392
393    
394    _marker: PhantomData<E>
395}
396
397impl <'q, E, T: 'q + Encode<'q, E::T> + Type<E::T>>Update<'q, E, T>
398where
399    E: Executor
400{
401    pub(crate) fn new(db: &'q E, statement: &'q mut Statement<'q, E::T>) -> Self {
402        return Self {
403            db: db,
404            statement: statement,
405            insert_arguments: Default::default(),
406            where_arguments: Default::default(),
407            _marker: PhantomData,
408        }
409    }
410
411    pub fn bind(&'q mut self, value: T) -> &'q mut Self {
412        // self.insert_arguments.add(value).unwrap();
413
414        self.insert_arguments.push(value);
415
416        return self;
417    }
418
419    pub fn r#where(&mut self, column: &str, operator: &str, value: T) -> &mut Self {
420        if self.statement.query.where_queries.len() != 0 {
421            return self.and_where(column, operator, value);
422        }
423
424        self.statement.query.where_queries.push(Where {
425            column: Some(column.to_string()),
426            operator: Some(operator.to_string()),
427            position: None,
428            group: None
429        });
430
431        self.where_arguments.push(value);
432        
433        return self;
434    }
435
436    pub fn and_where(&mut self, column: &str, operator: &str, value: T) -> &mut Self {
437        if self.statement.query.where_queries.len() == 0 {
438            return self.r#where(column, operator, value);
439        }
440
441        self.statement.query.where_queries.push(Where {
442            column: Some(column.to_string()),
443            operator: Some(operator.to_string()),
444            position: Some(Condition::AND),
445            group: None
446        });
447
448        self.where_arguments.push(value);
449        
450        return self;
451    }
452
453    pub fn or_where(&mut self, column: &str, operator: &str, value: T) -> &mut Self {
454        if self.statement.query.where_queries.len() == 0 {
455            return self.r#where(column, operator, value);
456        }
457
458        self.statement.query.where_queries.push(Where {
459            column: Some(column.to_string()),
460            operator: Some(operator.to_string()),
461            position: Some(Condition::OR),
462            group: None
463        });
464
465        self.where_arguments.push(value);
466
467        return self;
468    }
469
470    // pub fn where_group(&mut self, callback: fn(group: WhereQueryGroup<'q, E::T>) -> WhereQueryGroup<'q, E::T>) -> &mut Self {        
471    //     return self;
472    // }
473
474    // pub fn and_where_group(&mut self, callback: fn(group: WhereQueryGroup<'q, E::T>) -> WhereQueryGroup<'q, E::T>) -> &mut Self {        
475    //     return self;
476    // }
477
478    // pub fn or_where_group(&mut self, callback: fn(group: WhereQueryGroup<'q, E::T>) -> WhereQueryGroup<'q, E::T>) -> &mut Self {        
479    //     return self;
480    // }
481
482    pub async fn execute(&'q mut self) -> Result<()> {
483        self.statement.arguments = Default::default();
484
485        for v in self.insert_arguments.iter() {
486            self.statement.arguments.add(v).unwrap();
487        }
488
489        for v in self.where_arguments.iter() {
490            self.statement.arguments.add(v).unwrap();
491        }
492
493        return self.db.update(self.statement).await;
494    }
495}