move sqlx impls to reusable macro

This commit is contained in:
Brandon Thomas committed 2023-01-11 00:33:39 -05:00
1 parent cb1e092ccd
commit a34aedc375
3 files changed
+46 -40

No files matched your search

+1 -1
View File
@@ -37,7 +37,7 @@ pub enum Visibility {
}
impl_enum_display_and_debug_for_to_str!(Visibility);
impl_enum_display_and_debug_using_to_str!(Visibility);
// For reference, here's what the serde implementation might be if manually written.
// This may be useful for designing composite types in the future:
@@ -1,12 +1,5 @@
use serde::Deserialize;
use serde::Serialize;
use sqlx::Decode;
use sqlx::Encode;
use sqlx::Type;
use sqlx_core::database::HasArguments;
use sqlx_core::encode::IsNull;
use sqlx_core::error::BoxDynError;
use sqlx_core::mysql::{MySql, MySqlTypeInfo, MySqlValueRef};
#[cfg(test)]
use strum::EnumCount;
@@ -26,37 +19,8 @@ pub enum MediaUploadType {
Video,
}
// This overt approach is being taken because of the following error:
// `MySqlDatabaseError { code: Some("HY000"), number: 1210, message: "Incorrect arguments to mysqld_stmt_execute" }`
// Basically, sqlx can't turn our enum into a VARCHAR when using #[derive(sqlx::Type)].
// We further lose the ability to `#[sqlx(rename_all="lowercase")]`, etc., so our encoder/decoder
// need to set the rules.
// Solution adapted from https://github.com/launchbadge/sqlx/discussions/1502
impl Type<MySql> for MediaUploadType {
fn type_info() -> MySqlTypeInfo {
String::type_info()
}
}
impl<'q> Encode<'q, MySql> for MediaUploadType {
fn encode_by_ref(&self, buf: &mut <MySql as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
// NB: In the absence of `#[derive(sqlx::Type)]` and `#sqlx(rename_all="lowercase")]`,
// this controls the casing of the variants when sent to MySQL.
self.to_str().encode_by_ref(buf)
}
}
impl<'r> Decode<'r, MySql> for MediaUploadType {
fn decode(
value: MySqlValueRef<'r>,
) -> Result<Self, BoxDynError> {
let string = String::decode(value)?;
let value = MediaUploadType::from_str(&string)?;
Ok(value)
}
}
impl_enum_display_and_debug_for_to_str!(MediaUploadType);
impl_enum_display_and_debug_using_to_str!(MediaUploadType);
impl_enum_sqlx_coders!(MediaUploadType);
/// NB: Legacy API for older code.
impl MediaUploadType {
+43 -1
View File
@@ -1,7 +1,7 @@
/// Implement `Display` and `Debug` for enums that have a `.to_str()` method.
/// This ensures that the casing follows whatever `.to_str()` specifies.
macro_rules! impl_enum_display_and_debug_for_to_str {
macro_rules! impl_enum_display_and_debug_using_to_str {
($t:ident) => {
// Debug trait.
@@ -42,3 +42,45 @@ macro_rules! impl_enum_display_and_debug_for_to_str {
}
}
/// This overt approach is being taken because of the following error:
///
/// `MySqlDatabaseError { code: Some("HY000"), number: 1210, message: "Incorrect arguments to mysqld_stmt_execute" }`
///
/// Basically, sqlx can't turn our enum into a VARCHAR when using #[derive(sqlx::Type)].
/// Unfortunately, by not using this, we also lose the ability to `#[sqlx(rename_all="lowercase")]`, etc.,
/// so our encoder/decoder need to set the rules.
///
/// Solution adapted from https://github.com/launchbadge/sqlx/discussions/1502
macro_rules! impl_enum_sqlx_coders {
($t:ident) => {
impl sqlx::Type<sqlx_core::mysql::MySql> for $t {
fn type_info() -> sqlx_core::mysql::MySqlTypeInfo {
String::type_info()
}
}
impl<'q> sqlx::Encode<'q, sqlx_core::mysql::MySql> for $t {
fn encode_by_ref(
&self,
buf: &mut <sqlx_core::mysql::MySql as sqlx_core::database::HasArguments<'q>>::ArgumentBuffer
) -> sqlx_core::encode::IsNull {
// NB: In the absence of `#[derive(sqlx::Type)]` and `#sqlx(rename_all="lowercase")]`,
// this controls the casing of the variants when sent to MySQL.
self.to_str().encode_by_ref(buf)
}
}
impl<'r> sqlx::Decode<'r, sqlx_core::mysql::MySql> for $t {
fn decode(
value: sqlx_core::mysql::MySqlValueRef<'r>,
) -> Result<Self, sqlx_core::error::BoxDynError> {
let string = String::decode(value)?;
let value = $t::from_str(&string)?;
Ok(value)
}
}
}
}