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

Implement "Nest" for DerivePartialModel and From QueryResult #1716

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use sea_orm::entity::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub user_id: Option<i32> ,
pub user_id: Option<i32>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand All @@ -15,7 +15,7 @@ pub enum Relation {
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "NoAction",
on_delete = "NoAction",
on_delete = "NoAction"
)]
Users,
#[sea_orm(has_many = "super::users_saved_bills::Entity")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ pub enum Relation {
from = "Column::BillId",
to = "super::bills::Column::Id",
on_update = "Cascade",
on_delete = "Cascade",
on_delete = "Cascade"
)]
Bills,
#[sea_orm(
belongs_to = "super::users::Entity",
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "Cascade",
on_delete = "Cascade",
on_delete = "Cascade"
)]
Users,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ pub enum Relation {
from = "Column::BillId",
to = "super::bills::Column::Id",
on_update = "Cascade",
on_delete = "Cascade",
on_delete = "Cascade"
)]
Bills,
#[sea_orm(
belongs_to = "super::users::Entity",
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "Cascade",
on_delete = "Cascade",
on_delete = "Cascade"
)]
Users,
}
Expand Down
4 changes: 2 additions & 2 deletions sea-orm-codegen/src/tests_cfg/many_to_many/bills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use sea_orm::entity::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub user_id: Option<i32> ,
pub user_id: Option<i32>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand All @@ -15,7 +15,7 @@ pub enum Relation {
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "NoAction",
on_delete = "NoAction",
on_delete = "NoAction"
)]
Users,
#[sea_orm(has_many = "super::users_votes::Entity")]
Expand Down
4 changes: 2 additions & 2 deletions sea-orm-codegen/src/tests_cfg/many_to_many/users_votes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ pub enum Relation {
from = "Column::BillId",
to = "super::bills::Column::Id",
on_update = "Cascade",
on_delete = "Cascade",
on_delete = "Cascade"
)]
Bills,
#[sea_orm(
belongs_to = "super::users::Entity",
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "Cascade",
on_delete = "Cascade",
on_delete = "Cascade"
)]
Users,
}
Expand Down
4 changes: 2 additions & 2 deletions sea-orm-codegen/src/tests_cfg/many_to_many_multiple/bills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use sea_orm::entity::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub user_id: Option<i32> ,
pub user_id: Option<i32>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand All @@ -15,7 +15,7 @@ pub enum Relation {
from = "Column::UserId",
to = "super::users::Column::Id",
on_update = "NoAction",
on_delete = "NoAction",
on_delete = "NoAction"
)]
Users,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ pub struct Model {
pub user_id: i32,
#[sea_orm(primary_key, auto_increment = false)]
pub bill_id: i32,
pub user_idd: Option<i32> ,
pub bill_idd: Option<i32> ,
pub user_idd: Option<i32>,
pub bill_idd: Option<i32>,
pub vote: bool,
}

Expand All @@ -17,25 +17,25 @@ pub enum Relation {
#[sea_orm(
belongs_to = "super::bills::Entity",
from = "Column::BillIdd",
to = "super::bills::Column::Id",
to = "super::bills::Column::Id"
)]
Bills2,
#[sea_orm(
belongs_to = "super::bills::Entity",
from = "Column::BillId",
to = "super::bills::Column::Id",
to = "super::bills::Column::Id"
)]
Bills1,
#[sea_orm(
belongs_to = "super::users::Entity",
from = "Column::UserIdd",
to = "super::users::Column::Id",
to = "super::users::Column::Id"
)]
Users2,
#[sea_orm(
belongs_to = "super::users::Entity",
from = "Column::UserId",
to = "super::users::Column::Id",
to = "super::users::Column::Id"
)]
Users1,
}
Expand Down
8 changes: 2 additions & 6 deletions sea-orm-codegen/src/tests_cfg/self_referencing/bills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@ use sea_orm::entity::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub self_id: Option<i32> ,
pub self_id: Option<i32>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "Entity",
from = "Column::SelfId",
to = "Column::Id",
)]
#[sea_orm(belongs_to = "Entity", from = "Column::SelfId", to = "Column::Id")]
SelfRef,
}

