Skip to content
Open
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
269 changes: 188 additions & 81 deletions sea-orm-macros/src/derives/entity_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ pub struct EntityLoaderField {
pub via: Option<syn::LitStr>,
}

fn relation_enum_ident(relation_enum: &syn::LitStr) -> Ident {
Ident::new(&relation_enum.value(), relation_enum.span())
}

pub fn expand_entity_loader(vis: &Visibility, schema: EntityLoaderSchema) -> TokenStream {
let mut field_bools: Punctuated<_, Comma> = Punctuated::new();
let mut field_nests: Punctuated<_, Comma> = Punctuated::new();
Expand Down Expand Up @@ -60,19 +64,14 @@ pub fn expand_entity_loader(vis: &Visibility, schema: EntityLoaderSchema) -> Tok
let is_one = entity_field.is_one;
let is_self = entity_field.is_self;
let is_reverse = entity_field.is_reverse;
let is_duplicate_entity = *total_count.get(&entity_field.entity).unwrap() != 1;
let entity: TokenStream = entity_field.entity.parse().unwrap();
let entity_module: TokenStream = entity_field
.entity
.trim_end_matches("::Entity")
.parse()
.unwrap();

if !is_self && *total_count.get(&entity_field.entity).unwrap() != 1 {
// prevent impl trait for same entity twice
// self_ref is allowed
continue;
}

if !is_self {
field_bools.push(quote! {
#[doc = " Generated by sea-orm-macros"]
Expand All @@ -83,18 +82,28 @@ pub fn expand_entity_loader(vis: &Visibility, schema: EntityLoaderSchema) -> Tok
pub #field: #entity_module::EntityLoaderWith
});

with_impl.extend(quote! {
if target == sea_orm::compound::LoadTarget::TableRef(#entity.table_ref()) {
self.#field = true;
}
});
with_nest_impl.extend(quote! {
if left == sea_orm::compound::LoadTarget::TableRef(#entity.table_ref()) {
self.with.#field = true;
self.nest.#field.set(right);
return self;
}
});
if !is_duplicate_entity {
with_impl.extend(quote! {
if target == sea_orm::compound::LoadTarget::TableRef(#entity.table_ref()) {
self.#field = true;
}
});
with_nest_impl.extend(quote! {
if left == sea_orm::compound::LoadTarget::TableRef(#entity.table_ref()) {
self.with.#field = true;
self.nest.#field.set(right);
return self;
}
});
} else if let Some(relation_enum) = &entity_field.relation_enum {
with_impl.extend(quote! {
if let sea_orm::compound::LoadTarget::Relation(relation_enum) = &target {
if relation_enum == #relation_enum {
Comment thread
Huliiiiii marked this conversation as resolved.
self.#field = true;
Comment thread
Huliiiiii marked this conversation as resolved.
}
}
});
}
} else {
field_bools.push(quote! {
#[doc = " Generated by sea-orm-macros"]
Expand Down Expand Up @@ -166,96 +175,194 @@ pub fn expand_entity_loader(vis: &Visibility, schema: EntityLoaderSchema) -> Tok
}

if is_one && !is_self {
arity += 1;
if arity <= 3 {
// do not go beyond SelectThree
one_fields.push(quote!(#field));

select_impl.extend(quote! {
let select = if self.with.#field && self.nest.#field.is_empty() {
self.with.#field = false;
loaded.#field = true;
select.find_also(Entity, #entity)
} else {
select.select_also_fake(#entity)
};
});
if !is_duplicate_entity {
arity += 1;
if arity <= 3 {
// do not go beyond SelectThree
one_fields.push(quote!(#field));

select_impl.extend(quote! {
let select = if self.with.#field && self.nest.#field.is_empty() {
self.with.#field = false;
loaded.#field = true;
select.find_also(Entity, #entity)
} else {
select.select_also_fake(#entity)
};
});

assemble_one.extend(quote! {
if loaded.#field {
model.#field = #field.map(Into::into).map(Box::new).into();
}
});
}

assemble_one.extend(quote! {
if loaded.#field {
model.#field = #field.map(Into::into).map(Box::new).into();
load_one.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;
let #field = #entity_module::EntityLoader::load_nest(#field, &nest.#field, db)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
});
}
load_one_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;

load_one.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;
let #field = #entity_module::EntityLoader::load_nest(#field, &nest.#field, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
if let Some(model) = model.as_mut() {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
}
});
load_one_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
}
}
});
load_one_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;
});
} else if let Some(relation_enum) = &entity_field.relation_enum {
let relation_enum = relation_enum_ident(relation_enum);
load_one.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex_with_rel(
#entity,
sea_orm::RelationTrait::def(&Relation::#relation_enum),
db,
)#await_?;
let #field = #entity_module::EntityLoader::load_nest(#field, &nest.#field, db)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
if let Some(model) = model.as_mut() {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
}
});
load_one_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;
});
load_one_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex_with_rel(
#entity,
sea_orm::RelationTrait::def(&Relation::#relation_enum),
db,
)#await_?;

for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
if let Some(model) = model.as_mut() {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
}
}
});
} else if !is_one && !is_self {
load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;
let #field = #entity_module::EntityLoader::load_nest_nest(#field, &nest.#field, db)#await_?;
});
load_one_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex_with_rel(
#entity,
sea_orm::RelationTrait::def(&Relation::#relation_enum),
db,
)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
}
}
});
load_many_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;
});
}
} else if !is_one && !is_self {
if !is_duplicate_entity {
load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;
let #field = #entity_module::EntityLoader::load_nest_nest(#field, &nest.#field, db)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
if let Some(model) = model.as_mut() {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
}
});
load_many_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;
});
load_many_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
if let Some(model) = model.as_mut() {
model.#field = #field.into();
}
}
}
});
load_many_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;

for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
}
});
} else if entity_field.via.is_none() {
if let Some(relation_enum) = &entity_field.relation_enum {
let relation_enum = relation_enum_ident(relation_enum);
load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex_with_rel(
#entity,
sea_orm::RelationTrait::def(&Relation::#relation_enum),
db,
Comment thread
Huliiiiii marked this conversation as resolved.
)#await_?;
let #field = #entity_module::EntityLoader::load_nest_nest(#field, &nest.#field, db)#await_?;

for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
});
load_many_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex_with_rel(
#entity,
sea_orm::RelationTrait::def(&Relation::#relation_enum),
db,
)#await_?;

for (model, #field) in models.iter_mut().zip(#field) {
if let Some(model) = model.as_mut() {
model.#field = #field.into();
}
}
}
});
load_many_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex_with_rel(
#entity,
sea_orm::RelationTrait::def(&Relation::#relation_enum),
db,
)#await_?;

for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
}
});
}
});
}
} else if is_one && is_self {
if let Some(relation_enum) = &entity_field.relation_enum {
let relation_enum = Ident::new(&relation_enum.value(), relation_enum.span());
let relation_enum = relation_enum_ident(relation_enum);
load_one.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_ex(#entity, Relation::#relation_enum, db)#await_?;
Expand All @@ -268,7 +375,7 @@ pub fn expand_entity_loader(vis: &Visibility, schema: EntityLoaderSchema) -> Tok
}
} else if !is_one && is_self {
if let Some(relation_enum) = &entity_field.relation_enum {
let relation_enum = Ident::new(&relation_enum.value(), relation_enum.span());
let relation_enum = relation_enum_ident(relation_enum);
load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_many_ex(#entity, Relation::#relation_enum, db)#await_?;
Expand Down
Loading
Loading