Skip to main content

wae_database/connection/
turso.rs

1//! Turso 数据库实现
2
3use 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
14/// Turso 连接包装
15pub 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
130/// Turso 数据库服务
131pub struct DatabaseService {
132    db: Database,
133}
134
135impl DatabaseService {
136    /// 从配置创建数据库服务
137    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    /// 创建内存数据库
169    pub async fn in_memory() -> DatabaseResult<Self> {
170        Self::new(&DatabaseConfig::turso_in_memory()).await
171    }
172
173    /// 创建文件数据库
174    pub async fn file<P: Into<PathBuf>>(path: P) -> DatabaseResult<Self> {
175        Self::new(&DatabaseConfig::turso_file(path)).await
176    }
177
178    /// 获取连接
179    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}