-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Extend derive(FromRow) with additional features/attributes #156
Labels
E-medium
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
Comments
mehcode
added
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
labels
Mar 26, 2020
8 tasks
I wanted same feature to synchronize implementation // derive_crate/src/lib.rs
use darling::{ast, Error, FromDeriveInput};
use itertools::Itertools;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
mod args;
#[proc_macro_derive(ExtendedFromRow, attributes(extended))]
pub fn extended_from_row_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let ast = match args::ExtendedFromRow::from_derive_input(&ast) {
Ok(ast) => ast,
Err(err) => return TokenStream::from(err.write_errors()),
};
let ident = ast.ident;
let fields = match ast.data {
ast::Data::Struct(field) => field,
_ => {
return TokenStream::from(
Error::unsupported_format("Input should be a struct").write_errors(),
)
}
};
let fields = fields
.into_iter()
.map(|field| {
let id = field.ident.unwrap();
let column = field
.rename
.or_else(|| Some(id.to_string().trim_start_matches("r#").to_owned()))
.unwrap();
let ty = field.ty;
match field.flatten.unwrap_or(false) {
true => quote! {
#id: #ty::from_row(row)?
},
false => quote! {
#id: row.try_get(#column)?
},
}
})
.collect_vec();
let extended = quote! {
impl<'a> sqlx::FromRow<'a, sqlx::postgres::PgRow> for #ident {
fn from_row(row: &'a sqlx::postgres::PgRow) -> Result<Self, sqlx::Error> {
Ok(Self{#( #fields ),*})
}
}
};
extended.into()
} // derive_crate/src/args.rs
use darling::{ast::Data, util::Ignored, FromDeriveInput, FromField};
use proc_macro2::Ident;
use syn::{Attribute, Generics, Type};
#[derive(FromDeriveInput)]
#[darling(attributes(extended), forward_attrs(doc))]
pub struct ExtendedFromRow {
pub ident: Ident,
pub generics: Generics,
pub attrs: Vec<Attribute>,
pub data: Data<Ignored, ExtendedRowField>,
}
#[derive(FromField)]
#[darling(attributes(extended), forward_attrs(doc))]
pub struct ExtendedRowField {
pub ident: Option<Ident>,
pub ty: Type,
#[darling(default)]
pub flatten: Option<bool>,
#[darling(default)]
pub rename: Option<String>,
} Then use the derive like this #[derive(ExtendedFromRow)]
struct FooBar {
pub foo: String,
#[extended(flatten)]
pub bar: Bar,
}
#[derive(FromRow)]
struct Bar {
pub bar: String
} Then we can use the struct for this operation let foo_bars: Vec<FooBar> = sqlx::query_as("SELECT * FROM foo_bar").fetch_all(&conn).await?; the other solution i merge them in tuple struct using macro_rule // example
#[derive(FromRow)]
struct Foo {
pub foo: String
}
#[derive(FromRow)]
struct Bar {
pub bar: String
}
merge_object!(pub struct FooBar, Foo, Bar);
#[macro_export]
macro_rules! merge_model {
($vis:vis struct $model_name:ident, $($member:ident),*) => {
#[derive(Debug, Clone, Deserialize, Serialize, MergedObject)]
$vis struct $model_name($( pub $member ),*);
impl<'a> sqlx::FromRow<'a, sqlx::postgres::PgRow> for $model_name {
fn from_row(row: &'a sqlx::postgres::PgRow) -> Result<Self, sqlx::Error> {
Ok(Self($( $member::from_row(row)? ),*))
}
}
};
} I wish the feature available soon |
just for tracking purposes, item 4 was implemented in #1959 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
E-medium
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
Handle
#[sqlx(rename = "new_name")]
on a struct fieldSupport the derive on a tuple struct and use by ordinal retrieval from the row
Handle
#[sqlx(ordinal = 3)]
to use ordinal retrieval from the row (row.get(3)
)Handle a field that is
impl FromRow
. A parallel fromserde_json
would perhaps make this#[sqlx(flatten)]
.The text was updated successfully, but these errors were encountered: