geekorm_core/backends/
rusqlite.rs

1//! # RuSQLite Backend
2//!
3//! **Example:**
4//!
5//! ```no_run
6//! # #[cfg(feature = "backends")] {
7//! # use anyhow::Result;
8//! use geekorm::prelude::*;
9//!
10//! #[derive(Table, Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
11//! pub struct Users {
12//!     #[geekorm(primary_key, auto_increment)]
13//!     pub id: PrimaryKeyInteger,
14//!     #[geekorm(unique)]
15//!     pub username: String,
16//! }
17//!
18//! #[tokio::main]
19//! async fn main() -> Result<()> {
20//!     let connection = rusqlite::Connection::open_in_memory()
21//!         .expect("Failed to open connection");
22//!
23//!     Users::create_table(&connection).await?;
24//!
25//!     let mut user = Users::new("geekmasher");
26//!     user.save(&connection).await?;
27//!
28//!     let geekmasher = Users::fetch_by_username(&connection, "geekmasher").await?;
29//!
30//!     Ok(())
31//! }
32//! # }
33//! ```
34
35#[cfg(feature = "log")]
36use log::debug;
37use rusqlite::ToSql;
38use serde_rusqlite::*;
39
40use super::GeekConnection;
41
42impl GeekConnection for rusqlite::Connection {
43    type Connection = rusqlite::Connection;
44
45    async fn create_table<T>(connection: &Self::Connection) -> std::result::Result<(), crate::Error>
46    where
47        T: crate::TableBuilder
48            + crate::QueryBuilderTrait
49            + Sized
50            + serde::Serialize
51            + serde::de::DeserializeOwned,
52    {
53        let query = T::query_create().build()?;
54        #[cfg(feature = "log")]
55        {
56            debug!("Create Table Query :: {:?}", query.to_str());
57        }
58        connection
59            .execute(query.to_str(), ())
60            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
61        Ok(())
62    }
63
64    async fn query<T>(
65        connection: &Self::Connection,
66        query: crate::Query,
67    ) -> std::result::Result<Vec<T>, crate::Error>
68    where
69        T: serde::de::DeserializeOwned,
70    {
71        #[cfg(feature = "log")]
72        {
73            debug!("Query :: {:?}", query.to_str());
74        }
75        let mut statement = connection
76            .prepare(query.to_str())
77            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
78
79        let params = if !query.parameters.values.is_empty() {
80            rusqlite::params_from_iter(query.parameters.into_iter())
81        } else {
82            rusqlite::params_from_iter(query.values.into_iter())
83        };
84        #[cfg(feature = "log")]
85        {
86            debug!("Query Params :: {:?}", params);
87        }
88
89        let mut results = Vec::new();
90
91        let mut res = from_rows::<T>(
92            statement
93                .query(params)
94                .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?,
95        );
96        while let Some(Ok(row)) = res.next() {
97            results.push(row);
98        }
99
100        Ok(results)
101    }
102
103    async fn query_first<T>(
104        connection: &Self::Connection,
105        query: crate::Query,
106    ) -> std::result::Result<T, crate::Error>
107    where
108        T: serde::de::DeserializeOwned,
109    {
110        #[cfg(feature = "log")]
111        {
112            debug!("Query First :: {:?}", query.to_str());
113        }
114        let mut statement = connection
115            .prepare(query.to_str())
116            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
117
118        let params = if !query.parameters.values.is_empty() {
119            rusqlite::params_from_iter(query.parameters.into_iter())
120        } else {
121            rusqlite::params_from_iter(query.values.into_iter())
122        };
123        #[cfg(feature = "log")]
124        {
125            debug!("Query First Params :: {:?}", params);
126        }
127
128        let mut res = from_rows::<T>(
129            statement
130                .query(params)
131                .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?,
132        );
133
134        match res.next() {
135            Some(Ok(row)) => Ok(row),
136            _ => Err(crate::Error::RuSQLiteError("No rows found".to_string())),
137        }
138    }
139
140    async fn execute(
141        connection: &Self::Connection,
142        query: crate::Query,
143    ) -> std::result::Result<(), crate::Error> {
144        #[cfg(feature = "log")]
145        {
146            debug!("Execute :: {:?}", query.to_str());
147        }
148        let mut statement = connection
149            .prepare(query.to_str())
150            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
151
152        let params = if !query.parameters.values.is_empty() {
153            rusqlite::params_from_iter(query.parameters.into_iter())
154        } else {
155            rusqlite::params_from_iter(query.values.into_iter())
156        };
157        #[cfg(feature = "log")]
158        {
159            debug!("Execute Params :: {:?}", params);
160        }
161
162        statement
163            .execute(params)
164            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
165        Ok(())
166    }
167
168    async fn batch(
169        connection: &Self::Connection,
170        query: crate::Query,
171    ) -> std::result::Result<(), crate::Error> {
172        #[cfg(feature = "log")]
173        {
174            debug!("Batch :: {:?}", query.to_str());
175        }
176        connection
177            .execute_batch(query.query.as_str())
178            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
179
180        Ok(())
181    }
182
183    async fn row_count(
184        connection: &Self::Connection,
185        query: crate::Query,
186    ) -> std::result::Result<i64, crate::Error> {
187        let mut statement = connection
188            .prepare(query.to_str())
189            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
190        let params = rusqlite::params_from_iter(query.parameters.into_iter());
191        let mut res = statement
192            .query(params)
193            .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?;
194
195        match res.next() {
196            Ok(Some(row)) => Ok(row
197                .get(0)
198                .map_err(|e| crate::Error::RuSQLiteError(e.to_string()))?),
199            _ => Err(crate::Error::RuSQLiteError("No rows found".to_string())),
200        }
201    }
202}
203
204impl ToSql for crate::Value {
205    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
206        match self {
207            crate::Value::Identifier(value) => Ok(rusqlite::types::ToSqlOutput::Owned(
208                rusqlite::types::Value::Integer(*value as i64),
209            )),
210            crate::Value::Text(value) => Ok(rusqlite::types::ToSqlOutput::Owned(
211                rusqlite::types::Value::Text(value.clone()),
212            )),
213            crate::Value::Integer(value) => Ok(rusqlite::types::ToSqlOutput::Owned(
214                rusqlite::types::Value::Integer(*value),
215            )),
216            crate::Value::Blob(value) | crate::Value::Json(value) => Ok(
217                rusqlite::types::ToSqlOutput::Owned(rusqlite::types::Value::Blob(value.clone())),
218            ),
219            crate::Value::Boolean(value) => Ok(rusqlite::types::ToSqlOutput::Owned(
220                rusqlite::types::Value::Integer(*value as i64),
221            )),
222            crate::Value::Null => Ok(rusqlite::types::ToSqlOutput::Owned(
223                rusqlite::types::Value::Null,
224            )),
225        }
226    }
227}