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}