wae_database/connection/
turso.rs1use crate::connection::{
4 config::{DatabaseConfig, DatabaseResult},
5 row::DatabaseRows,
6 statement::DatabaseStatement,
7 trait_impl::{DatabaseBackend, DatabaseConnection},
8};
9use async_trait::async_trait;
10use std::path::PathBuf;
11use turso::{Builder, Connection, Database, Value as TursoValue};
12use wae_types::{WaeError, WaeErrorKind};
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 fn backend(&self) -> DatabaseBackend {
28 DatabaseBackend::Turso
29 }
30
31 async fn query(&self, sql: &str) -> DatabaseResult<DatabaseRows> {
32 let mut stmt = self.conn.prepare(sql).await.map_err(|e| {
33 WaeError::database(WaeErrorKind::QueryFailed {
34 query: Some(sql.to_string()),
35 reason: format!("Prepare failed: {}", e),
36 })
37 })?;
38 let rows = stmt.query(()).await.map_err(|e| {
39 WaeError::database(WaeErrorKind::QueryFailed {
40 query: Some(sql.to_string()),
41 reason: format!("Query failed: {}", e),
42 })
43 })?;
44 Ok(DatabaseRows::new_turso(rows))
45 }
46
47 async fn query_with(&self, sql: &str, params: Vec<wae_types::Value>) -> DatabaseResult<DatabaseRows> {
48 let turso_params = crate::types::from_wae_values(params);
49 self.query_with_turso(sql, turso_params).await
50 }
51
52 async fn execute(&self, sql: &str) -> DatabaseResult<u64> {
53 self.conn.execute(sql, ()).await.map_err(|e| {
54 WaeError::database(WaeErrorKind::ExecuteFailed {
55 statement: Some(sql.to_string()),
56 reason: format!("Execute failed: {}", e),
57 })
58 })
59 }
60
61 async fn execute_with(&self, sql: &str, params: Vec<wae_types::Value>) -> DatabaseResult<u64> {
62 let turso_params = crate::types::from_wae_values(params);
63 self.execute_with_turso(sql, turso_params).await
64 }
65
66 async fn prepare(&self, sql: &str) -> DatabaseResult<DatabaseStatement> {
67 self.conn
68 .prepare(sql)
69 .await
70 .map_err(|e| {
71 WaeError::database(WaeErrorKind::QueryFailed {
72 query: Some(sql.to_string()),
73 reason: format!("Prepare failed: {}", e),
74 })
75 })
76 .map(DatabaseStatement::new_turso)
77 }
78
79 async fn begin_transaction(&self) -> DatabaseResult<()> {
80 self.conn.execute("BEGIN TRANSACTION", ()).await.map_err(|e| {
81 WaeError::database(WaeErrorKind::DatabaseConnectionFailed { reason: format!("Failed to begin transaction: {}", e) })
82 })?;
83 Ok(())
84 }
85
86 async fn commit(&self) -> DatabaseResult<()> {
87 self.conn.execute("COMMIT", ()).await.map_err(|e| {
88 WaeError::database(WaeErrorKind::DatabaseConnectionFailed {
89 reason: format!("Failed to commit transaction: {}", e),
90 })
91 })?;
92 Ok(())
93 }
94
95 async fn rollback(&self) -> DatabaseResult<()> {
96 self.conn.execute("ROLLBACK", ()).await.map_err(|e| {
97 WaeError::database(WaeErrorKind::DatabaseConnectionFailed {
98 reason: format!("Failed to rollback transaction: {}", e),
99 })
100 })?;
101 Ok(())
102 }
103
104 async fn query_with_turso(&self, sql: &str, params: Vec<TursoValue>) -> DatabaseResult<DatabaseRows> {
105 let mut stmt = self.conn.prepare(sql).await.map_err(|e| {
106 WaeError::database(WaeErrorKind::QueryFailed {
107 query: Some(sql.to_string()),
108 reason: format!("Prepare failed: {}", e),
109 })
110 })?;
111 let rows = stmt.query(params).await.map_err(|e| {
112 WaeError::database(WaeErrorKind::QueryFailed {
113 query: Some(sql.to_string()),
114 reason: format!("Query failed: {}", e),
115 })
116 })?;
117 Ok(DatabaseRows::new_turso(rows))
118 }
119
120 async fn execute_with_turso(&self, sql: &str, params: Vec<TursoValue>) -> DatabaseResult<u64> {
121 self.conn.execute(sql, params).await.map_err(|e| {
122 WaeError::database(WaeErrorKind::ExecuteFailed {
123 statement: Some(sql.to_string()),
124 reason: format!("Execute failed: {}", e),
125 })
126 })
127 }
128}
129
130pub struct DatabaseService {
132 db: Database,
133}
134
135impl DatabaseService {
136 pub async fn new(config: &DatabaseConfig) -> DatabaseResult<Self> {
138 match config {
139 DatabaseConfig::Turso { path } => {
140 let db = match path {
141 Some(path) => {
142 let path_str = path.to_string_lossy().into_owned();
143 Builder::new_local(&path_str).build().await.map_err(|e| {
144 WaeError::database(WaeErrorKind::DatabaseConnectionFailed {
145 reason: format!("Failed to create database: {}", e),
146 })
147 })?
148 }
149 None => Builder::new_local(":memory:").build().await.map_err(|e| {
150 WaeError::database(WaeErrorKind::DatabaseConnectionFailed {
151 reason: format!("Failed to create database: {}", e),
152 })
153 })?,
154 };
155 Ok(Self { db })
156 }
157 #[cfg(feature = "postgres")]
158 DatabaseConfig::Postgres { .. } => Err(WaeError::database(WaeErrorKind::DatabaseConnectionFailed {
159 reason: "Use PostgresDatabaseService for Postgres".to_string(),
160 })),
161 #[cfg(feature = "mysql")]
162 DatabaseConfig::MySql { .. } => Err(WaeError::database(WaeErrorKind::DatabaseConnectionFailed {
163 reason: "Use MySqlDatabaseService for MySQL".to_string(),
164 })),
165 }
166 }
167
168 pub async fn in_memory() -> DatabaseResult<Self> {
170 Self::new(&DatabaseConfig::turso_in_memory()).await
171 }
172
173 pub async fn file<P: Into<PathBuf>>(path: P) -> DatabaseResult<Self> {
175 Self::new(&DatabaseConfig::turso_file(path)).await
176 }
177
178 pub fn connect(&self) -> DatabaseResult<TursoConnection> {
180 let conn = self.db.connect().map_err(|e| {
181 WaeError::database(WaeErrorKind::DatabaseConnectionFailed { reason: format!("Failed to connect: {}", e) })
182 })?;
183 Ok(TursoConnection::new(conn))
184 }
185}