Skip to main content

uts_sql/
macros.rs

1/// A helper macro to define a text-based enum that can be stored in a SQLite database.
2/// The enum must implement `Into<&'static str>` and `FromStr`.
3#[macro_export]
4macro_rules! define_text_enum {
5    ($ty:ty) => {
6        impl ::sqlx::Type<sqlx::Sqlite> for $ty {
7            fn type_info() -> ::sqlx::sqlite::SqliteTypeInfo {
8                <String as ::sqlx::Type<::sqlx::Sqlite>>::type_info()
9            }
10
11            fn compatible(ty: &::sqlx::sqlite::SqliteTypeInfo) -> bool {
12                ::sqlx::TypeInfo::name(ty) == "TEXT"
13            }
14        }
15
16        impl<'q> ::sqlx::Encode<'q, ::sqlx::Sqlite> for $ty {
17            fn encode_by_ref(
18                &self,
19                args: &mut Vec<::sqlx::sqlite::SqliteArgumentValue<'q>>,
20            ) -> Result<::sqlx::encode::IsNull, ::sqlx::error::BoxDynError> {
21                let s: &'static str = self.into();
22                args.push(::sqlx::sqlite::SqliteArgumentValue::Text(s.into()));
23
24                Ok(::sqlx::encode::IsNull::No)
25            }
26        }
27
28        impl<'r> ::sqlx::Decode<'r, sqlx::Sqlite> for $ty {
29            fn decode(
30                value: ::sqlx::sqlite::SqliteValueRef<'r>,
31            ) -> Result<Self, ::sqlx::error::BoxDynError> {
32                let text = <&str as ::sqlx::Decode<::sqlx::Sqlite>>::decode(value)?;
33                ::core::str::FromStr::from_str(text)
34                    .map_err(|e| Box::new(e) as ::sqlx::error::BoxDynError)
35            }
36        }
37    };
38}
39
40/// A helper macro to define a `migrate` function that runs database migrations from a specified directory.
41#[macro_export]
42macro_rules! migrator {
43    ($dir:literal) => {
44        /// Run database migrations. This should be run at the start of the application to ensure the
45        /// database schema is up to date.
46        #[inline]
47        pub async fn migrate<'a, A>(migrator: A) -> Result<(), ::sqlx::migrate::MigrateError>
48        where
49            A: ::sqlx::Acquire<'a>,
50            <A::Connection as ::core::ops::Deref>::Target: ::sqlx::migrate::Migrate,
51        {
52            ::sqlx::migrate!($dir).run(migrator).await
53        }
54    };
55    () => {
56        migrator!("./migrations");
57    };
58}