wae_database/connection/
turso.rs1use crate::connection::{
4 config::{DatabaseConfig, DatabaseResult},
5 row::DatabaseRows,
6 statement::DatabaseStatement,
7 trait_impl::DatabaseConnection,
8};
9use async_trait::async_trait;
10use std::path::PathBuf;
11use turso::{Builder, Connection, Database, Value as TursoValue};
12use wae_types::{DatabaseErrorKind, WaeError};
13
14pub struct TursoConnection {
16 conn: Connection,
17}
18
19impl TursoConnection {
20 pub(crate) fn new(conn: Connection) -> Self {
21 Self { conn }
22 }
23}
24
25#[async_trait]
26impl DatabaseConnection for TursoConnection {
27 async fn query(&self, sql: &str) -> DatabaseResult<DatabaseRows> {
28 let mut stmt = self.conn.prepare(sql).await.map_err(|e| {
29 WaeError::database(DatabaseErrorKind::QueryFailed {
30 query: Some(sql.to_string()),
31 message: format!("Prepare failed: {}", e),
32 })
33 })?;
34 let rows = stmt.query(()).await.map_err(|e| {
35 WaeError::database(DatabaseErrorKind::QueryFailed {
36 query: Some(sql.to_string()),
37 message: format!("Query failed: {}", e),
38 })
39 })?;
40 Ok(DatabaseRows::new_turso(rows))
41 }
42
43 async fn query_with(&self, sql: &str, params: Vec<wae_types::Value>) -> DatabaseResult<DatabaseRows> {
44 let turso_params = crate::types::from_wae_values(params);
45 self.query_with_turso(sql, turso_params).await
46 }
47
48 async fn execute(&self, sql: &str) -> DatabaseResult<u64> {
49 self.conn.execute(sql, ()).await.map_err(|e| {
50 WaeError::database(DatabaseErrorKind::ExecuteFailed {
51 query: Some(sql.to_string()),
52 message: format!("Execute failed: {}", e),
53 })
54 })
55 }
56
57 async fn execute_with(&self, sql: &str, params: Vec<wae_types::Value>) -> DatabaseResult<u64> {
58 let turso_params = crate::types::from_wae_values(params);
59 self.execute_with_turso(sql, turso_params).await
60 }
61
62 async fn prepare(&self, sql: &str) -> DatabaseResult<DatabaseStatement> {
63 self.conn
64 .prepare(sql)
65 .await
66 .map_err(|e| {
67 WaeError::database(DatabaseErrorKind::QueryFailed {
68 query: Some(sql.to_string()),
69 message: format!("Prepare failed: {}", e),
70 })
71 })
72 .map(DatabaseStatement::new_turso)
73 }
74
75 async fn query_with_turso(&self, sql: &str, params: Vec<TursoValue>) -> DatabaseResult<DatabaseRows> {
76 let mut stmt = self.conn.prepare(sql).await.map_err(|e| {
77 WaeError::database(DatabaseErrorKind::QueryFailed {
78 query: Some(sql.to_string()),
79 message: format!("Prepare failed: {}", e),
80 })
81 })?;
82 let rows = stmt.query(params).await.map_err(|e| {
83 WaeError::database(DatabaseErrorKind::QueryFailed {
84 query: Some(sql.to_string()),
85 message: format!("Query failed: {}", e),
86 })
87 })?;
88 Ok(DatabaseRows::new_turso(rows))
89 }
90
91 async fn execute_with_turso(&self, sql: &str, params: Vec<TursoValue>) -> DatabaseResult<u64> {
92 self.conn.execute(sql, params).await.map_err(|e| {
93 WaeError::database(DatabaseErrorKind::ExecuteFailed {
94 query: Some(sql.to_string()),
95 message: format!("Execute failed: {}", e),
96 })
97 })
98 }
99}
100
101pub struct DatabaseService {
103 db: Database,
104}
105
106impl DatabaseService {
107 pub async fn new(config: &DatabaseConfig) -> DatabaseResult<Self> {
109 match config {
110 DatabaseConfig::Turso { path } => {
111 let db = match path {
112 Some(path) => {
113 let path_str = path.to_string_lossy().into_owned();
114 Builder::new_local(&path_str).build().await.map_err(|e| {
115 WaeError::database(DatabaseErrorKind::ConnectionFailed {
116 message: format!("Failed to create database: {}", e),
117 })
118 })?
119 }
120 None => Builder::new_local(":memory:").build().await.map_err(|e| {
121 WaeError::database(DatabaseErrorKind::ConnectionFailed {
122 message: format!("Failed to create database: {}", e),
123 })
124 })?,
125 };
126 Ok(Self { db })
127 }
128 #[cfg(feature = "postgres")]
129 DatabaseConfig::Postgres { .. } => Err(WaeError::database(DatabaseErrorKind::ConnectionFailed {
130 message: "Use PostgresDatabaseService for Postgres".to_string(),
131 })),
132 #[cfg(feature = "mysql")]
133 DatabaseConfig::MySql { .. } => Err(WaeError::database(DatabaseErrorKind::ConnectionFailed {
134 message: "Use MySqlDatabaseService for MySQL".to_string(),
135 })),
136 }
137 }
138
139 pub async fn in_memory() -> DatabaseResult<Self> {
141 Self::new(&DatabaseConfig::turso_in_memory()).await
142 }
143
144 pub async fn file<P: Into<PathBuf>>(path: P) -> DatabaseResult<Self> {
146 Self::new(&DatabaseConfig::turso_file(path)).await
147 }
148
149 pub fn connect(&self) -> DatabaseResult<TursoConnection> {
151 let conn = self.db.connect().map_err(|e| WaeError::internal(format!("Failed to connect: {}", e)))?;
152 Ok(TursoConnection::new(conn))
153 }
154}