SeaQL / sea-orm

🐚 An async & dynamic ORM for Rust
https://www.sea-ql.org/SeaORM/
Apache License 2.0
7.43k stars 519 forks source link

> 0.10.2: error[E0119]: conflicting implementations of trait #1287

Closed frederikhors closed 1 year ago

frederikhors commented 1 year ago

Description

Using unfortunately on a new PC the new sea-orm-cli@0.10.5 instead of 0.10.2 I get the below error with the same PG schema.

I cannot publish code because of NDA.

Actual Behavior

It gives this error after generation:

error[E0119]: conflicting implementations of trait `sea_orm::Related<generated::tenant::Entity>` for type `generated::player::Entity`
   |
63 | impl Related<super::tenant::Entity> for Entity {
   | ---------------------------------------------- first implementation here
...
69 | impl Related<super::tenant::Entity> for Entity {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `generated::player::Entity`

Versions

Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-orm v0.10.5
Ôöé   Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-orm-macros v0.10.5 (proc-macro)
Ôöé   Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-query v0.27.2
Ôöé   Ôöé   Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-query-derive v0.2.0 (proc-macro)
Ôöé   Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-query-binder v0.2.2
Ôöé   Ôöé   Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-query v0.27.2 (*)
Ôöé   Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-strum v0.23.0
Ôöé   Ôöé   Ôöé   Ôöé   ÔööÔöÇÔöÇ sea-strum_macros v0.23.0 (proc-macro)
Ôöé   Ôöé   ÔööÔöÇÔöÇ sea-orm v0.10.5 (*)
Ôöé   Ôöé   Ôö£ÔöÇÔöÇ sea-orm v0.10.5 (*)
Ôöé   Ôö£ÔöÇÔöÇ sea-orm v0.10.5 (*)
billy1624 commented 1 year ago

Hey @frederikhors, thanks for the reporting!! I want to understand the situation before formulating the solution.

image

I guess the schema is similar to above?

There are two paths between cake and baker

`cake` entity file: ```rs use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub name: String, #[sea_orm(column_type = "Decimal(Some((19, 4)))")] pub price: Decimal, pub bakery_id: Option, pub gluten_free: bool, pub serial: Uuid, pub recipe_author: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( belongs_to = "super::baker::Entity", from = "Column::RecipeAuthor", to = "super::baker::Column::Id", on_update = "NoAction", on_delete = "NoAction" )] Baker, #[sea_orm( belongs_to = "super::bakery::Entity", from = "Column::BakeryId", to = "super::bakery::Column::Id", on_update = "NoAction", on_delete = "NoAction" )] Bakery, #[sea_orm(has_many = "super::lineitem::Entity")] Lineitem, } impl Related for Entity { fn to() -> RelationDef { Relation::Bakery.def() } } impl Related for Entity { fn to() -> RelationDef { Relation::Lineitem.def() } } impl Related for Entity { // Conflicting implementation!! fn to() -> RelationDef { Relation::Baker.def() } } impl Related for Entity { // Conflicting implementation!! fn to() -> RelationDef { super::cakes_bakers::Relation::Baker.def() } fn via() -> Option { Some(super::cakes_bakers::Relation::Cake.def().rev()) } } impl ActiveModelBehavior for ActiveModel {} ```
`baker` entity file: ```rs use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "baker")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub name: String, pub contact_details: Json, pub bakery_id: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( belongs_to = "super::bakery::Entity", from = "Column::BakeryId", to = "super::bakery::Column::Id", on_update = "Cascade", on_delete = "Cascade" )] Bakery, #[sea_orm(has_many = "super::cake::Entity")] Cake, } impl Related for Entity { fn to() -> RelationDef { Relation::Bakery.def() } } impl Related for Entity { // Conflicting implementation!! fn to() -> RelationDef { Relation::Cake.def() } } impl Related for Entity { // Conflicting implementation!! fn to() -> RelationDef { super::cakes_bakers::Relation::Cake.def() } fn via() -> Option { Some(super::cakes_bakers::Relation::Baker.def().rev()) } } impl ActiveModelBehavior for ActiveModel {} ```
frederikhors commented 1 year ago

Yeah. I think the issue is because we have tenant_id column on both tables. And sea-orm-cli goes crazy about it! :smile:

TurtIeSocks commented 1 year ago

I think I'm seeing something similar on 0.10.*.

I was previously using 0.9.0 without issue.

error[E0119]: conflicting implementations of trait `std::fmt::Display` for type `sea_orm_active_enums::Type`
 --> entity/src/sea_orm_active_enums.rs:7:53
  |
7 |     Debug, Display, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Deserialize, Serialize,
  |            ------- first implementation here        ^^^^^^^^^^^^^^^^ conflicting implementation for `sea_orm_active_enums::Type`
  |
  = note: this error originates in the derive macro `DeriveActiveEnum` (in Nightly builds, run with -Z macro-backtrace for more info)

Imports and macro for the file in question:

use sea_orm::{entity::prelude::*, strum::Display};
use serde::{Deserialize, Serialize};

#[derive(
    Debug, Display, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Deserialize, Serialize,
)]

