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}