use proc_macro2::TokenStream;
use quote::quote;
use std::collections::{HashMap, HashSet};
use syn::{Ident, TypePath, Visibility, punctuated::Punctuated, token::Comma};
#[derive(Default)]
pub struct EntityLoaderSchema {
pub fields: Vec<EntityLoaderField>,
}
pub enum EntityLoaderFieldKind {
HasOne,
HasOneSelf,
HasMany,
HasManySelf,
ManyToMany,
ManyToManySelf {
junction_module: Ident,
reverse: bool,
},
}
pub struct EntityLoaderField {
pub field: Ident,
pub entity: TypePath,
pub relation_enum: Option<syn::LitStr>,
pub kind: EntityLoaderFieldKind,
}
#[derive(Default)]
struct EntityLoaderOutput {
loader_with_fields: Punctuated<TokenStream, Comma>,
loader_nest_fields: Punctuated<TokenStream, Comma>,
select_tuple_fields: Punctuated<TokenStream, Comma>,
loader_with_set_impl: TokenStream,
loader_with_2_impl: TokenStream,
fetch_select_impl: TokenStream,
assemble_one: TokenStream,
load_one: TokenStream,
load_many: TokenStream,
load_one_nest: TokenStream,
load_many_nest: TokenStream,
load_one_nest_nest: TokenStream,
load_many_nest_nest: TokenStream,
with_param_impls: TokenStream,
}
impl EntityLoaderField {
fn expand_loader_with_field_into(&self, output: &mut EntityLoaderOutput) {
let field = &self.field;
output.loader_with_fields.push(quote! {
#[doc = " Generated by sea-orm-macros"]
pub #field: bool
});
}
fn expand_loader_nest_field_into(&self, output: &mut EntityLoaderOutput) {
let field = &self.field;
let nest_type = match &self.kind {
EntityLoaderFieldKind::HasOne
| EntityLoaderFieldKind::HasMany
| EntityLoaderFieldKind::ManyToMany => {
let mut entity_module = self.entity.path.clone();
entity_module.segments.pop();
entity_module
.segments
.push(syn::parse_quote!(EntityLoaderWith));
quote!(#entity_module)
}
EntityLoaderFieldKind::HasOneSelf
| EntityLoaderFieldKind::HasManySelf
| EntityLoaderFieldKind::ManyToManySelf { .. } => quote!(EntityLoaderWith),
};
output.loader_nest_fields.push(quote! {
#[doc = " Generated by sea-orm-macros"]
pub #field: #nest_type
});
}
fn expand_relation_tuple_with_param_into(&self, output: &mut EntityLoaderOutput) {
let mut entity_module = self.entity.path.clone();
entity_module.segments.pop();
let mut related_entity = entity_module.clone();
related_entity.segments.push(syn::parse_quote!(Entity));
let mut related_relation = entity_module;
related_relation.segments.push(syn::parse_quote!(Relation));
output.with_param_impls.extend(quote! {
impl EntityLoaderWithParam for (Relation, #related_entity) {
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(
sea_orm::compound::LoadTarget::Relation(sea_orm::RelationTrait::name(&self.0)),
Some(sea_orm::compound::LoadTarget::TableRef(self.1.table_ref())),
)
}
}
impl EntityLoaderWithParam for (Relation, #related_relation) {
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(
sea_orm::compound::LoadTarget::Relation(sea_orm::RelationTrait::name(&self.0)),
Some(sea_orm::compound::LoadTarget::Relation(sea_orm::RelationTrait::name(&self.1))),
)
}
}
});
}
fn expand_many_to_many_self_with_param_into(
&self,
output: &mut EntityLoaderOutput,
junction_module: &Ident,
reverse: bool,
) {
let target_type = if !reverse {
Ident::new("TableRef", junction_module.span())
} else {
Ident::new("TableRefRev", junction_module.span())
};
let target_entity = if !reverse {
quote!(super::#junction_module::Entity)
} else {
quote!(super::#junction_module::EntityReverse)
};
output.with_param_impls.extend(quote! {
impl EntityLoaderWithParam for #target_entity {
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(sea_orm::compound::LoadTarget::#target_type(super::#junction_module::Entity.table_ref()), None)
}
}
impl<S> EntityLoaderWithParam for (#target_entity, S)
where
S: EntityTrait,
Entity: Related<S>,
{
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(
sea_orm::compound::LoadTarget::#target_type(super::#junction_module::Entity.table_ref()),
Some(sea_orm::compound::LoadTarget::TableRef(self.1.table_ref())),
)
}
}
});
}
fn expand_loader_with_set_impl_into(
&self,
output: &mut EntityLoaderOutput,
duplicate_entity: bool,
) {
let field = &self.field;
let entity = &self.entity;
match &self.kind {
EntityLoaderFieldKind::HasOne
| EntityLoaderFieldKind::HasMany
| EntityLoaderFieldKind::ManyToMany => {
if !duplicate_entity {
output.loader_with_set_impl.extend(quote! {
if target == sea_orm::compound::LoadTarget::TableRef(#entity.table_ref()) {
self.#field = true;
}
});
} else if let Some(relation_enum) = &self.relation_enum {
output.loader_with_set_impl.extend(quote! {
if let sea_orm::compound::LoadTarget::Relation(relation_enum) = &target {
if relation_enum == #relation_enum {
self.#field = true;
}
}
});
}
}
EntityLoaderFieldKind::HasOneSelf
| EntityLoaderFieldKind::HasManySelf
| EntityLoaderFieldKind::ManyToManySelf { .. } => {
if let Some(relation_enum) = &self.relation_enum {
output.loader_with_set_impl.extend(quote! {
if let sea_orm::compound::LoadTarget::Relation(relation_enum) = &target {
if relation_enum == #relation_enum {
self.#field = true;
}
}
});
}
if let EntityLoaderFieldKind::ManyToManySelf {
junction_module,
reverse,
} = &self.kind
{
let target_type = if !reverse {
Ident::new("TableRef", junction_module.span())
} else {
Ident::new("TableRefRev", junction_module.span())
};
output.loader_with_set_impl.extend(quote! {
if target == sea_orm::compound::LoadTarget::#target_type(super::#junction_module::Entity.table_ref()) {
self.#field = true;
}
});
}
}
}
}
fn expand_loader_with_2_impl_into(
&self,
output: &mut EntityLoaderOutput,
duplicate_entity: bool,
) {
let field = &self.field;
let entity = &self.entity;
match &self.kind {
EntityLoaderFieldKind::HasOne
| EntityLoaderFieldKind::HasMany
| EntityLoaderFieldKind::ManyToMany => {
if !duplicate_entity {
output.loader_with_2_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) = &self.relation_enum {
output.loader_with_2_impl.extend(quote! {
if let sea_orm::compound::LoadTarget::Relation(relation_enum) = &left {
if relation_enum == #relation_enum {
self.with.#field = true;
self.nest.#field.set(right);
return self;
}
}
});
}
}
EntityLoaderFieldKind::HasOneSelf | EntityLoaderFieldKind::HasManySelf => {}
EntityLoaderFieldKind::ManyToManySelf {
junction_module,
reverse,
} => {
let target_type = if !reverse {
Ident::new("TableRef", junction_module.span())
} else {
Ident::new("TableRefRev", junction_module.span())
};
output.loader_with_2_impl.extend(quote! {
if left == sea_orm::compound::LoadTarget::#target_type(super::#junction_module::Entity.table_ref()) {
self.with.#field = true;
self.nest.#field.set(right);
return self;
}
});
}
}
}
fn expand_select_one_into(&self, output: &mut EntityLoaderOutput) {
let field = &self.field;
let entity = &self.entity;
output.select_tuple_fields.push(quote!(#field));
output.fetch_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)
};
});
output.assemble_one.extend(quote! {
if loaded.#field {
model.#field = #field.map(Into::into).map(Box::new).into();
}
});
}
fn expand_load_one_into(&self, output: &mut EntityLoaderOutput) {
let field = &self.field;
let entity = &self.entity;
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
let mut entity_module = self.entity.path.clone();
entity_module.segments.pop();
entity_module.segments.push(syn::parse_quote!(EntityLoader));
output.load_one.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_ex(#entity, db)#await_?;
let #field = <#entity_module>::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();
}
}
});
output.load_one_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) {
if let Some(model) = model.as_mut() {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
}
});
output.load_one_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_one_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.map(Into::into).map(Box::new).into();
}
}
}
});
}
fn expand_load_one_with_rel_into(
&self,
output: &mut EntityLoaderOutput,
relation_enum: &syn::LitStr,
) {
let field = &self.field;
let entity = &self.entity;
let relation_enum = Ident::new(&relation_enum.value(), relation_enum.span());
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
let mut entity_module = self.entity.path.clone();
entity_module.segments.pop();
entity_module.segments.push(syn::parse_quote!(EntityLoader));
output.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>::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();
}
}
});
output.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 (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();
}
}
}
});
output.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 (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();
}
}
}
});
}
fn expand_load_many_into(&self, output: &mut EntityLoaderOutput) {
let field = &self.field;
let entity = &self.entity;
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
let mut entity_module = self.entity.path.clone();
entity_module.segments.pop();
entity_module.segments.push(syn::parse_quote!(EntityLoader));
output.load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_many_ex(#entity, db)#await_?;
let #field = <#entity_module>::load_nest_nest(#field, &nest.#field, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
});
output.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();
}
}
}
});
output.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();
}
}
}
});
}
fn expand_load_many_with_rel_into(
&self,
output: &mut EntityLoaderOutput,
relation_enum: &syn::LitStr,
) {
let field = &self.field;
let entity = &self.entity;
let relation_enum = Ident::new(&relation_enum.value(), relation_enum.span());
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
let mut entity_module = self.entity.path.clone();
entity_module.segments.pop();
entity_module.segments.push(syn::parse_quote!(EntityLoader));
output.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,
)#await_?;
let #field = <#entity_module>::load_nest_nest(#field, &nest.#field, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
});
output.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();
}
}
}
});
output.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();
}
}
}
});
}
fn expand_load_one_self_into(
&self,
output: &mut EntityLoaderOutput,
relation_enum: &syn::LitStr,
) {
let field = &self.field;
let entity = &self.entity;
let relation_enum = Ident::new(&relation_enum.value(), relation_enum.span());
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
output.load_one.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_ex(#entity, Relation::#relation_enum, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.map(Into::into).map(Box::new).into();
}
}
});
}
fn expand_load_many_self_into(
&self,
output: &mut EntityLoaderOutput,
relation_enum: &syn::LitStr,
) {
let field = &self.field;
let entity = &self.entity;
let relation_enum = Ident::new(&relation_enum.value(), relation_enum.span());
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
output.load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_many_ex(#entity, Relation::#relation_enum, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
});
}
fn expand_load_many_to_many_self_into(
&self,
output: &mut EntityLoaderOutput,
junction_module: &Ident,
reverse: bool,
) {
let field = &self.field;
let await_ = if cfg!(feature = "async") {
quote!(.await)
} else {
quote!()
};
output.load_many.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_via_ex(super::#junction_module::Entity, #reverse, db)#await_?;
let #field = EntityLoader::load_nest_nest(#field, &nest.#field, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
});
output.load_many_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_via_ex(super::#junction_module::Entity, #reverse, db)#await_?;
for (model, #field) in models.iter_mut().zip(#field) {
if let Some(model) = model.as_mut() {
model.#field = #field.into();
}
}
}
});
output.load_many_nest_nest.extend(quote! {
if with.#field {
let #field = models.as_slice().load_self_via_ex(super::#junction_module::Entity, #reverse, db)#await_?;
for (models, #field) in models.iter_mut().zip(#field) {
for (model, #field) in models.iter_mut().zip(#field) {
model.#field = #field.into();
}
}
}
});
}
fn expand_load_into(&self, output: &mut EntityLoaderOutput, duplicate_entity: bool) {
match &self.kind {
EntityLoaderFieldKind::HasOne if !duplicate_entity => {
self.expand_load_one_into(output);
}
EntityLoaderFieldKind::HasOne => {
if let Some(relation_enum) = &self.relation_enum {
self.expand_load_one_with_rel_into(output, relation_enum);
}
}
EntityLoaderFieldKind::HasMany | EntityLoaderFieldKind::ManyToMany
if !duplicate_entity =>
{
self.expand_load_many_into(output);
}
EntityLoaderFieldKind::HasMany => {
if let Some(relation_enum) = &self.relation_enum {
self.expand_load_many_with_rel_into(output, relation_enum);
}
}
EntityLoaderFieldKind::ManyToMany => {}
EntityLoaderFieldKind::HasOneSelf => {
if let Some(relation_enum) = &self.relation_enum {
self.expand_load_one_self_into(output, relation_enum);
}
}
EntityLoaderFieldKind::HasManySelf => {
if let Some(relation_enum) = &self.relation_enum {
self.expand_load_many_self_into(output, relation_enum);
}
}
EntityLoaderFieldKind::ManyToManySelf {
junction_module,
reverse,
} => {
if let Some(relation_enum) = &self.relation_enum {
self.expand_load_many_self_into(output, relation_enum);
}
self.expand_load_many_to_many_self_into(output, junction_module, *reverse);
}
}
}
}
impl EntityLoaderOutput {
fn from_schema(schema: &EntityLoaderSchema) -> Self {
let total_count = schema.fields.iter().fold(
HashMap::<&TypePath, usize>::new(),
|mut total_count, field| {
*total_count.entry(&field.entity).or_insert(0) += 1;
total_count
},
);
let mut relation_tuple_impls = HashSet::<&TypePath>::new();
let mut select_arity = 1;
let mut output = Self::default();
output.select_tuple_fields.push(quote!(model));
for field in &schema.fields {
let duplicate_entity = total_count
.get(&field.entity)
.is_some_and(|count| *count != 1);
field.expand_loader_with_field_into(&mut output);
field.expand_loader_nest_field_into(&mut output);
field.expand_loader_with_set_impl_into(&mut output, duplicate_entity);
field.expand_loader_with_2_impl_into(&mut output, duplicate_entity);
if let EntityLoaderFieldKind::ManyToManySelf {
junction_module,
reverse,
} = &field.kind
{
field.expand_many_to_many_self_with_param_into(
&mut output,
junction_module,
*reverse,
);
}
if matches!(
&field.kind,
EntityLoaderFieldKind::HasOne
| EntityLoaderFieldKind::HasMany
| EntityLoaderFieldKind::ManyToMany
) && duplicate_entity
&& field.relation_enum.is_some()
&& relation_tuple_impls.insert(&field.entity)
{
field.expand_relation_tuple_with_param_into(&mut output);
}
if matches!(&field.kind, EntityLoaderFieldKind::HasOne) && !duplicate_entity {
select_arity += 1;
if select_arity <= 3 {
field.expand_select_one_into(&mut output);
}
}
field.expand_load_into(&mut output, duplicate_entity);
}
output
}
}
pub fn expand_entity_loader(vis: &Visibility, schema: EntityLoaderSchema) -> TokenStream {
let EntityLoaderOutput {
loader_with_fields,
loader_nest_fields,
select_tuple_fields,
loader_with_set_impl,
loader_with_2_impl,
fetch_select_impl,
assemble_one,
load_one,
load_many,
load_one_nest,
load_many_nest,
load_one_nest_nest,
load_many_nest_nest,
with_param_impls,
} = EntityLoaderOutput::from_schema(&schema);
let (async_, await_) = if cfg!(feature = "async") {
(quote!(async), quote!(.await))
} else {
(quote!(), quote!())
};
let async_trait = if cfg!(feature = "async") {
quote!(#[async_trait::async_trait])
} else {
quote!()
};
quote! {
#[doc = " Generated by sea-orm-macros"]
#[derive(Clone)]
#vis struct EntityLoader {
select: sea_orm::Select<Entity>,
with: EntityLoaderWith,
nest: EntityLoaderNest,
}
#[doc = " Generated by sea-orm-macros"]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#vis struct EntityReverse;
impl sea_orm::compound::EntityReverse for EntityReverse {
type Entity = Entity;
}
#[doc = " Generated by sea-orm-macros"]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#vis struct EntityLoaderWith {
#loader_with_fields
}
#[doc = " Generated by sea-orm-macros"]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#vis struct EntityLoaderNest {
#loader_nest_fields
}
impl Entity {
#[doc = " Generated by sea-orm-macros"]
pub const REVERSE: EntityReverse = EntityReverse;
}
impl EntityLoaderWith {
#[doc = " Generated by sea-orm-macros"]
pub fn is_empty(&self) -> bool {
self == &Self::default()
}
#[doc = " Generated by sea-orm-macros"]
pub fn set(&mut self, target: sea_orm::compound::LoadTarget) {
#loader_with_set_impl
}
}
#[doc = " Parameters for EntityLoader"]
#vis trait EntityLoaderWithParam {
#[doc = " Generated by sea-orm-macros"]
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>);
}
#[automatically_derived]
impl<R> EntityLoaderWithParam for R
where
R: EntityTrait,
Entity: Related<R>,
{
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(sea_orm::compound::LoadTarget::TableRef(self.table_ref()), None)
}
}
#[automatically_derived]
impl<R, S> EntityLoaderWithParam for (R, S)
where
R: EntityTrait,
Entity: Related<R>,
S: EntityTrait,
R: Related<S>,
{
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(
sea_orm::compound::LoadTarget::TableRef(self.0.table_ref()),
Some(sea_orm::compound::LoadTarget::TableRef(self.1.table_ref())),
)
}
}
#[automatically_derived]
impl<R, S> EntityLoaderWithParam for sea_orm::compound::EntityLoaderWithSelf<R, S>
where
R: EntityTrait,
Entity: Related<R>,
S: EntityTrait,
R: RelatedSelfVia<S>,
{
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(
sea_orm::compound::LoadTarget::TableRef(self.0.table_ref()),
Some(sea_orm::compound::LoadTarget::TableRef(self.1.table_ref())),
)
}
}
#[automatically_derived]
impl<R, S, SR> EntityLoaderWithParam for sea_orm::compound::EntityLoaderWithSelfRev<R, SR>
where
R: EntityTrait,
Entity: Related<R>,
S: EntityTrait,
R: RelatedSelfVia<S>,
SR: sea_orm::compound::EntityReverse<Entity = S>,
{
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(
sea_orm::compound::LoadTarget::TableRef(self.0.table_ref()),
Some(sea_orm::compound::LoadTarget::TableRefRev(S::default().table_ref())),
)
}
}
#[automatically_derived]
impl EntityLoaderWithParam for Relation {
fn into_with_param(self) -> (sea_orm::compound::LoadTarget, Option<sea_orm::compound::LoadTarget>) {
(sea_orm::compound::LoadTarget::Relation(self.name()), None)
}
}
#with_param_impls
#[automatically_derived]
impl std::fmt::Debug for EntityLoader {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EntityLoader")
.field("select", &match (Entity::default().schema_name(), Entity::default().table_name()) {
(Some(s), t) => format!("{s}.{t}"),
(None, t) => t.to_owned(),
})
.field("with", &self.with)
.field("nest", &self.nest)
.finish()
}
}
#[automatically_derived]
impl sea_orm::QueryFilter for EntityLoader {
type QueryStatement = <sea_orm::Select<Entity> as sea_orm::QueryFilter>::QueryStatement;
fn query(&mut self) -> &mut Self::QueryStatement {
sea_orm::QueryFilter::query(&mut self.select)
}
}
#[automatically_derived]
impl sea_orm::QueryOrder for EntityLoader {
type QueryStatement = <sea_orm::Select<Entity> as sea_orm::QueryOrder>::QueryStatement;
fn query(&mut self) -> &mut Self::QueryStatement {
sea_orm::QueryOrder::query(&mut self.select)
}
}
#[automatically_derived]
#async_trait
impl sea_orm::compound::EntityLoaderTrait<Entity> for EntityLoader {
type ModelEx = ModelEx;
#async_ fn fetch<C: sea_orm::ConnectionTrait>(self, db: &C, page: u64, page_size: u64) -> Result<Vec<Self::ModelEx>, sea_orm::DbErr> {
self.fetch(db, page, page_size)#await_
}
#async_ fn num_items<C: sea_orm::ConnectionTrait>(self, db: &C, page_size: u64) -> Result<u64, sea_orm::DbErr> {
self.select.paginate(db, page_size).num_items()#await_
}
}
impl Entity {
#[doc = " Generated by sea-orm-macros"]
pub fn load() -> EntityLoader {
EntityLoader {
select: Entity::find(),
with: Default::default(),
nest: Default::default(),
}
}
}
impl EntityLoader {
#[doc = " Generated by sea-orm-macros"]
pub #async_ fn one<C: sea_orm::ConnectionTrait>(mut self, db: &C) -> Result<Option<ModelEx>, sea_orm::DbErr> {
use sea_orm::QuerySelect;
self.select = self.select.limit(1);
Ok(self.all(db)#await_?.into_iter().next())
}
#[doc = " Generated by sea-orm-macros"]
pub #async_ fn all<C: sea_orm::ConnectionTrait>(self, db: &C) -> Result<Vec<ModelEx>, sea_orm::DbErr> {
self.fetch(db, 0, 0)#await_
}
#[doc = " Generated by sea-orm-macros"]
pub fn with<T: EntityLoaderWithParam>(mut self, param: T) -> Self {
match param.into_with_param() {
(left, None) => self.with_1(left),
(left, Some(right)) => self.with_2(left, right),
}
}
fn with_1(mut self, load_target: sea_orm::compound::LoadTarget) -> Self {
self.with.set(load_target);
self
}
fn with_2(mut self, left: sea_orm::compound::LoadTarget, right: sea_orm::compound::LoadTarget) -> Self {
#loader_with_2_impl
self
}
#[doc = " Generated by sea-orm-macros"]
#async_ fn fetch<C: sea_orm::ConnectionTrait>(mut self, db: &C, page: u64, page_size: u64) -> Result<Vec<ModelEx>, sea_orm::DbErr> {
let select = self.select;
let mut loaded = EntityLoaderWith::default();
#fetch_select_impl
let models = if page_size != 0 {
select.paginate(db, page_size).fetch_page(page)#await_?
} else {
select.all(db)#await_?
};
let models = models.into_iter().map(|(#select_tuple_fields)| {
let mut model = model.into_ex();
#assemble_one
model
}).collect::<Vec<_>>();
let models = Self::load(models, &self.with, &self.nest, db)#await_?;
Ok(models)
}
#[doc = " Generated by sea-orm-macros"]
pub #async_ fn load<C: sea_orm::ConnectionTrait>(mut models: Vec<ModelEx>, with: &EntityLoaderWith, nest: &EntityLoaderNest, db: &C) -> Result<Vec<ModelEx>, DbErr> {
use sea_orm::LoaderTraitEx;
#load_one
#load_many
Ok(models)
}
#[doc = " Generated by sea-orm-macros"]
pub #async_ fn load_nest<C: sea_orm::ConnectionTrait>(mut models: Vec<Option<ModelEx>>, with: &EntityLoaderWith, db: &C) -> Result<Vec<Option<ModelEx>>, DbErr> {
use sea_orm::LoaderTraitEx;
#load_one_nest
#load_many_nest
Ok(models)
}
#[doc = " Generated by sea-orm-macros"]
pub #async_ fn load_nest_nest<C: sea_orm::ConnectionTrait>(mut models: Vec<Vec<ModelEx>>, with: &EntityLoaderWith, db: &C) -> Result<Vec<Vec<ModelEx>>, DbErr> {
use sea_orm::NestedLoaderTrait;
#load_one_nest_nest
#load_many_nest_nest
Ok(models)
}
}
}
}