Expand Down
16 changes: 4 additions & 12 deletions sea-orm-codegen/src/tests_cfg/self_referencing/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,15 @@ use sea_orm::entity::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub self_id: Option<i32> ,
pub self_idd: Option<i32> ,
pub self_id: Option<i32>,
pub self_idd: Option<i32>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "Entity",
from = "Column::SelfId",
to = "Column::Id",
)]
#[sea_orm(belongs_to = "Entity", from = "Column::SelfId", to = "Column::Id")]
SelfRef2,
#[sea_orm(
belongs_to = "Entity",
from = "Column::SelfIdd",
to = "Column::Id",
)]
#[sea_orm(belongs_to = "Entity", from = "Column::SelfIdd", to = "Column::Id")]
SelfRef1,
}

Expand Down
26 changes: 21 additions & 5 deletions sea-orm-macros/src/derives/partial_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ use syn::Meta;

use self::util::GetAsKVMeta;

use super::util::field_attr_contain_key;

#[derive(Debug)]
enum Error {
InputNotStruct,
EntityNotSpecific,
NotSupportGeneric(Span),
BothFromColAndFromExpr(Span),
FlattenNotOnly(Span),
Syn(syn::Error),
}
#[derive(Debug, PartialEq, Eq)]
Expand All @@ -29,6 +32,8 @@ enum ColumnAs {
ColAlias { col: syn::Ident, field: String },
/// from an expr
Expr { expr: syn::Expr, field_name: String },
/// flatten
Flatten { ty: syn::Type },
}

