Skip to main content

d1_orm/
macros.rs

1#[macro_export]
2macro_rules! migration_info_helper {
3    (@table($name:expr)) => {
4        $crate::MigrationInfo::Table($name)
5    };
6    (@index($name:expr)) => {
7        $crate::MigrationInfo::Index($name)
8    };
9    (@column($t:expr, $c:expr)) => {
10        $crate::MigrationInfo::Column {
11            table: $t,
12            column: $c,
13        }
14    };
15    (@adhoc($info:expr)) => {
16        *$info
17    };
18}
19
20#[macro_export]
21macro_rules! sql_params {
22    ($p:ident sql) => {};
23    ($p:ident info) => {};
24    ($p:ident $field:ident [skip_primary_key]) => {
25        for u in $field
26            .iter()
27            .filter(|u| !$crate::FieldMeta::is_primary_key(*u))
28        {
29            $p.push($crate::FieldUpdate::to_value(u));
30        }
31    };
32    ($p:ident $field:ident) => {
33        $crate::ToParams::add_params($field, &mut $p);
34    };
35}
36
37#[macro_export]
38macro_rules! define_sql {
39    (
40        $enum_name:ident
41        $(
42            $( @$mtype:ident ( $($margs:tt)* ) )?
43            $name:ident $( { $($field:ident : $ftype:ty $( [ $mode:ident ] )? ),* $(,)? } )? => $sql:expr
44        ),* $(,)?
45    ) => {
46        #[derive(Clone, Debug)]
47        pub enum $enum_name<'a> {
48            $(
49                #[allow(dead_code)]
50                $name $( { $($field : $ftype),* } )?,
51            )*
52        }
53
54        impl<'a> $crate::Query for $enum_name<'a> {
55            fn build(&self) -> Result<(::std::borrow::Cow<'static, str>, Vec<$crate::DatabaseValue>), $crate::Error> {
56                match self {
57                    $(
58                        $enum_name::$name $( { $($field,)* } )? => {
59                            $( $(let _ = &$field;)* )?
60                            let sql: Result<::std::borrow::Cow<'static, str>, _> =
61                                $crate::IntoResultCow::into_result_cow($sql);
62
63                            sql.map(|sql| {
64                                #[allow(unused_mut)]
65                                let mut v = Vec::new();
66                                $(
67                                    $(
68                                        $crate::sql_params!(v $field $( [$mode] )? );
69                                    )*
70                                )?
71                                (sql, v)
72                            })
73                        },
74                    )*
75                }
76            }
77        }
78
79        impl<'a> $crate::MigrationMeta for $enum_name<'a> {
80            fn migration_info(&self) -> Option<$crate::MigrationInfo> {
81                match self {
82                    $(
83                        $enum_name::$name $( { $($field,)* } )? => {
84                            $( $(let _ = $field;)* )?
85                            None $( .or(Some($crate::migration_info_helper!(@$mtype($($margs)*)))) )?
86                        }
87                    ),*
88                }
89            }
90        }
91    };
92}
93
94#[macro_export]
95macro_rules! is_pk_helper {
96    (@pk) => {
97        true
98    };
99}
100
101#[macro_export]
102macro_rules! define_model {
103    ($(#[$struct_meta:meta])* $name:ident, $enum_name:ident, $update_enum:ident {
104        $( $(#[$field_meta:meta])* $field:ident : $ftype:ty $( [ $mode:ident ] )? ),* $(,)?
105    }) => {
106        #[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
107        $(#[$struct_meta])*
108        pub struct $name {
109            $( $(#[$field_meta])* pub $field : $ftype ),*
110        }
111
112        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
113        #[allow(non_camel_case_types, dead_code)]
114        pub enum $enum_name {
115            $( $field ),*
116        }
117
118        impl $enum_name {
119            #[allow(dead_code)]
120            pub fn as_str(&self) -> &'static str {
121                match self {
122                    $( Self::$field => stringify!($field) ),*
123                }
124            }
125        }
126
127        #[allow(non_camel_case_types, dead_code)]
128        #[derive(Debug, Clone)]
129        pub enum $update_enum {
130             $( $field($ftype) ),*
131        }
132
133        impl $crate::FieldUpdate for $update_enum {
134            fn field(&self) -> &'static str {
135                match self {
136                    $( Self::$field(_) => stringify!($field) ),*
137                }
138            }
139            fn to_value(&self) -> $crate::DatabaseValue {
140                match self {
141                    $( Self::$field(v) => v.clone().into() ),*
142                }
143            }
144        }
145
146        impl $crate::FieldMeta for $update_enum {
147            fn is_primary_key(&self) -> bool {
148                match self {
149                    $( Self::$field(_) => {
150                        false $( || $crate::is_pk_helper!(@$mode) )?
151                    } ),*
152                }
153            }
154        }
155
156        impl $crate::ToParams for $update_enum {
157            fn add_params(&self, params: &mut Vec<$crate::DatabaseValue>) {
158                match self {
159                    $( Self::$field(v) => params.push(v.clone().into()) ),*
160                }
161            }
162        }
163    };
164}