FromRow

Derive Macro FromRow 

Source
#[derive(FromRow)]
{
    // Attributes available to this derive:
    #[sqlx_with]
}
Expand description

Derive sqlx::FromRow specific to the given database.

The original derive macro of sqlx::FromRow is database-agnostic but too generic to define custom decoder for specific columns. For example, sqlx::FromRow cannot support custom decoder like below.

#[derive(sqlx::FromRow)]
struct Row {
    #[sqlx(decode = "split_x")]
    x: (i64, i64),
}

fn split_x<'r, R>(index: &'r str, row: &'r R) -> sqlx::Result<(i64, i64)>
where
    R: sqlx::Row,
    &'r str: sqlx::ColumnIndex<R>,
    i64: sqlx::Type<R::Database> + sqlx::Decode<'r, R::Database>,
{
    let n: i64 = row.try_get(index)?;
    Ok((n, n + 2))
}

The reason is sqlx::FromRow cannot add i64: sqlx::Type<R::Database> + sqlx::Decode<'r, R::Database> to the derived implementation since it cannot see row.try_get() usage from the struct definition.

sqlx-derive-with resolves the problem by specifying database.

§Usage

Basic usage is similar to sqlx::FromRow.

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Row {
    x: i64,
    y: String,
}

You have to specify db.

#[derive(sqlx_derive_with::FromRow)]
struct Row {
    x: i64,
    y: String,
}

You cannot use sqlx-derive-with to tuple structs. Use the original sqlx::FromRow instead.

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Row(i64, String);

§Container attributes

§rename_all

Specify column name conversion.

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite", rename_all = "camelCase")]
struct Row {
    foo_bar: i64,   // deserialized from column "fooBar"
}

§Field attributes

§rename

Configure column name explicitly. rename takes precedence over rename_all.

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Row {
    #[sqlx_with(rename = "z")]
    x: i64, // deserialized from column "z"
    y: String,  // deserialized from column "y"
}

§default

Use Default::default() value when the column doesn’t exist..

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Row {
    #[sqlx_with(default)]
    x: i64, // i64::default() value is set when column "x" doesn't exist.
    y: String,
}

§flatten

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Row {
    x: i64,
    #[sqlx_with(flatten)]
    y: Y,
}
#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Y {
    z: i64,
    w: i64,
}

§decode

Configure custom decode function to specific columns.

#[derive(sqlx_derive_with::FromRow)]
#[sqlx_with(db = "sqlx::Sqlite")]
struct Row {
    #[sqlx_with(decode = "split_x")]
    x: (i64, i64),
    y: String,
}

fn split_x(index: &str, row: &sqlx::sqlite::SqliteRow) -> sqlx::Result<(i64, i64)> {
    use sqlx::Row as _;
    let n: i64 = row.try_get(index)?;
    Ok((n, n + 2))
}