-
-
Notifications
You must be signed in to change notification settings - Fork 660
Description
Description
FromQueryResult fails for PartialModel when having nested Option where the nested Model has optional fields
Steps to Reproduce
#[derive(DerivePartialModel, Debug, Clone)]
#[sea_orm(entity = "crate::definition::user::User)"]
pub struct User {
id: Uuid,
#[sea_orm(nested)]
post: Option<Post>,
}
// Post Model
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Serialize, Deserialize)]
pub struct Model {
pub id: Uuid,
pub foo: Option<String>,
}
If you try to do a left join and there are no matching user posts, and then call .into_partial_model it throws an error Missing value for column id
Expected Behavior
The query should be successful
Actual Behavior
Throws error Missing value for column id
Reproduces How Often
Always, I believe the bug is in this PR #2845
The below code always wraps the field in Option<> so you will end up with Option<Option<String>> for the Post model
let reader = quote! {
let #field_ident =
row.try_get_nullable::<Option<#field_type>>(
pre,
sea_orm::IdenStatic::as_str(
&<<Self as sea_orm::ModelTrait>::Entity
as sea_orm::entity::EntityTrait>::Column::#column_ident
).into()
)?;
and then when checking if the entire nested model is None, this below check is faulty because calling .is_none() on an Option<Option> value returns false when the value is
Some(None)
let all_null_check = {
let checks: Vec<_> = izip!(field_idents, ignore_attrs)
.filter_map(|(field_ident, &ignore)| {
if ignore {
None
} else {
Some(quote! { #field_ident.is_none() })
}
})
.collect();
quote! { true #( && #checks )* }
};
Workarounds
If I implement FromQueryResult myself and change the all_null_check function to properly evaluate Option<Option>, then the partial model query works properly
if true
&& id.is_none()
&& (foo.is_none() || (foo == Some(None)))
{
return Err(sea_orm::TryGetError::Null(
"All fields of nested model are null".into(),
));
}
Versions
- sea-orm v2.0.0-rc.30
- postgres 15.12