Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for field specific decode and encode #3678

Open
jakoritarleite opened this issue Jan 10, 2025 · 0 comments
Open

Support for field specific decode and encode #3678

jakoritarleite opened this issue Jan 10, 2025 · 0 comments
Labels
enhancement New feature or request

Comments

@jakoritarleite
Copy link

jakoritarleite commented Jan 10, 2025

I have found these related issues/pull requests

Could not find any related issue nor pull request.

Description

It would be nice specify that I want a specific field of my struct to be encoded or decoded using a different implementation of the original Decode and Encode of the specific type, something like serde serialize_with and deserialize_with.

Prefered solution

What I imagine is that sqlx would provide a field attribute called decode_with and encode_with (just like serde) which expects a function name, and this function name would have the implementation inside for whatever we want.

encode_with would be callable with

fn<'q, O, DB>(&T, &mut DB::ArgumentBuffer<'q>) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError>
where
    DB: Database,
    // This is the output type we want to encode to, say for example String, i32, bool, etc.
    O: Encode<'q, DB>;

and decode_with

fn<'r, I, DB>(DB::ValueRef<'r>) -> Result<Self, sqlx::error::BoxDynError>
where
    DB: Database,
    // This is the input type we want to decode from.
    I: Decode<'r, DB>;

and the implementation may look something like this:

#[derive(sqlx::Type)]
#[repr(i8)]
pub enum Status {
    Processed = 1,
    Processing = 2,
    Failed = 3,
}

impl Display for Status { ... }

#[derive(sqlx::FromRow)]
pub struct Data {
    pub id: Uuid,
    #[sqlx(encode_with = "encode_as_string", decode_with = "decode_as_string")]
    pub status: Status,
    // In this case, would use the `sqlx::Type` derived impls.
    pub status_code: Status,
}

fn encode_as_string<'q, DB>(
    value: &StatusCode,
    buf: &mut DB::ArgumentBuffer<'q>,
) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError>
where
    DB: sqlx::database::Database,
    String: sqlx::Encode<'q, DB>,
{
    <String as sqlx::Encode<'q, DB>>::encode(value.to_string(), buf)
}

fn decode_as_string<'r, DB>(value: <DB as Database>::ValueRef<'r>) -> Result<Status, sqlx::error::BoxDynError>
where
    DB: Database,
    String: Decode<'r, DB> 
{
    let value = <String as Decode<'r, DB>>::decode(value)?;
    
    /// Match each enum as String.
    match value { ... }
}

Is this a breaking change? Why or why not?

It's not breaking change, it would only add another proc macro attribute that supports this.

@jakoritarleite jakoritarleite added the enhancement New feature or request label Jan 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant