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::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
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    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
101/// Turso 数据库服务
102pub struct DatabaseService {
103    db: Database,
104}
105
106impl DatabaseService {
107    /// 从配置创建数据库服务
108    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    /// 创建内存数据库
140    pub async fn in_memory() -> DatabaseResult<Self> {
141        Self::new(&DatabaseConfig::turso_in_memory()).await
142    }
143
144    /// 创建文件数据库
145    pub async fn file<P: Into<PathBuf>>(path: P) -> DatabaseResult<Self> {
146        Self::new(&DatabaseConfig::turso_file(path)).await
147    }
148
149    /// 获取连接
150    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}