1#[cfg(any(feature = "db-sqlite", feature = "db-postgres", feature = "db-mysql"))]
2use sqlx::Pool as SqlxPool;
3#[cfg(feature = "db-mysql")]
4use sqlx::{MySql, mysql::MySqlPoolOptions};
5#[cfg(feature = "db-postgres")]
6use sqlx::{Postgres, postgres::PgPoolOptions};
7#[cfg(feature = "db-sqlite")]
8use sqlx::{Sqlite, sqlite::SqlitePoolOptions};
9
10use crate::db::{DatabaseConfig, DatabaseError, DatabaseKind, DatabaseResult};
11
12#[cfg(feature = "db-sqlite")]
14pub type SqliteDatabasePool = SqlxPool<Sqlite>;
15
16#[cfg(feature = "db-postgres")]
18pub type PostgresDatabasePool = SqlxPool<Postgres>;
19
20#[cfg(feature = "db-mysql")]
22pub type MySqlDatabasePool = SqlxPool<MySql>;
23
24#[cfg(feature = "db-sqlite")]
26pub type DatabasePool = SqliteDatabasePool;
27
28#[cfg(all(not(feature = "db-sqlite"), feature = "db-postgres"))]
30pub type DatabasePool = PostgresDatabasePool;
31
32#[cfg(all(
34 not(feature = "db-sqlite"),
35 not(feature = "db-postgres"),
36 feature = "db-mysql"
37))]
38pub type DatabasePool = MySqlDatabasePool;
39
40#[cfg(feature = "db-sqlite")]
42pub async fn connect_pool(config: &DatabaseConfig) -> DatabaseResult<DatabasePool> {
43 connect_sqlite_pool(config).await
44}
45
46#[cfg(all(not(feature = "db-sqlite"), feature = "db-postgres"))]
48pub async fn connect_pool(config: &DatabaseConfig) -> DatabaseResult<DatabasePool> {
49 connect_postgres_pool(config).await
50}
51
52#[cfg(all(
54 not(feature = "db-sqlite"),
55 not(feature = "db-postgres"),
56 feature = "db-mysql"
57))]
58pub async fn connect_pool(config: &DatabaseConfig) -> DatabaseResult<DatabasePool> {
59 connect_mysql_pool(config).await
60}
61
62#[cfg(feature = "db-sqlite")]
64pub async fn connect_sqlite_pool(config: &DatabaseConfig) -> DatabaseResult<SqliteDatabasePool> {
65 if config.kind != DatabaseKind::Sqlite {
66 return Err(DatabaseError::Unsupported(
67 "sqlite database kind required".to_string(),
68 ));
69 }
70 Ok(SqlitePoolOptions::new()
71 .max_connections(config.max_connections)
72 .acquire_timeout(config.connect_timeout)
73 .connect(&config.url)
74 .await?)
75}
76
77#[cfg(feature = "db-postgres")]
79pub async fn connect_postgres_pool(
80 config: &DatabaseConfig,
81) -> DatabaseResult<PostgresDatabasePool> {
82 if config.kind != DatabaseKind::Postgres {
83 return Err(DatabaseError::Unsupported(
84 "postgres database kind required".to_string(),
85 ));
86 }
87 Ok(PgPoolOptions::new()
88 .max_connections(config.max_connections)
89 .acquire_timeout(config.connect_timeout)
90 .connect(&config.url)
91 .await?)
92}
93
94#[cfg(feature = "db-mysql")]
96pub async fn connect_mysql_pool(config: &DatabaseConfig) -> DatabaseResult<MySqlDatabasePool> {
97 if config.kind != DatabaseKind::Mysql {
98 return Err(DatabaseError::Unsupported(
99 "mysql database kind required".to_string(),
100 ));
101 }
102 Ok(MySqlPoolOptions::new()
103 .max_connections(config.max_connections)
104 .acquire_timeout(config.connect_timeout)
105 .connect(&config.url)
106 .await?)
107}
108
109pub async fn health_check(pool: &DatabasePool) -> DatabaseResult<()> {
111 sqlx::query("SELECT 1").execute(pool).await?;
112 Ok(())
113}
114
115#[cfg(all(feature = "db-postgres", feature = "db-sqlite"))]
117pub async fn health_check_postgres(pool: &PostgresDatabasePool) -> DatabaseResult<()> {
118 sqlx::query("SELECT 1").execute(pool).await?;
119 Ok(())
120}
121
122#[cfg(all(
124 feature = "db-mysql",
125 any(feature = "db-sqlite", feature = "db-postgres")
126))]
127pub async fn health_check_mysql(pool: &MySqlDatabasePool) -> DatabaseResult<()> {
128 sqlx::query("SELECT 1").execute(pool).await?;
129 Ok(())
130}
131
132#[cfg(test)]
133mod tests {
134 use crate::db::{DatabaseConfig, DatabaseKind};
135 #[cfg(feature = "db-sqlite")]
136 use crate::db::{connect_pool, health_check};
137
138 #[cfg(feature = "db-sqlite")]
139 #[tokio::test]
140 async fn sqlite_pool_passes_health_check() {
141 let pool = connect_pool(&DatabaseConfig::default())
142 .await
143 .expect("pool");
144 health_check(&pool).await.expect("health");
145 }
146
147 #[test]
148 fn postgres_config_uses_postgres_kind() {
149 let config = DatabaseConfig::postgres("postgres://localhost/app");
150 assert_eq!(config.kind, DatabaseKind::Postgres);
151 }
152
153 #[test]
154 fn mysql_config_uses_mysql_kind() {
155 let config = DatabaseConfig::mysql("mysql://localhost/app");
156 assert_eq!(config.kind, DatabaseKind::Mysql);
157 }
158}