bubble_db/
lib.rs

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}