feat(plugin): PluginRelation 级联删除声明 + OnDeleteStrategy

新增 OnDeleteStrategy 枚举(Nullify/Cascade/Restrict)和
PluginRelation 结构体声明实体关联关系。PluginEntity 增加
relations 字段(serde(default) 向后兼容)。
This commit is contained in:
iven
2026-04-17 10:33:58 +08:00
parent 62f17d13ad
commit 527a57df9e
2 changed files with 58 additions and 0 deletions

View File

@@ -956,6 +956,7 @@ mod tests {
},
],
indexes: vec![],
relations: vec![],
};
let sql = DynamicTableManager::build_create_table_sql("erp_crm", &entity);
@@ -996,6 +997,7 @@ mod tests {
..PluginField::default_for_field()
}],
indexes: vec![],
relations: vec![],
};
let sql = DynamicTableManager::build_create_table_sql("erp_crm", &entity);

View File

@@ -43,6 +43,8 @@ pub struct PluginEntity {
pub fields: Vec<PluginField>,
#[serde(default)]
pub indexes: Vec<PluginIndex>,
#[serde(default)]
pub relations: Vec<PluginRelation>,
}
/// 字段校验规则
@@ -156,6 +158,23 @@ pub struct PluginIndex {
pub unique: bool,
}
/// 级联删除策略
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum OnDeleteStrategy {
Nullify, // 置空外键字段
Cascade, // 级联软删除
Restrict, // 存在关联时拒绝删除
}
/// 实体关联关系声明
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginRelation {
pub entity: String,
pub foreign_key: String,
pub on_delete: OnDeleteStrategy,
}
/// 事件订阅配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginEvents {
@@ -690,4 +709,41 @@ no_cycle = true
assert_eq!(field.no_cycle, Some(true));
assert_eq!(field.ref_entity.as_deref(), Some("customer"));
}
#[test]
fn parse_entity_with_relations() {
let toml = r#"
[metadata]
id = "test"
name = "Test"
version = "0.1.0"
[schema]
[[schema.entities]]
name = "customer"
display_name = "客户"
[[schema.entities.fields]]
name = "code"
field_type = "string"
required = true
display_name = "编码"
[[schema.entities.relations]]
entity = "contact"
foreign_key = "customer_id"
on_delete = "cascade"
[[schema.entities.relations]]
entity = "customer_tag"
foreign_key = "customer_id"
on_delete = "cascade"
"#;
let manifest = parse_manifest(toml).unwrap();
let entity = &manifest.schema.unwrap().entities[0];
assert_eq!(entity.relations.len(), 2);
assert_eq!(entity.relations[0].entity, "contact");
assert_eq!(entity.relations[0].foreign_key, "customer_id");
assert!(matches!(entity.relations[0].on_delete, OnDeleteStrategy::Cascade));
}
}