1pub mod config;
2pub mod mysql;
3pub mod postgres;
4pub mod redis;
5pub mod sqlite;
6pub mod types;
7
8use async_trait::async_trait;
9use serde::Serialize;
10use std::fmt::Debug;
11
12pub use config::{DatabaseConfig, DatabaseType};
13
14pub type DbResult<T> = Result<T, String>;
15
16#[async_trait]
17pub trait DatabaseConnection: Send + Sync + Debug {
18 async fn execute(&self, sql: &str) -> DbResult<u64>;
19 async fn query(&self, sql: &str) -> DbResult<String>;
20 async fn query_one(&self, sql: &str) -> DbResult<String>;
21 async fn insert_batch(&self, table: &str, json_data: &str) -> DbResult<u64>;
22}
23
24pub fn to_sql_value<T: Serialize>(value: &T) -> DbResult<String> {
25 let json = serde_json::to_value(value).map_err(|e| e.to_string())?;
26 match json {
27 serde_json::Value::String(s) => Ok(format!("'{}'", s.replace("'", "''"))),
28 serde_json::Value::Number(n) => Ok(n.to_string()),
29 serde_json::Value::Bool(b) => Ok(if b { "1".to_string() } else { "0".to_string() }),
30 serde_json::Value::Null => Ok("NULL".to_string()),
31 _ => Ok(format!("'{}'", json.to_string().replace("'", "''"))),
32 }
33}
34
35#[derive(Debug)]
36pub enum DbConnection {
37 MySql(mysql::MySqlConnection),
38 Postgres(postgres::PostgresConnection),
39 Sqlite(sqlite::SqliteConnection),
40 Redis(redis::RedisConnection),
41}
42
43#[async_trait]
44impl DatabaseConnection for DbConnection {
45 async fn execute(&self, sql: &str) -> DbResult<u64> {
46 match self {
47 DbConnection::MySql(conn) => conn.execute(sql).await,
48 DbConnection::Postgres(conn) => conn.execute(sql).await,
49 DbConnection::Sqlite(conn) => conn.execute(sql).await,
50 DbConnection::Redis(conn) => conn.execute(sql).await,
51 }
52 }
53
54 async fn query(&self, sql: &str) -> DbResult<String> {
55 match self {
56 DbConnection::MySql(conn) => conn.query(sql).await,
57 DbConnection::Postgres(conn) => conn.query(sql).await,
58 DbConnection::Sqlite(conn) => conn.query(sql).await,
59 DbConnection::Redis(conn) => conn.query(sql).await,
60 }
61 }
62
63 async fn query_one(&self, sql: &str) -> DbResult<String> {
64 match self {
65 DbConnection::MySql(conn) => conn.query_one(sql).await,
66 DbConnection::Postgres(conn) => conn.query_one(sql).await,
67 DbConnection::Sqlite(conn) => conn.query_one(sql).await,
68 DbConnection::Redis(conn) => conn.query_one(sql).await,
69 }
70 }
71
72 async fn insert_batch(&self, table: &str, json_data: &str) -> DbResult<u64> {
73 match self {
74 DbConnection::MySql(conn) => conn.insert_batch(table, json_data).await,
75 DbConnection::Postgres(conn) => conn.insert_batch(table, json_data).await,
76 DbConnection::Sqlite(conn) => conn.insert_batch(table, json_data).await,
77 DbConnection::Redis(conn) => conn.insert_batch(table, json_data).await,
78 }
79 }
80}
81
82pub async fn connect(config: &DatabaseConfig) -> DbResult<DbConnection> {
83 match config.database_type {
84 DatabaseType::MySql => {
85 let conn = mysql::MySqlConnection::connect(config).await?;
86 Ok(DbConnection::MySql(conn))
87 }
88 DatabaseType::Postgres => {
89 let conn = postgres::PostgresConnection::connect(config).await?;
90 Ok(DbConnection::Postgres(conn))
91 }
92 DatabaseType::Sqlite => {
93 let conn = sqlite::SqliteConnection::connect(config).await?;
94 Ok(DbConnection::Sqlite(conn))
95 }
96 DatabaseType::Redis => {
97 let conn = redis::RedisConnection::connect(config).await?;
98 Ok(DbConnection::Redis(conn))
99 }
100 }
101}