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