SeaQL / SeaQL/sea-orm

[EntityLoader] `EntityLoader::load()::with()` does not work for `self_ref` self references.

Open
#3,189 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Area:docs Category:enhancement help-wanted
Dominant language
Rust
Stars
9.9k
Forks
734
Avg merge
6h 36m
Merged PRs (30d)
8

Description

Description

I believe that EntityLoader::load()::with() does not work when trying to additionally select self referencing relations. Below is a hopefully working simple setup which I adapted from my existing project here. It should showcase the issue, but I haven't fully implemented it within a test project.

Steps to Reproduce

human.rs

use sea_orm::entity::prelude::*;

#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "humans")]
pub struct Model {
    #[sea_orm(primary_key)]
    id: i32,
   #[sea_orm(has_many)]
    pub hats: HasMany<super::hats::Entity>,
    #[sea_orm(
        self_ref,
        via = "jt_parent_to_child",
        from = "Humans",
        to = "Child"
    )]
    pub children: HasMany<Entity>,
    #[sea_orm(self_ref, via = "jt_parent_to_child", reverse)]
    pub parents: HasMany<Entity>,
}

impl ActiveModelBehavior for ActiveModel {}

jt_parent_child.rs

use sea_orm::entity::prelude::*;

#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "jt_parent_to_child")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub parent_id: i32,
    #[sea_orm(primary_key, auto_increment = false)]
    pub child_id: i32,
    #[sea_orm(belongs_to, from = "parent_id", to = "id")]
    pub parent: BelongsTo<super::humans::Entity>,
    #[sea_orm(belongs_to, relation_enum = "Child", from = "child_id", to = "id")]
    pub child: BelongsTo<super::humans::Entity>,
}

impl ActiveModelBehavior for ActiveModel {}

hats.rs

use sea_orm::entity::prelude::*;

#[sea_orm::model]
#[derive(Default, Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "hats")]
pub struct Model {
    #[sea_orm(primary_key)]
    id: i32,
    pub human_id: Option<i32>,
    #[sea_orm(belongs_to, from = "human_id", to = "id")]
    pub parent: BelongsTo<Option<super::humans::Entity>>,
}
Expected Behavior

This should work. However, since there currently is no mechanism to specifically identify the specific self _ref to select you would have to input .with(humans::Entity).

human::Entity::load()
            .filter_by_d(1)
            .with(hats::Entity)
            .with(/*some kind of mechanism to identify specific self ref*/)
            .one(db
            .await
Actual Behavior

This then fails with:

error[E0277]: the trait bound `entity::Humans: entity::humans::EntityLoaderWithParam` is not satisfied
   --> humans.rs:176:19
    |
176 |             .with(humans::Entity)
    |              ---- ^^^^^^^^^^^^^^^^^^^ the trait `Related<entity::Humans>` is not implemented for `entity::Humans`
    |              |
    |              required by a bound introduced by this call
    |
help: `entity::Humans` implements trait `Related<R>`
   --> some.rs:37:1
    |
 37 | #[sea_orm::model]
    | ^^^^^^^^^^^^^^^^^
    | |
    | `Related<entity::Hats>`
    = note: required for `entity::Humans` to implement `entity::humans::EntityLoaderWithParam`
note: required by a bound in `entity::humans::EntityLoader::with`
   --> humans.rs:37:1
    |
 37 | #[sea_orm::model]
    | ^^^^^^^^^^^^^^^^^ required by this bound in `EntityLoader::with`
    = note: this error originates in the derive macro `DeriveModelEx` (in Nightly builds, run with -Z macro-backtrace for more info)
Reproduces How Often

always

Workarounds

current none known

Versions

❯ cargo tree | grep sea-
│   │   ├── sea-orm v2.0.2
│   │   │   ├── sea-orm-macros v2.0.2 (proc-macro)
│   │   │   │   ├── sea-bae v0.2.2 (proc-macro)
│   │   │   ├── sea-query v1.0.2
│   │   │   │   ├── sea-query-derive v1.0.0 (proc-macro)
│   │   │   ├── sea-query-sqlx v0.9.1
│   │   │   │   ├── sea-query v1.0.2 (*)
│   │   │   ├── sea-schema v0.18.1
│   │   │   │   ├── sea-query v1.0.2 (*)
│   │   │   │   ├── sea-query-sqlx v0.9.1 (*)
│   │   │   │   ├── sea-schema-derive v0.3.0 (proc-macro)
│   │   ├── sea-query v1.0.2 (*)
├── sea-orm v2.0.2 (*)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the failing .with(humans::Entity) call from human.rs with the self-referencing relations in jt_parent_child.rs and hats.rs. Read the generated EntityLoader code and the referenced humans.rs and some.rs locations, then inspect the derive macro path named in the compiler error. Done means self-referencing relations can be selected through EntityLoader without the reported trait error, with a regression test covering the example.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.