Skip to main content

flyer_orm/databases/sqlite/
mod.rs

1use anyhow::Result;
2use sqlx::{Arguments, Pool, Sqlite};
3
4use crate::{
5    Executor,
6    databases::sqlite::{builder::Builder, query::SQLiteQueryResult},
7    query::{Pagination, QueryBuilder, QueryResult, Statement, Total, logic::Where}
8};
9
10pub mod query;
11mod builder;
12
13#[derive(Debug)]
14pub struct SQLite {
15    db: Pool<Sqlite>,
16}
17
18impl SQLite {
19    async fn fetch_one<'q, O>(&'q self, sql: String, arguments: <<SQLite as Executor>::T as sqlx::Database>::Arguments<'q>) -> Result<O>
20    where
21        O: for<'r> sqlx::FromRow<'r, <<SQLite as Executor>::T as sqlx::Database>::Row> + Send + Unpin + Sized
22    {
23        return Ok(
24            sqlx::query_as_with::<<SQLite as Executor>::T, O, _>(&sql, arguments)
25                .fetch_one(&self.db)
26                .await
27                .unwrap()
28        );
29    }
30
31    async fn fetch_all<'q, O>(&'q self, sql: String, arguments: <<SQLite as Executor>::T as sqlx::Database>::Arguments<'q>) -> Result<Vec<O>>
32    where
33        O: for<'r> sqlx::FromRow<'r, <<SQLite as Executor>::T as sqlx::Database>::Row> + Send + Unpin + Sized
34    {
35        return Ok(
36            sqlx::query_as_with::<<SQLite as Executor>::T, O, _>(&sql, arguments)
37                .fetch_all(&self.db)
38                .await
39                .unwrap()
40        );
41    }
42
43    async fn execute_query<'q>(&'q self, sql: String, arguments: <<SQLite as Executor>::T as sqlx::Database>::Arguments<'q>) -> Result<SQLiteQueryResult> {
44        let result = sqlx::query_with::<<SQLite as Executor>::T, _>(&sql, arguments)
45            .execute(&self.db)
46            .await
47            .unwrap();
48
49        return Ok(SQLiteQueryResult {
50            affected: result.rows_affected(),
51            id: result.last_insert_rowid() as u64,
52        });
53    }
54}
55
56impl Executor for SQLite {
57    type T = sqlx::Sqlite;
58
59    async fn new(url: &str) -> Self where Self: Sized {
60        return Self {
61            db: sqlx::SqlitePool::connect(url).await.unwrap(),
62        };
63    }
64    
65    fn db<'q>(&'q self) -> &'q Pool<Self::T> {
66        return &self.db;
67    }
68    
69    fn to_sql<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<String> {
70        return Ok(Builder::new(&statement.query).query().unwrap());
71    }
72
73    async fn execute<'q>(&self, sql: &'q str) -> Result<impl QueryResult> {
74        return self.execute_query(String::from(sql), Default::default()).await;
75    }
76    
77    async fn insert<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<()> {
78        self.execute_query(Builder::new(&statement.query).insert().unwrap(), statement.arguments.clone()).await.unwrap();
79
80        return Ok(());
81    }
82    
83    async fn insert_as<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<O>
84    where
85        O: for<'r> sqlx::FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized
86    {
87        let result = self.execute_query(Builder::new(&statement.query).insert().unwrap(), statement.arguments.clone()).await.unwrap();
88
89        let mut statement = Statement::<Self::T>::new(&statement.query.table);
90
91        statement.query.where_queries.push(Where {
92            column: Some("rowid".to_string()),
93            operator: Some("=".to_string()),
94            condition: None,
95            group: None
96        });
97
98        statement.arguments.add(result.last_inserted() as i64).unwrap();
99
100        return Ok(self.first(&statement).await.unwrap());
101    }
102    
103    async fn update<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<()> {
104        self.execute_query(Builder::new(&statement.query).update().unwrap(), statement.arguments.clone()).await.unwrap();
105        return Ok(());
106    }
107    
108    async fn count<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<u64> {
109        let query = {
110            let mut query = statement.query.clone();
111            query.select = vec!["COUNT(*) as total".to_string()];
112            query
113        };
114
115        return self.fetch_one::<Total>(Builder::new(&query).query().unwrap(), statement.arguments.clone())
116            .await
117            .map(|t| t.total);
118    }
119    
120    async fn delete<'q>(&self, statement: &'q Statement<'q, Self::T>) -> Result<()> {
121        self.execute_query(Builder::new(&statement.query).delete().unwrap(), statement.arguments.clone()).await.unwrap();
122        return Ok(());
123    }
124    
125    async fn query_all<'q, O, T: 'q + sqlx::Encode<'q, Self::T> + sqlx::Type<Self::T>>(&self, sql: &str, args: Vec<T>) -> Result<Vec<O>>
126    where
127        O: for<'r> sqlx::FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized
128    {
129        let mut arguments: <Self::T as sqlx::Database>::Arguments<'q> = Default::default();
130
131        for arg in args { arguments.add(arg).unwrap(); }
132
133        return self.fetch_all(String::from(sql), arguments).await;
134    }
135    
136    async fn query_one<'q, O, T: 'q + sqlx::Encode<'q, Self::T> + sqlx::Type<Self::T>>(&self, sql: &str, args: Vec<T>) -> Result<O>
137    where
138        O: for<'r> sqlx::FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized
139    {
140        let mut arguments: <Self::T as sqlx::Database>::Arguments<'q> = Default::default();
141
142        for arg in args { arguments.add(arg).unwrap(); }
143
144        return self.fetch_one(String::from(sql), arguments).await;
145    }
146    
147    async fn first<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<O>
148    where
149        O: for<'r> sqlx::FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized
150    {
151        return self.fetch_one(self.to_sql(statement).unwrap(), statement.arguments.clone()).await;
152    }
153    
154    async fn all<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<Vec<O>>
155    where
156        O: for<'r> sqlx::FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized
157    {
158        return self.fetch_all::<O>(self.to_sql(statement).unwrap(), statement.arguments.clone()).await;
159    }
160
161    async fn paginate<'q, O>(&self, statement: &'q Statement<'q, Self::T>) -> Result<Pagination<O>>
162    where
163        O: for<'r> sqlx::FromRow<'r, <Self::T as sqlx::Database>::Row> + Send + Unpin + Sized
164    {
165        let mut query = statement.query.clone();
166
167        query.select = vec!["COUNT(*) as total".to_string()];
168        query.limit = None;
169        query.page = None;
170
171        return Ok(
172            Pagination {
173                page: statement.query.page.unwrap(),
174                per_page: statement.query.limit.unwrap(),
175                total: self.fetch_one::<Total>(self.to_sql(statement).unwrap(), statement.arguments.clone()).await.unwrap().total,
176                items: self.fetch_all::<O>(self.to_sql(statement).unwrap(), statement.arguments.clone()).await.unwrap(),
177            }
178        );
179    }
180}