struct DerivePartialModel {
Expand Down Expand Up @@ -78,6 +83,7 @@ impl DerivePartialModel {

let mut from_col = None;
let mut from_expr = None;
let flatten = field_attr_contain_key(&field, "flatten");

for attr in field.attrs.iter() {
if !attr.path().is_ident("sea_orm") {
Expand All @@ -100,8 +106,8 @@ impl DerivePartialModel {

let field_name = field.ident.unwrap();

let col_as = match (from_col, from_expr) {
(None, None) => {
let col_as = match (from_col, from_expr, flatten) {
(None, None, false) => {
if entity.is_none() {
return Err(Error::EntityNotSpecific);
}
Expand All @@ -110,19 +116,23 @@ impl DerivePartialModel {
field_name.to_string().to_upper_camel_case()
))
}
(None, Some(expr)) => ColumnAs::Expr {
(None, Some(expr), false) => ColumnAs::Expr {
expr,
field_name: field_name.to_string(),
},
(Some(col), None) => {
(Some(col), None, false) => {
if entity.is_none() {
return Err(Error::EntityNotSpecific);
}

let field = field_name.to_string();
ColumnAs::ColAlias { col, field }
}
(Some(_), Some(_)) => return Err(Error::BothFromColAndFromExpr(field_span)),
(None, None, true) => ColumnAs::Flatten { ty: field.ty },
(Some(_), _, true) | (_, Some(_), true) => {
return Err(Error::FlattenNotOnly(field_span))
}
(Some(_), Some(_), _) => return Err(Error::BothFromColAndFromExpr(field_span)),
};
column_as_list.push(col_as);
}
Expand Down Expand Up @@ -159,6 +169,9 @@ impl DerivePartialModel {
ColumnAs::Expr { expr, field_name } => {
quote!(let #select_ident = sea_orm::SelectColumns::select_column_as(#select_ident, #expr, #field_name);)
},
ColumnAs::Flatten { ty } => {
quote!(let #select_ident = <#ty as sea_orm::PartialModelTrait>::select_cols(#select_ident);)
}
});

quote! {
Expand Down Expand Up @@ -190,6 +203,9 @@ pub fn expand_derive_partial_model(input: syn::DeriveInput) -> syn::Result<Token
Err(Error::InputNotStruct) => Ok(quote_spanned! {
ident_span => compile_error!("you can only derive `DerivePartialModel` on named struct");
}),
Err(Error::FlattenNotOnly(span)) => Ok(quote_spanned! {
span => compile_error!("you can only derive `DerivePartialModel` on named struct");
}),
Err(Error::Syn(err)) => Err(err),
}
}
Expand Down
10 changes: 7 additions & 3 deletions sea-orm-macros/src/derives/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ use quote::format_ident;
use syn::{punctuated::Punctuated, token::Comma, Field, Ident, Meta};

pub(crate) fn field_not_ignored(field: &Field) -> bool {
!field_attr_contain_key(field, "ignore")
}

pub(crate) fn field_attr_contain_key(field: &Field, key: &'static str) -> bool {
for attr in field.attrs.iter() {
if let Some(ident) = attr.path().get_ident() {
if ident != "sea_orm" {
Expand All @@ -16,15 +20,15 @@ pub(crate) fn field_not_ignored(field: &Field) -> bool {
for meta in list.iter() {
if let Meta::Path(path) = meta {
if let Some(name) = path.get_ident() {
if name == "ignore" {
return false;
if name == key {
return true;
}
}
}
}
}
}
true
false
}

pub(crate) fn format_field_ident(field: Field) -> Ident {
Expand Down
56 changes: 56 additions & 0 deletions sea-orm-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,24 @@ pub fn derive_active_enum(input: TokenStream) -> TokenStream {
/// skip_me: i32,
/// }
/// ```
///
/// Can contain other `FromQueryResult` for a complex query result
/// ```
/// use sea_orm::{entity::prelude::*, FromQueryResult};
///
/// #[derive(Debug, FromQueryResult)]
/// struct Foo {
/// bar: i64,
/// }
///
/// #[derive(Debug, FromQueryResult)]
/// struct SelectResult {
/// name: String,
/// num_of_fruits: i32,
/// #[sea_orm(flatten)]
/// foo: Foo,
/// }
/// ```
#[cfg(feature = "derive")]
#[proc_macro_derive(FromQueryResult, attributes(sea_orm))]
pub fn derive_from_query_result(input: TokenStream) -> TokenStream {
Expand Down Expand Up @@ -786,6 +804,44 @@ pub fn derive_from_json_query_result(input: TokenStream) -> TokenStream {
/// sum: i32
/// }
/// ```
///
/// Can contain orther `PartialModel` for complex col constitution
/// ```
/// use sea_orm::{entity::prelude::*, sea_query::Expr, DerivePartialModel, FromQueryResult};
///
/// #[derive(Debug, FromQueryResult, DerivePartialModel)]
/// struct SelectResult {
/// #[sea_orm(from_expr = "Expr::val(1).add(1)")]
/// sum: i32,
/// #[sea_orm(flatten)]
/// foo: Foo,
/// }
///
/// #[derive(Debug, FromQueryResult, DerivePartialModel)]
/// struct Foo {
/// #[sea_orm(from_expr = "Expr::val(12).add(2)")]
/// bar: i64,
/// }
/// ```
/// Note: the `flatten` cannot use with `from_expr` or `from_col`,
/// or is cannot compile
/// ```compile_fail
/// use sea_orm::{entity::prelude::*, sea_query::Expr, DerivePartialModel, FromQueryResult};
///
/// #[derive(Debug, FromQueryResult, DerivePartialModel)]
/// struct SelectResult {
/// #[sea_orm(from_expr = "Expr::val(1).add(1)")]
/// sum: i32,
/// #[sea_orm(flatten, from_expr = "Expr::val(11).div(5)")]
/// foo: Foo
/// }
///
/// #[derive(Debug, FromQueryResult, DerivePartialModel)]
/// struct Foo{
/// #[sea_orm(from_expr = "Expr::val(12).add(2)")]
/// bar: i64
/// }
/// ```
#[cfg(feature = "derive")]
#[proc_macro_derive(DerivePartialModel, attributes(sea_orm))]
pub fn derive_partial_model(input: TokenStream) -> TokenStream {
Expand Down
Loading
Loading