real_time_sqlx/
macros.rs

1//! Helper macros to automatically generate static dispatcher code between models.
2
3pub extern crate paste;
4
5/// Macro that generates the static rows serialization dispatcher function,
6/// that given sqlite rows, serializes them to the appropriate model based on the table name.
7///
8/// Example:
9/// ```ignore
10/// // Generate the function
11/// serialize_rows_static!(sqlite, ("todos", Todo), ("users", User));
12///
13/// // Use it to serialize `QueryData<Row>` to JSON, with a table name.
14/// let serialized: serde_json::Value = serialize_rows_static(&rows, "todos");
15/// ```
16#[macro_export]
17macro_rules! serialize_rows_static {
18    ($db_type:ident, $(($table_name:literal, $struct:ty)),+ $(,)?) => {
19        fn serialize_rows_static(data: &$crate::queries::serialize::QueryData<$crate::database_row!($db_type)>, table: &str) -> serde_json::Value {
20            match table {
21                $(
22                    $table_name => $crate::database::serialize_rows::<$struct, $crate::database_row!($db_type)>(data),
23                )+
24                _ => panic!("Table not found"),
25            }
26        }
27    };
28}
29
30/// Macro that generates a static operation executor and serializer function,
31/// that given a granular operation, executes it, parses the result into the data structure
32/// corresponding to the table name, and serializes it to JSON. This is useful for simple operation
33/// processing, without real-time updates.
34///
35/// Example:
36/// ```ignore
37/// // Generate the function`
38/// granular_operations!(sqlite, ("todos", Todo), ("users", User));
39///
40/// // Use it to execute a granular operation and serialize the result to JSON.
41/// let serialized: serde_json::Value = granular_operation_static(operation, &pool).await;
42/// ```
43#[macro_export]
44macro_rules! granular_operations {
45    ($db_type:ident, $(($table_name:literal, $struct:ty)),+ $(,)?) => {
46        async fn granular_operation_static(
47            operation: $crate::operations::serialize::GranularOperation,
48            pool: &$crate::database_pool!($db_type),
49        ) -> serde_json::Value {
50            match operation.get_table() {
51                $(
52                    $table_name => {
53                        // Dynamically invoke the correct database function based on $db_type
54                        let result: Option<$crate::operations::serialize::OperationNotification<$struct>> =
55                            $crate::granular_operation_fn!($db_type)(operation, pool).await;
56                        serde_json::to_value(result).unwrap()
57                    }
58                )+
59                _ => panic!("Table not found"),
60            }
61        }
62    };
63}
64
65// ************************************************************************* //
66//        HELPER MACROS - RESOLVE DATABASE SPECIFIC FUNCTIONS AND TYPES      //
67// ************************************************************************* //
68
69/// Returns the appropriate database pool type based on the database type.
70#[macro_export]
71macro_rules! database_pool {
72  (sqlite) => {
73    sqlx::Pool<sqlx::Sqlite>
74  };
75  (mysql) => {
76    sqlx::Pool<sqlx::MySql>
77  };
78  (postgresql) => {
79    sqlx::Pool<sqlx::Postgres>
80  };
81}
82
83/// Returns the appropriate database row type based on the database type.
84#[macro_export]
85macro_rules! database_row {
86    (sqlite) => {
87        sqlx::sqlite::SqliteRow
88    };
89    (mysql) => {
90        sqlx::mysql::MySqlRow
91    };
92    (postgresql) => {
93        sqlx::postgres::PgRow
94    };
95}
96
97/// Returns the appropriate granular operation processing function depending on the database type.
98#[macro_export]
99macro_rules! granular_operation_fn {
100    (sqlite) => {
101        $crate::database::sqlite::granular_operation_sqlite
102    };
103    (mysql) => {
104        $crate::database::mysql::granular_operation_mysql
105    };
106    (postgresql) => {
107        $crate::database::postgresql::granular_operation_postgresql
108    };
109}
110
111/// Returns the appropriate database query fetching function depending on the database type.
112#[macro_export]
113macro_rules! fetch_query_fn {
114    (sqlite) => {
115        $crate::database::sqlite::fetch_sqlite_query
116    };
117    (mysql) => {
118        $crate::database::mysql::fetch_mysql_query
119    };
120    (postgresql) => {
121        $crate::database::postgresql::fetch_postgresql_query
122    };
123}