Downgrading to 0.9.3 solves the issue. Let me know if you'd like me to open a separate issue @billy1624.

frederikhors commented 1 year ago

I think this is not the same.

clay07g commented 1 year ago

I was talking about this in the discord a bit.

The generator seems to generate all relations as Related functions without considering multiple relationships between two entities.

You can manually code the solution to this with, I believe, Chained Relations, so in the example could do:

// cake.rs
// ....

pub struct CakeBakersLink;

impl Linked for CakeBakersLink {
    type FromEntity = Entity;

    type ToEntity = cake_bakers::Entity;

    fn link(&self) -> Vec<RelationDef> {
        vec![
            cake_bakers::Relation::Cakes.def().rev(),
            cake_bakers::Relation::Bakers.def(),
        ]
    }
}

So the default relationship from Cake will give you its recipe author. To get its bakers, you use CakeBakersLink. You can also ditch the Relation function entirely and also make the recipe author relationship a chained one, too, so that it's more clear.

Short term maybe the generator should generate Linked structs for secondary relationships for entities.

And long term, maybe make it customizable for how the user wants to handle relationships. For example, I think I'd like the ability to generate all relationships as Linked instead of Related, except for linking tables like cake_bakers. I like chained relationships because the Linked struct can be named to give context. Cake::find().also_find_related(Baker) is less intuitive to me than Cake::find().also_find_linked(RecipeAuthorBakerLink) (which can be generated based on column name).

billy1624 commented 1 year ago

Hey @TurtIeSocks, the problem you mention isn't related to this issue.

In sea-orm 0.10.x, DeriveActiveEnum implement Display trait for you. So, you don't need to derive or implement it on your own.

https://github.com/SeaQL/sea-orm/issues/1255

billy1624 commented 1 year ago

Hey everyone, thanks for the input! I've created https://github.com/SeaQL/sea-orm/pull/1298 which will skip the implementation of

impl Related<super::baker::Entity> for Entity {
    fn to() -> RelationDef {
        Relation::Baker.def()
    }
}

While keeping this

impl Related<super::baker::Entity> for Entity {
    fn to() -> RelationDef {
        super::cakes_bakers::Relation::Baker.def()
    }
    fn via() -> Option<RelationDef> {
        Some(super::cakes_bakers::Relation::Cake.def().rev())
    }
}
frederikhors commented 1 year ago

Hey everyone, thanks for the input! I've created #1298 which will skip the implementation of

impl Related<super::baker::Entity> for Entity {
    fn to() -> RelationDef {
        Relation::Baker.def()
    }
}

While keeping this

impl Related<super::baker::Entity> for Entity {
    fn to() -> RelationDef {
        super::cakes_bakers::Relation::Baker.def()
    }
    fn via() -> Option<RelationDef> {
        Some(super::cakes_bakers::Relation::Cake.def().rev())
    }
}

Can you release this ASAP?

billy1624 commented 1 year ago

I'll publish it tomorrow morning

billy1624 commented 1 year ago

sea-orm-cli 0.10.6 has been published https://crates.io/crates/sea-orm-cli/0.10.6