zirv_db_sqlx/lib.rs
1pub mod db;
2
3/// Macro to initialize the global database pool.
4///
5/// This macro wraps the asynchronous function from the `db` module:
6/// `$crate::db::init_db_pool().await`. It should be called early in your application
7/// (e.g., in your `main` function) to set up the database connection pool.
8///
9/// # Example
10/// ```rust
11/// use zirv_db_sqlx::init_db_pool;
12/// use zirv_config::register_config;
13/// use serde::{Serialize, Deserialize};
14///
15/// #[derive(Serialize, Deserialize)]
16/// struct DatabaseConfig {
17/// url: String,
18/// max_connections: u32,
19/// }
20///
21/// # #[tokio::main]
22/// # async fn main() {
23///
24/// register_config!("database", DatabaseConfig {
25/// url: "mysql://root:password@localhost".to_owned(),
26/// max_connections: 10,
27/// });
28/// init_db_pool!();
29/// # }
30/// ```
31#[macro_export]
32macro_rules! init_db_pool {
33 () => {
34 $crate::db::init_db_pool().await;
35 }
36}
37
38/// Macro to retrieve a reference to the global database pool.
39///
40/// This macro wraps the call to `$crate::db::get_db_pool()`, which returns a reference
41/// to the initialized pool. It panics if the pool has not been initialized yet (i.e., if
42/// `init_db_pool!()` has not been called).
43///
44/// # Example
45/// ```rust
46/// use zirv_db_sqlx::get_db_pool;
47///
48/// fn perform_db_operations() {
49/// let pool = get_db_pool!();
50/// // Use `pool` for database operations...
51/// }
52/// ```
53#[macro_export]
54macro_rules! get_db_pool {
55 () => {
56 $crate::db::get_db_pool()
57 }
58}
59
60/// Macro to start a new database transaction.
61///
62/// This macro begins a transaction using the global database pool by calling `begin()` on it.
63/// In case of an error starting the transaction, the error is logged and returned.
64///
65/// # Example
66/// ```rust
67/// use zirv_db_sqlx::{start_transaction, commit_transaction};
68///
69/// async fn perform_db_operations() -> Result<(), sqlx::Error> {
70/// let mut tx = start_transaction!();
71/// // Execute operations within the transaction...
72/// commit_transaction!(tx);
73/// Ok(())
74/// }
75/// ```
76#[macro_export]
77macro_rules! start_transaction {
78 () => {
79 match $crate::db::get_db_pool().begin().await {
80 Ok(tx) => tx,
81 Err(e) => {
82 eprintln!("Failed to start transaction: {:?}", e);
83 return Err(e);
84 }
85 }
86 };
87}
88
89/// Macro to commit an active transaction.
90///
91/// This macro takes a transaction handle as an argument and commits the transaction.
92/// If the commit fails, it logs the error and returns it.
93///
94/// # Example
95/// ```rust
96/// use zirv_db_sqlx::{commit_transaction, start_transaction};
97///
98/// async fn perform_db_operations() -> Result<(), sqlx::Error> {
99/// let mut tx = start_transaction!();
100/// // Execute operations within the transaction...
101/// commit_transaction!(tx);
102/// Ok(())
103/// }
104/// ```
105#[macro_export]
106macro_rules! commit_transaction {
107 ($tx:expr) => {
108 match $tx.commit().await {
109 Ok(_) => (),
110 Err(e) => {
111 eprintln!("Failed to commit transaction: {:?}", e);
112 return Err(e);
113 }
114 }
115 };
116}
117
118/// Macro to rollback an active transaction.
119///
120/// This macro takes a transaction handle as an argument and rolls back the transaction.
121/// If the rollback fails, it logs the error and returns it.
122///
123/// # Example
124/// ```rust
125/// use zirv_db_sqlx::{rollback_transaction, start_transaction};
126///
127/// async fn perform_db_operations() -> Result<(), sqlx::Error> {
128/// let mut tx = start_transaction!();
129/// // Execute operations within the transaction...
130/// rollback_transaction!(tx);
131/// Ok(())
132/// }
133/// ```
134#[macro_export]
135macro_rules! rollback_transaction {
136 ($tx:expr) => {
137 match $tx.rollback().await {
138 Ok(_) => (),
139 Err(e) => {
140 eprintln!("Failed to rollback transaction: {:?}", e);
141 return Err(e);
142 }
143 }
144 };
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use sqlx::query_as;
151 use std::env;
152
153 /// Helper function to check if a required environment variable is set.
154 fn is_db_configured() -> bool {
155 // Adjust this check according to how your `read_config!` macro obtains its configuration.
156 // Here we simply check for the DATABASE_URL env variable.
157 env::var("DATABASE_URL").is_ok()
158 }
159
160 /// Test that the database pool can be initialized and retrieved.
161 #[tokio::test]
162 async fn test_init_and_get_db_pool() {
163 if !is_db_configured() {
164 eprintln!("DATABASE_URL not set. Skipping test_init_and_get_db_pool.");
165 return;
166 }
167
168 // Initialize the DB pool using the macro.
169 init_db_pool!();
170
171 // Retrieve the pool using the macro.
172 let pool = get_db_pool!();
173
174 // Execute a simple query to verify the connection.
175 let row: (i32,) = query_as("SELECT 1")
176 .fetch_one(pool)
177 .await
178 .expect("Failed to execute test query on DB pool");
179 assert_eq!(row.0, 1);
180 }
181}