Name conflict of foreign key constraints when two entities have more than one foreign keys (#417)
* fix: name conflict of foreign key constraints when two entities have more than one fk * test: update test case's foreign keys * feat: override default name of foreign key constraint
This commit is contained in:
parent
946a03b426
commit
76c0d7fff5
@ -28,5 +28,6 @@ pub mod field_attr {
|
|||||||
pub on_delete: Option<syn::Lit>,
|
pub on_delete: Option<syn::Lit>,
|
||||||
pub from: Option<syn::Lit>,
|
pub from: Option<syn::Lit>,
|
||||||
pub to: Option<syn::Lit>,
|
pub to: Option<syn::Lit>,
|
||||||
|
pub fk_name: Option<syn::Lit>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,22 @@ impl DeriveRelation {
|
|||||||
result = quote! { #result.on_delete(sea_orm::prelude::ForeignKeyAction::#on_delete) };
|
result = quote! { #result.on_delete(sea_orm::prelude::ForeignKeyAction::#on_delete) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if attr.fk_name.is_some() {
|
||||||
|
let fk_name = attr
|
||||||
|
.fk_name
|
||||||
|
.as_ref()
|
||||||
|
.map(|lit| {
|
||||||
|
match lit {
|
||||||
|
syn::Lit::Str(lit_str) => Ok(lit_str.value()),
|
||||||
|
_ => Err(syn::Error::new_spanned(lit, "attribute must be a string")),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok_or_else(|| {
|
||||||
|
syn::Error::new_spanned(variant, "Missing value for 'fk_name'")
|
||||||
|
})??;
|
||||||
|
result = quote! { #result.fk_name(#fk_name) };
|
||||||
|
}
|
||||||
|
|
||||||
result = quote! { #result.into() };
|
result = quote! { #result.into() };
|
||||||
|
|
||||||
Result::<_, syn::Error>::Ok(result)
|
Result::<_, syn::Error>::Ok(result)
|
||||||
|
@ -62,6 +62,8 @@ pub struct RelationDef {
|
|||||||
/// Defines an operation to be performed on a Foreign Key when a
|
/// Defines an operation to be performed on a Foreign Key when a
|
||||||
/// `UPDATE` Operation is performed
|
/// `UPDATE` Operation is performed
|
||||||
pub on_update: Option<ForeignKeyAction>,
|
pub on_update: Option<ForeignKeyAction>,
|
||||||
|
/// The name of foreign key constraint
|
||||||
|
pub fk_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines a helper to build a relation
|
/// Defines a helper to build a relation
|
||||||
@ -80,6 +82,7 @@ where
|
|||||||
is_owner: bool,
|
is_owner: bool,
|
||||||
on_delete: Option<ForeignKeyAction>,
|
on_delete: Option<ForeignKeyAction>,
|
||||||
on_update: Option<ForeignKeyAction>,
|
on_update: Option<ForeignKeyAction>,
|
||||||
|
fk_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelationDef {
|
impl RelationDef {
|
||||||
@ -94,6 +97,7 @@ impl RelationDef {
|
|||||||
is_owner: !self.is_owner,
|
is_owner: !self.is_owner,
|
||||||
on_delete: self.on_delete,
|
on_delete: self.on_delete,
|
||||||
on_update: self.on_update,
|
on_update: self.on_update,
|
||||||
|
fk_name: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,6 +118,7 @@ where
|
|||||||
is_owner,
|
is_owner,
|
||||||
on_delete: None,
|
on_delete: None,
|
||||||
on_update: None,
|
on_update: None,
|
||||||
|
fk_name: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +133,7 @@ where
|
|||||||
is_owner,
|
is_owner,
|
||||||
on_delete: None,
|
on_delete: None,
|
||||||
on_update: None,
|
on_update: None,
|
||||||
|
fk_name: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +166,12 @@ where
|
|||||||
self.on_update = Some(action);
|
self.on_update = Some(action);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the name of foreign key constraint
|
||||||
|
pub fn fk_name(mut self, fk_name: &str) -> Self {
|
||||||
|
self.fk_name = Some(fk_name.to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, R> From<RelationBuilder<E, R>> for RelationDef
|
impl<E, R> From<RelationBuilder<E, R>> for RelationDef
|
||||||
@ -177,6 +189,7 @@ where
|
|||||||
is_owner: b.is_owner,
|
is_owner: b.is_owner,
|
||||||
on_delete: b.on_delete,
|
on_delete: b.on_delete,
|
||||||
on_update: b.on_update,
|
on_update: b.on_update,
|
||||||
|
fk_name: b.fk_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,20 +144,18 @@ where
|
|||||||
let mut foreign_key_stmt = ForeignKeyCreateStatement::new();
|
let mut foreign_key_stmt = ForeignKeyCreateStatement::new();
|
||||||
let from_tbl = unpack_table_ref(&relation.from_tbl);
|
let from_tbl = unpack_table_ref(&relation.from_tbl);
|
||||||
let to_tbl = unpack_table_ref(&relation.to_tbl);
|
let to_tbl = unpack_table_ref(&relation.to_tbl);
|
||||||
match relation.from_col {
|
let from_cols: Vec<String> = match relation.from_col {
|
||||||
Identity::Unary(o1) => {
|
Identity::Unary(o1) => vec![o1],
|
||||||
foreign_key_stmt.from_col(o1);
|
Identity::Binary(o1, o2) => vec![o1, o2],
|
||||||
}
|
Identity::Ternary(o1, o2, o3) => vec![o1, o2, o3],
|
||||||
Identity::Binary(o1, o2) => {
|
|
||||||
foreign_key_stmt.from_col(o1);
|
|
||||||
foreign_key_stmt.from_col(o2);
|
|
||||||
}
|
|
||||||
Identity::Ternary(o1, o2, o3) => {
|
|
||||||
foreign_key_stmt.from_col(o1);
|
|
||||||
foreign_key_stmt.from_col(o2);
|
|
||||||
foreign_key_stmt.from_col(o3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.into_iter()
|
||||||
|
.map(|col| {
|
||||||
|
let col_name = col.to_string();
|
||||||
|
foreign_key_stmt.from_col(col);
|
||||||
|
col_name
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
match relation.to_col {
|
match relation.to_col {
|
||||||
Identity::Unary(o1) => {
|
Identity::Unary(o1) => {
|
||||||
foreign_key_stmt.to_col(o1);
|
foreign_key_stmt.to_col(o1);
|
||||||
@ -166,7 +164,7 @@ where
|
|||||||
foreign_key_stmt.to_col(o1);
|
foreign_key_stmt.to_col(o1);
|
||||||
foreign_key_stmt.to_col(o2);
|
foreign_key_stmt.to_col(o2);
|
||||||
}
|
}
|
||||||
crate::Identity::Ternary(o1, o2, o3) => {
|
Identity::Ternary(o1, o2, o3) => {
|
||||||
foreign_key_stmt.to_col(o1);
|
foreign_key_stmt.to_col(o1);
|
||||||
foreign_key_stmt.to_col(o2);
|
foreign_key_stmt.to_col(o2);
|
||||||
foreign_key_stmt.to_col(o3);
|
foreign_key_stmt.to_col(o3);
|
||||||
@ -178,13 +176,14 @@ where
|
|||||||
if let Some(action) = relation.on_update {
|
if let Some(action) = relation.on_update {
|
||||||
foreign_key_stmt.on_update(action);
|
foreign_key_stmt.on_update(action);
|
||||||
}
|
}
|
||||||
|
let name = if let Some(name) = relation.fk_name {
|
||||||
|
name
|
||||||
|
} else {
|
||||||
|
format!("fk-{}-{}", from_tbl.to_string(), from_cols.join("-"))
|
||||||
|
};
|
||||||
stmt.foreign_key(
|
stmt.foreign_key(
|
||||||
foreign_key_stmt
|
foreign_key_stmt
|
||||||
.name(&format!(
|
.name(&name)
|
||||||
"fk-{}-{}",
|
|
||||||
from_tbl.to_string(),
|
|
||||||
to_tbl.to_string()
|
|
||||||
))
|
|
||||||
.from_tbl(from_tbl)
|
.from_tbl(from_tbl)
|
||||||
.to_tbl(to_tbl),
|
.to_tbl(to_tbl),
|
||||||
);
|
);
|
||||||
@ -235,7 +234,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKeyCreateStatement::new()
|
ForeignKeyCreateStatement::new()
|
||||||
.name("fk-cake_filling_price-cake_filling")
|
.name("fk-cake_filling_price-cake_id-filling_id")
|
||||||
.from_tbl(CakeFillingPrice)
|
.from_tbl(CakeFillingPrice)
|
||||||
.from_col(cake_filling_price::Column::CakeId)
|
.from_col(cake_filling_price::Column::CakeId)
|
||||||
.from_col(cake_filling_price::Column::FillingId)
|
.from_col(cake_filling_price::Column::FillingId)
|
||||||
|
@ -55,7 +55,7 @@ pub async fn create_baker_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
.col(ColumnDef::new(baker::Column::BakeryId).integer())
|
.col(ColumnDef::new(baker::Column::BakeryId).integer())
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-baker-bakery")
|
.name("fk-baker-bakery_id")
|
||||||
.from(baker::Entity, baker::Column::BakeryId)
|
.from(baker::Entity, baker::Column::BakeryId)
|
||||||
.to(bakery::Entity, bakery::Column::Id)
|
.to(bakery::Entity, bakery::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -111,7 +111,7 @@ pub async fn create_order_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-order-bakery")
|
.name("fk-order-bakery_id")
|
||||||
.from(order::Entity, order::Column::BakeryId)
|
.from(order::Entity, order::Column::BakeryId)
|
||||||
.to(bakery::Entity, bakery::Column::Id)
|
.to(bakery::Entity, bakery::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -119,7 +119,7 @@ pub async fn create_order_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-order-customer")
|
.name("fk-order-customer_id")
|
||||||
.from(order::Entity, order::Column::CustomerId)
|
.from(order::Entity, order::Column::CustomerId)
|
||||||
.to(customer::Entity, customer::Column::Id)
|
.to(customer::Entity, customer::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -162,7 +162,7 @@ pub async fn create_lineitem_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-lineitem-order")
|
.name("fk-lineitem-order_id")
|
||||||
.from(lineitem::Entity, lineitem::Column::OrderId)
|
.from(lineitem::Entity, lineitem::Column::OrderId)
|
||||||
.to(order::Entity, order::Column::Id)
|
.to(order::Entity, order::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -170,7 +170,7 @@ pub async fn create_lineitem_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-lineitem-cake")
|
.name("fk-lineitem-cake_id")
|
||||||
.from(lineitem::Entity, lineitem::Column::CakeId)
|
.from(lineitem::Entity, lineitem::Column::CakeId)
|
||||||
.to(cake::Entity, cake::Column::Id)
|
.to(cake::Entity, cake::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -202,7 +202,7 @@ pub async fn create_cakes_bakers_table(db: &DbConn) -> Result<ExecResult, DbErr>
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-cakes_bakers-cake")
|
.name("fk-cakes_bakers-cake_id")
|
||||||
.from(cakes_bakers::Entity, cakes_bakers::Column::CakeId)
|
.from(cakes_bakers::Entity, cakes_bakers::Column::CakeId)
|
||||||
.to(cake::Entity, cake::Column::Id)
|
.to(cake::Entity, cake::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -210,7 +210,7 @@ pub async fn create_cakes_bakers_table(db: &DbConn) -> Result<ExecResult, DbErr>
|
|||||||
)
|
)
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-cakes_bakers-baker")
|
.name("fk-cakes_bakers-baker_id")
|
||||||
.from(cakes_bakers::Entity, cakes_bakers::Column::BakerId)
|
.from(cakes_bakers::Entity, cakes_bakers::Column::BakerId)
|
||||||
.to(baker::Entity, baker::Column::Id)
|
.to(baker::Entity, baker::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
@ -240,7 +240,7 @@ pub async fn create_cake_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
.col(ColumnDef::new(cake::Column::BakeryId).integer())
|
.col(ColumnDef::new(cake::Column::BakeryId).integer())
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKey::create()
|
ForeignKey::create()
|
||||||
.name("fk-cake-bakery")
|
.name("fk-cake-bakery_id")
|
||||||
.from(cake::Entity, cake::Column::BakeryId)
|
.from(cake::Entity, cake::Column::BakeryId)
|
||||||
.to(bakery::Entity, bakery::Column::Id)
|
.to(bakery::Entity, bakery::Column::Id)
|
||||||
.on_delete(ForeignKeyAction::Cascade)
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
@ -16,6 +16,7 @@ pub struct Model {
|
|||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
pub enum Relation {
|
pub enum Relation {
|
||||||
#[sea_orm(
|
#[sea_orm(
|
||||||
|
fk_name = "fk-active_enum_child-active_enum",
|
||||||
belongs_to = "super::active_enum::Entity",
|
belongs_to = "super::active_enum::Entity",
|
||||||
from = "Column::ParentId",
|
from = "Column::ParentId",
|
||||||
to = "super::active_enum::Column::Id"
|
to = "super::active_enum::Column::Id"
|
||||||
|
@ -116,7 +116,7 @@ pub async fn create_self_join_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
.col(ColumnDef::new(self_join::Column::Time).time())
|
.col(ColumnDef::new(self_join::Column::Time).time())
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
ForeignKeyCreateStatement::new()
|
ForeignKeyCreateStatement::new()
|
||||||
.name("fk-self_join-self_join")
|
.name("fk-self_join-uuid_ref")
|
||||||
.from_tbl(SelfJoin)
|
.from_tbl(SelfJoin)
|
||||||
.from_col(self_join::Column::UuidRef)
|
.from_col(self_join::Column::UuidRef)
|
||||||
.to_tbl(SelfJoin)
|
.to_tbl(SelfJoin)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user