Macro exemplar::record

source ·
macro_rules! record {
    ($(#[$struct_doc:meta])* Name => $name:ident, $($(#[$field_doc:meta])* $fname:ident => $ftype:ty),* $(,)?) => { ... };
    ($($(#[$field_doc:meta])* $fname:ident => $ftype:ty),* $(,)?) => { ... };
}
Expand description

Generate an “anonymous” record struct that implements from_row.

This is best used for deserializing rows from an ad-hoc query in a strongly typed manner.

Note that the generated struct does not implement Model, as it can’t be associated with any specific table. This means that tools like #[bind]/#[extr] and the like are not available for records.

However, TryFrom<Row> is still implemented, making records usable in some generic contexts.

Example

The example assumes this database schema:

CREATE TABLE people (name, age, alive); 
record! {
    // The provided field name is assumed to map directly to a column in a query's output.
    name => String,
    age  => u16,
}
 
record! {
    // By default, the generated struct is called `Record.`
    // This can be overridden with the `Name` parameter, should the need arise.
    Name => Age,
    age  => u16,
}
 
let mut get_people = conn.prepare("SELECT name, age FROM people")?;
let mut get_ages = conn.prepare("SELECT age FROM people")?;
 
get_people
    .query_and_then([], Record::from_row)?
    .map(|record| ...);
 
get_ages
    .query_and_then([], Age::from_row)?
    .map(|age| ...);

Notes

Doc comments (and other attributes) are supported:

record! {
    /// A person's name.
    name => String,
    /// A person's age.
    age  => u16,
}

Additionally, you can apply type-level attributes like derives on the Name argument.

record! {
    #[derive(Debug, Clone)]
    Name => Age,
    age  => u16,
}

(record! does not apply any derives automatically.)

This does not work without the Name argument, due to macro limitations - Rust can’t disambiguate between “attributes for the struct” and “attributes for the field.”

record! {
    #[derive(Debug, Clone)]
    /// A person's name.
    name => String,
    /// A person's age.
    age  => u16,
}