1use libsql::{de, params::IntoValue};
40#[cfg(feature = "log")]
41use log::{debug, error};
42use serde::{Serialize, de::DeserializeOwned};
43use std::collections::HashMap;
44
45use crate::{
46 GeekConnection, QueryBuilderTrait, TableBuilder, Value, Values, builder::models::QueryType,
47};
48
49#[cfg(feature = "backends-tokio")]
50mod mutex;
51
52impl GeekConnection for libsql::Connection {
53 type Connection = libsql::Connection;
54
55 async fn create_table<T>(connection: &Self::Connection) -> Result<(), crate::Error>
56 where
57 T: TableBuilder + QueryBuilderTrait + Sized + Serialize + DeserializeOwned,
58 {
59 let query = T::query_create().build()?;
60 #[cfg(feature = "log")]
61 {
62 debug!("Create Table Query :: {:?}", query.to_str());
63 }
64 connection.execute(query.to_str(), ()).await.map_err(|e| {
65 crate::Error::QuerySyntaxError {
66 error: e.to_string(),
67 query: query.to_string(),
68 }
69 })?;
70 Ok(())
71 }
72
73 async fn row_count(
74 connection: &Self::Connection,
75 query: crate::Query,
76 ) -> Result<i64, crate::Error> {
77 #[cfg(feature = "log")]
78 {
79 debug!("Row Count Query :: {:?}", query.to_str());
80 }
81 let mut statement = connection.prepare(query.to_str()).await.map_err(|e| {
82 crate::Error::QuerySyntaxError {
83 error: e.to_string(),
84 query: query.to_string(),
85 }
86 })?;
87
88 let parameters: Vec<libsql::Value> = convert_values(&query)?;
89
90 let mut rows =
91 statement
92 .query(parameters)
93 .await
94 .map_err(|e| crate::Error::LibSQLError {
95 error: e.to_string(),
96 query: query.to_string(),
97 })?;
98
99 let row = match rows.next().await.map_err(|e| crate::Error::LibSQLError {
100 error: e.to_string(),
101 query: query.to_string(),
102 })? {
103 Some(row) => row,
104 None => {
105 #[cfg(feature = "log")]
106 {
107 error!("Error fetching row count");
108 }
109 return Err(crate::Error::LibSQLError {
110 error: "Error fetching row count".to_string(),
111 query: query.to_string(),
112 });
113 }
114 };
115 row.get(0).map_err(|e| crate::Error::LibSQLError {
117 error: e.to_string(),
118 query: query.to_string(),
119 })
120 }
121
122 async fn query<T>(
123 connection: &Self::Connection,
124 query: crate::Query,
125 ) -> Result<Vec<T>, crate::Error>
126 where
127 T: serde::de::DeserializeOwned,
128 {
129 #[cfg(feature = "log")]
130 {
131 debug!("Query :: {:?}", query.to_str());
132 }
133
134 let mut statement = connection.prepare(query.to_str()).await.map_err(|e| {
135 crate::Error::QuerySyntaxError {
136 error: e.to_string(),
137 query: query.to_string(),
138 }
139 })?;
140
141 let parameters: Vec<libsql::Value> = convert_values(&query)?;
142
143 #[cfg(feature = "log")]
144 {
145 debug!("Parameters :: {:?}", parameters.clone());
146 }
147
148 let mut rows =
150 statement
151 .query(parameters)
152 .await
153 .map_err(|e| crate::Error::LibSQLError {
154 error: e.to_string(),
155 query: query.to_string(),
156 })?;
157
158 let mut results = Vec::new();
159
160 while let Some(row) = rows.next().await.map_err(|e| crate::Error::LibSQLError {
161 error: e.to_string(),
162 query: query.to_string(),
163 })? {
164 results.push(de::from_row::<T>(&row).map_err(|e| {
165 #[cfg(feature = "log")]
166 {
167 error!("Error deserializing row: `{}`", e);
168 }
169 crate::Error::SerdeError(e.to_string())
170 })?);
171 }
172
173 Ok(results)
174 }
175
176 async fn query_first<T>(
177 connection: &Self::Connection,
178 query: crate::Query,
179 ) -> Result<T, crate::Error>
180 where
181 T: serde::de::DeserializeOwned,
182 {
183 if query.query_type == QueryType::Update {
185 #[cfg(feature = "log")]
186 {
187 error!(
188 "Query type is an `update`, use execute() instead as it does not return a row"
189 );
190 }
191 return Err(crate::Error::LibSQLError {
192 error: "Query type is an `update`".to_string(),
193 query: query.to_string(),
194 });
195 }
196
197 let mut statement = connection.prepare(query.to_str()).await.map_err(|e| {
198 crate::Error::QuerySyntaxError {
199 error: e.to_string(),
200 query: query.to_string(),
201 }
202 })?;
203
204 let parameters: Vec<libsql::Value> = convert_values(&query)?;
206
207 #[cfg(feature = "log")]
208 {
209 debug!("Query :: {:?}", query.to_str());
210 debug!("Parameters :: {:?}", parameters.clone());
211 }
212
213 let mut rows =
215 statement
216 .query(parameters)
217 .await
218 .map_err(|e| crate::Error::LibSQLError {
219 error: e.to_string(),
220 query: query.to_string(),
221 })?;
222
223 let row: libsql::Row = match rows.next().await? {
224 Some(row) => row,
225 None => {
226 #[cfg(feature = "log")]
227 {
228 error!("No rows found for query: `{}`", query.to_str());
229 }
230 return Err(crate::Error::NoRowsFound {
231 query: query.to_string(),
232 });
233 }
234 };
235
236 de::from_row::<T>(&row).map_err(|e| {
237 #[cfg(feature = "log")]
238 {
239 error!("Error deserializing row: `{}`", e);
240 }
241 crate::Error::SerdeError(e.to_string())
242 })
243 }
244
245 async fn execute(
246 connection: &Self::Connection,
247 query: crate::Query,
248 ) -> Result<(), crate::Error> {
249 let parameters: Vec<libsql::Value> = convert_values(&query)?;
251
252 connection
253 .execute(query.to_str(), parameters)
254 .await
255 .map_err(|e| crate::Error::QuerySyntaxError {
256 error: e.to_string(),
257 query: query.to_string(),
258 })?;
259 Ok(())
260 }
261
262 async fn batch(connection: &Self::Connection, query: crate::Query) -> Result<(), crate::Error> {
263 connection
264 .execute_batch(query.to_str())
265 .await
266 .map_err(|e| crate::Error::QuerySyntaxError {
267 error: e.to_string(),
268 query: query.to_string(),
269 })?;
270 Ok(())
271 }
272
273 async fn query_raw(
274 connection: &Self::Connection,
275 query: crate::Query,
276 ) -> Result<Vec<HashMap<String, Value>>, crate::Error> {
277 let params = convert_values(&query)?;
278
279 let mut statement = connection.prepare(query.to_str()).await.map_err(|e| {
280 crate::Error::QuerySyntaxError {
281 error: e.to_string(),
282 query: query.to_string(),
283 }
284 })?;
285
286 #[cfg(feature = "log")]
287 {
288 debug!("Query :: {:?}", query.to_str());
289 debug!("Parameters :: {:?}", params);
290 }
291
292 let mut rows = statement
293 .query(params)
294 .await
295 .map_err(|e| crate::Error::LibSQLError {
296 error: e.to_string(),
297 query: query.to_string(),
298 })?;
299
300 let mut results: Vec<HashMap<String, Value>> = Vec::new();
301
302 while let Some(row) = rows.next().await? {
303 let mut values: HashMap<String, Value> = HashMap::new();
304
305 for (index, column_name) in query.columns.iter().enumerate() {
306 let value = row.get_value(index as i32).unwrap();
307 values.insert(column_name.to_string(), value.into());
308 }
309 results.push(values);
310 }
311
312 Ok(results)
313 }
314}
315
316fn convert_values(query: &crate::Query) -> Result<Vec<libsql::Value>, crate::Error> {
317 let mut parameters: Vec<libsql::Value> = Vec::new();
318
319 let values: &Values = match query.query_type {
321 QueryType::Insert | QueryType::Update => &query.parameters,
322 _ => &query.values,
323 };
324
325 for (column_name, value) in &values.values {
326 if let Some(column) = query.table.columns.get(column_name.as_str()) {
329 if query.query_type == QueryType::Insert && column.column_type.is_auto_increment() {
331 continue;
332 } else if query.query_type == QueryType::Update && column.column_type.is_primary_key() {
333 continue;
334 }
335 }
336
337 #[cfg(feature = "log")]
338 {
339 log::trace!("LIBSQL - Column('{}', '{}')", column_name, value);
340 }
341
342 parameters.push(
343 value
344 .clone()
345 .into_value()
346 .map_err(|e| crate::Error::LibSQLError {
347 error: format!("Error converting value - {}", e),
348 query: query.to_string(),
349 })?,
350 );
351 }
352 Ok(parameters)
353}
354
355impl From<libsql::Error> for crate::Error {
357 fn from(value: libsql::Error) -> Self {
358 #[cfg(feature = "log")]
359 {
360 log::error!("LibSQL Error: `{}`", value);
361 }
362
363 crate::Error::LibSQLError {
364 error: value.to_string(),
365 query: String::new(),
366 }
367 }
368}
369
370impl From<(libsql::Error, String)> for crate::Error {
371 fn from(value: (libsql::Error, String)) -> Self {
372 #[cfg(feature = "log")]
373 {
374 log::error!("LibSQL Error: `{}`", value.0);
375 log::error!("LibSQL Error Query: `{}`", value.1);
376 }
377
378 crate::Error::LibSQLError {
379 error: value.0.to_string(),
380 query: value.1,
381 }
382 }
383}
384
385impl IntoValue for Value {
386 fn into_value(self) -> libsql::Result<libsql::Value> {
387 Ok(match self {
388 Value::Text(value) => libsql::Value::Text(value),
389 Value::Integer(value) => libsql::Value::Integer(value),
390 Value::Boolean(value) => libsql::Value::Text(value.to_string()),
391 Value::Identifier(value) => libsql::Value::Integer(value as i64),
393 Value::Blob(value) | Value::Json(value) => libsql::Value::Blob(value),
394 Value::Null => libsql::Value::Null,
395 })
396 }
397}
398
399impl From<libsql::Value> for Value {
400 fn from(value: libsql::Value) -> Self {
401 match value {
402 libsql::Value::Text(value) => Value::Text(value),
403 libsql::Value::Integer(value) => Value::Integer(value),
404 libsql::Value::Null => Value::Null,
405 libsql::Value::Blob(value) => {
406 if let Some(start) = value.first() {
408 if *start == b'{' || *start == b'[' {
409 return Value::Json(value);
410 }
411 }
412 Value::Blob(value)
413 }
414 libsql::Value::Real(_) => {
415 todo!("Real values are not supported yet")
416 }
417 }
418 }
419}