I have two tables in my schema which depend on each other. One of them is site, a "main" table which has many foreign keys pointing to site.site_id. Another is site_domain, which has a one-to-many relationship to sites, that is, one site could have no custom domains, or many. However, sites can (optionally) choose one domain as its "preferred" one, and there is a foreign key constraint from this column in site to site_domain.
The entity file generated for site lacked a Relation case for doing a JOIN where I want the site associated with a particular domain, instead it utilized a different foreign key, which was causing my query to not produce results as expected.
See "background" for further information.
Steps to Reproduce
Create a postgres database.
Apply a schema where, for tables which have a one-to-many relation, the one table has a foreign key constraint to one of the many.
Generate entity files. I used sea-orm-cli generate entity --verbose --database-url [url] --output-dir [dir].
Inspect the generated entity file and observe that there is no result for the many table in Relation which has #[sea_orm(has_many)].
Reproducible Example
A Postgres database with the given schema will produce the following entity files:
CREATE TABLE site (
site_id BIGSERIAL PRIMARY KEY,
custom_domain TEXT
);
CREATE TABLE site_domain (
domain TEXT PRIMARY KEY,
site_id BIGINT NOT NULL REFERENCES site(site_id)
);
ALTER TABLE site
ADD CONSTRAINT site_custom_domain_fk
FOREIGN KEY (custom_domain) REFERENCES site_domain(domain);
But, if I remove the second foreign key constraint, then it generates the has_many relation for finding the associated Site for a SiteDomain:
CREATE TABLE site (
site_id BIGSERIAL PRIMARY KEY,
custom_domain TEXT -- does NOT have a foreign key relation!
);
CREATE TABLE site_domain (
domain TEXT PRIMARY KEY,
site_id BIGINT NOT NULL REFERENCES site(site_id)
);
There should be multiple cases generated, one of which should be the simple has_many case.
Actual Behavior
Only one Relation::SiteDomain case is generated, which seems to be "overwriting" the has_many case with the belongs_to case.
Perhaps the naming should be numerical, e.g. SiteDomain1, SiteDomain2, or alternatively suffix-based, like SiteDomainCustomDomain for the custom_domain relation because it sees plain SiteDomain (just the has_many) already exists, or having that be named SiteDomainSite or similar.
Reproduces How Often
The above minimal example consistently generates the entity files as described.
Background
This issue was discovered while attempting to do a JOIN between the site and site_domain tables. It was failing to find results, and on inspection, the query that was being generated was incorrect. After debugging, I realized that the wrong JOIN condition was used, per the entity file.
I was attempting to write code that would execute this SQL query:
SELECT *
FROM site
JOIN site_domain
ON site.site_id = site_domain.site_id
WHERE site_domain.domain = $1
To do this, I wrote the following SeaORM code:
let model = Site::find()
.join(JoinType::Join, site::Relation::SiteDomain.def())
.filter(site_domain::Column::Domain.eq(domain))
.one(txn)
.await?;
#[sea_orm(
belongs_to = "super::site_domain::Entity",
from = "Column::CustomDomain",
to = "super::site_domain::Column::Domain",
on_update = "NoAction",
on_delete = "NoAction"
)]
SiteDomain,
I was expecting a simple #[sea_orm(has_many = "super::site_domain::Entity")] like the other Relation cases.
Workarounds
Presently, my workaround for this bug is to manually edit the entity file and add the case to the Relation enum. However, I would like to have sea-orm-cli wholly autogenerate my entity files to reduce maintenance burden.
Description
I have two tables in my schema which depend on each other. One of them is
site
, a "main" table which has many foreign keys pointing tosite.site_id
. Another issite_domain
, which has a one-to-many relationship to sites, that is, one site could have no custom domains, or many. However,site
s can (optionally) choose one domain as its "preferred" one, and there is a foreign key constraint from this column insite
tosite_domain
.The entity file generated for
site
lacked aRelation
case for doing a JOIN where I want the site associated with a particular domain, instead it utilized a different foreign key, which was causing my query to not produce results as expected.See "background" for further information.
Steps to Reproduce
sea-orm-cli generate entity --verbose --database-url [url] --output-dir [dir]
.Relation
which has#[sea_orm(has_many)]
.Reproducible Example
A Postgres database with the given schema will produce the following entity files:
Entity file:
```rs //! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.1 use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "site")] pub struct Model { #[sea_orm(primary_key)] pub site_id: i64, #[sea_orm(column_type = "Text", nullable)] pub custom_domain: Optionsite.rs
Entity file:
```rs //! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.1 use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "site_domain")] pub struct Model { #[sea_orm(primary_key, auto_increment = false, column_type = "Text")] pub domain: String, pub site_id: i64, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( belongs_to = "super::site::Entity", from = "Column::SiteId", to = "super::site::Column::SiteId", on_update = "NoAction", on_delete = "NoAction" )] Site, } impl Relatedsite_domain.rs
But, if I remove the second foreign key constraint, then it generates the
has_many
relation for finding the associatedSite
for aSiteDomain
:Entity file:
```rs //! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.1 use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "site")] pub struct Model { #[sea_orm(primary_key)] pub site_id: i64, #[sea_orm(column_type = "Text", nullable)] pub custom_domain: Optionsite.rs
Entity file:
```rs //! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.1 use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "site_domain")] pub struct Model { #[sea_orm(primary_key, auto_increment = false, column_type = "Text")] pub domain: String, pub site_id: i64, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm( belongs_to = "super::site::Entity", from = "Column::SiteId", to = "super::site::Column::SiteId", on_update = "NoAction", on_delete = "NoAction" )] Site, } impl Relatedsite_domain.rs
Expected Behavior
There should be multiple cases generated, one of which should be the simple
has_many
case.Actual Behavior
Only one
Relation::SiteDomain
case is generated, which seems to be "overwriting" thehas_many
case with thebelongs_to
case.Perhaps the naming should be numerical, e.g.
SiteDomain1
,SiteDomain2
, or alternatively suffix-based, likeSiteDomainCustomDomain
for thecustom_domain
relation because it sees plainSiteDomain
(just thehas_many
) already exists, or having that be namedSiteDomainSite
or similar.Reproduces How Often
The above minimal example consistently generates the entity files as described.
Background
This issue was discovered while attempting to do a JOIN between the
site
andsite_domain
tables. It was failing to find results, and on inspection, the query that was being generated was incorrect. After debugging, I realized that the wrong JOIN condition was used, per the entity file.I was attempting to write code that would execute this SQL query:
To do this, I wrote the following SeaORM code:
However the
Relation::SiteDomain
that was generated was nothas_many
:I was expecting a simple
#[sea_orm(has_many = "super::site_domain::Entity")]
like the otherRelation
cases.Workarounds
Presently, my workaround for this bug is to manually edit the entity file and add the case to the
Relation
enum. However, I would like to havesea-orm-cli
wholly autogenerate my entity files to reduce maintenance burden.See https://github.com/scpwiki/wikijump/pull/2084
Versions
Tested on sea-orm-cli versions 1.0.0 and 1.0.1