20260919211702

This commit is contained in:
oneao committed 2026-09-19 21:17:02 +08:00
1 parent f56e70b050
commit f4bfc1ddfc
97 files changed
+6059 -1712

No files matched your search

+12 -14
View File
@@ -205,7 +205,7 @@ create table dbo.s_relation (
b_target_module_id varchar(50) not null, -- 目标模块
b_target_field varchar(50) not null, -- 目标字段
b_relation_type varchar(20) not null, -- one_to_one / one_to_many / many_to_one
b_on_delete varchar(20) not null default 'none', -- 删除连带:none不连带 / cascade连带删除 / archive连带归档
b_on_delete varchar(20) not null default 'restrict', -- 删除处置:restrict有外部引用即拒绝 / cascade连带删除 / none不处理不保护
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_xh int not null default 0, -- 显示顺序
primary key (
@@ -226,21 +226,19 @@ create index ix_s_relation_target
GO
/* ============================================================================
9.1 删除规则
9.1 删除 SQL 规则
挂在模块(业务条件:勾条件 / 写 SQL)或模块关系(存在引用即拒绝删除)上的删除前规则。
规则类型不单独存列,由 b_predicate 推断:空=引用规则;JSON=勾条件;其余=SQL 文本。
b_scope_id 是挂载对象的业务键:模块=模块编码;关系=源模块|源字段|目标模块|目标字段。
主键用雪花 id(新增时前端取号,与业务表一致):规则没有天然业务键,也不要求 IT 填编码。
模块级“什么情况下不允许删除”的规则:b_sql 是只读查询,返回至少一行即拒绝本批删除。
只服务模块删除(target=module);无模块的技术表走直接删除,不受本表约束。
关系上的关联处置(含引用保护)由 s_relation.b_on_delete 表达,不再挂规则行。
主键用雪花 id(新增时前端取号):规则没有天然业务键,也不要求 IT 填编码。
============================================================================ */
create table dbo.s_rule (
create table dbo.s_delete_rule (
b_id bigint not null, -- 雪花主键(新增时前端经 /data/nextid 取号)
b_scope_type varchar(20) not null, -- module / relation(挂载范围)
b_scope_id varchar(250) not null, -- module=模块编码;relation=源模块|源字段|目标模块|目标字段
b_hook varchar(30) not null, -- delete.pre(一期只做这个),save.pre 留位
b_predicate nvarchar(max) null, -- 空=引用规则;JSON={"kind":"dsl","expr":…}=勾条件;其余=SQL 文本
b_message nvarchar(500) null, -- 提示文案(写 SQL 必填;勾条件可空,引擎按条件自动生成)
b_module_id varchar(50) not null, -- 规则所属数据模块编码(对应 s_module.b_id)
b_sql nvarchar(max) not null, -- 只读查询 SQL,用 :ids 标记本次待删 ID 集合
b_message nvarchar(500) null, -- 删除失败时的提示文案(第一阶段固定文案)
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_xh int not null default 0, -- 执行顺序(并列按 b_xh、b_id)
b_created_by varchar(50) null, -- 审计列由服务端维护,配置界面不提交
@@ -251,8 +249,8 @@ create table dbo.s_rule (
);
GO
create index ix_s_rule_scope
on dbo.s_rule (b_scope_type, b_scope_id, b_hook, b_canuse, b_xh);
create index ix_s_delete_rule_module
on dbo.s_delete_rule (b_module_id, b_canuse, b_xh);
GO
/* ============================================================================
+81 -28
View File
@@ -1,47 +1,100 @@
/* ============================================================================
删除规则一期:s_relation 加删除连带列 + 新建规则表 s_rule
删除策略重构:s_relation 删除处置三值 + 新建删除 SQL 规则表 s_delete_rule
----------------------------------------------------------------------------
背景:见 FMS删除规则引擎设计.md(一期只落配置,后端引擎二期做)。
依据:FMS删除策略重构设计.md v1.2
第一阶段元数据脚本,只改结构,不含初始化数据。
本脚本可重复执行:
- s_relation.b_on_delete 不存在时才加(存量行回填 'none');
- s_rule 直接重建(drop + create)——表里还没有规则数据时才可执行,
库中已有配置数据时请勿运行,改为手工迁移。
- s_relation.b_on_delete 不存在时才加,且默认值取 'restrict';
- 存量关系的 b_on_delete 不批量回填(设计 §3.1:避免上线后突然改变存量删除行为);
仅把历史遗留的 'archive' 归一到 'none'(阶段一不支持归档,避免执行器遇到未知值);
- s_delete_rule 不存在才建;旧的 s_rule 已废弃,按需手工 drop(见文件末尾说明)。
执行:fms-api 目录下
java -cp "tools/migration/mssql-jdbc-13.4.0.jre11.jar" tools/migration/RunSqlFile.java \
../sql/fms_delete_rule.sql --dry-run
确认分批正确后去掉 --dry-run 实跑(按 GO 分批、单事务、失败整体回滚)。
============================================================================ */
/* 1. b_on_delete:补列并设定新语义的默认值。
新值域 restrict / cascade / none;默认 restrict 只作用于新建行,
存量行保持原值(历史为 'none'),由单独迁移决定是否升级。 */
if col_length('dbo.s_relation', 'b_on_delete') is null
begin
alter table dbo.s_relation add
b_on_delete varchar(20) not null default 'none'; -- none不连带 / cascade连带删除 / archive连带归档
b_on_delete varchar(20) not null
constraint df_s_relation_on_delete default 'restrict';
end
GO
drop table if exists dbo.s_rule;
/* 2. 列已存在时,只改默认值约束,不动存量数据。 */
if col_length('dbo.s_relation', 'b_on_delete') is not null
begin
declare @constraint sysname;
select @constraint = dc.name
from sys.default_constraints dc
join sys.columns c
on c.object_id = dc.parent_object_id
and c.column_id = dc.parent_column_id
where dc.parent_object_id = object_id('dbo.s_relation')
and c.name = 'b_on_delete';
if @constraint is not null
begin
declare @dropSql nvarchar(400) =
N'alter table dbo.s_relation drop constraint ' + quotename(@constraint);
exec sp_executesql @dropSql;
end
alter table dbo.s_relation add
constraint df_s_relation_on_delete default 'restrict' for b_on_delete;
end
GO
/* 删除规则表:挂在模块(业务条件)或模块关系(存在引用即拒绝删除)上。
规则类型不单独存列,由 b_predicate 推断:空=引用规则;JSON=勾条件;其余=SQL 文本。
主键用雪花 id(新增时前端取号,与业务表一致):规则没有天然业务键,也不要求 IT 填编码。 */
create table dbo.s_rule (
b_id bigint not null, -- 雪花主键(新增时前端经 /data/nextid 取号)
b_scope_type varchar(20) not null, -- module / relation(挂载范围)
b_scope_id varchar(250) not null, -- module=模块编码;relation=源模块|源字段|目标模块|目标字段
b_hook varchar(30) not null, -- delete.pre(一期只做这个),save.pre 留位
b_predicate nvarchar(max) null, -- 空=引用规则;JSON={"kind":"dsl","expr":…}=勾条件;其余=SQL 文本
b_message nvarchar(500) null, -- 提示文案(写 SQL 必填;勾条件可空,引擎按条件自动生成)
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_xh int not null default 0, -- 执行顺序(并列按 b_xh、b_id)
b_created_by varchar(50) null, -- 审计列由服务端维护,配置界面不提交
b_created_at datetime2 null,
b_updated_by varchar(50) null,
b_updated_at datetime2 null,
primary key (b_id)
);
/* 3. 历史 'archive' 阶段一不支持:归一为 'none'(不处理、不保护),
避免删除执行器读到未知处置值。空值与非法值同样归一,保证值域收敛。 */
update dbo.s_relation
set b_on_delete = 'none'
where b_on_delete is null
or b_on_delete not in ('restrict', 'cascade', 'none');
GO
create index ix_s_rule_scope
on dbo.s_rule (b_scope_type, b_scope_id, b_hook, b_canuse, b_xh);
GO
/* 4. 删除 SQL 规则表。 */
if object_id('dbo.s_delete_rule', 'U') is null
begin
create table dbo.s_delete_rule (
b_id bigint not null, -- 雪花主键(新增时前端经 /data/nextid 取号)
b_module_id varchar(50) not null, -- 规则所属数据模块编码(对应 s_module.b_id)
b_sql nvarchar(max) not null, -- 只读查询 SQL,用 :ids 标记本次待删 ID 集合
b_message nvarchar(500) null, -- 删除失败时的提示文案(第一阶段固定文案)
b_canuse tinyint not null default 1, -- 是否启用(0/1)
b_xh int not null default 0, -- 执行顺序(并列按 b_xh、b_id)
b_created_by varchar(50) null, -- 审计列由服务端维护,配置界面不提交
b_created_at datetime2 null,
b_updated_by varchar(50) null,
b_updated_at datetime2 null,
primary key (b_id)
);
end
GO
if not exists (
select 1 from sys.indexes
where name = 'ix_s_delete_rule_module'
and object_id = object_id('dbo.s_delete_rule')
)
begin
create index ix_s_delete_rule_module
on dbo.s_delete_rule (b_module_id, b_canuse, b_xh);
end
GO
/* 5. 旧表 s_rule 的处置。
已确认库内 s_rule 无配置数据,可直接重建;此处刻意不 drop,
避免脚本误伤可能存在的历史配置。确认无数据后手工执行:
drop table if exists dbo.s_rule;
若库中确实存在规则数据,需先迁移:
- b_scope_type='module' 且 b_predicate 为 SQL 文本 → 写入 s_delete_rule
(b_module_id = b_scope_id,b_sql = b_predicate);
- b_scope_type='relation'(引用规则)→ 置该关系 s_relation.b_on_delete='restrict';
- b_predicate 为 JSON 勾条件的数据无法自动转换,需人工改写为等价 SQL。 */
+22
View File
@@ -0,0 +1,22 @@
/* ============================================================================
删除废弃表 s_rule
----------------------------------------------------------------------------
背景:删除策略重构(FMS删除策略重构设计.md v1.2)用 s_delete_rule 取代了
旧的泛化规则表 s_rule。s_rule 已无任何读取方(前端旧概念、后端引用均已移除),
且经核实库中行数为 0,可直接删除。
执行前已确认:
- catalog = FMS(RunSqlFile 自带校验)
- s_rule 行数 = 0
- s_delete_rule 已存在(新表就位)
执行:fms-api 目录下
java -cp "tools/migration/mssql-jdbc-13.4.0.jre11.jar" tools/migration/RunSqlFile.java \
../sql/fms_drop_s_rule.sql
============================================================================ */
if object_id('dbo.s_rule', 'U') is not null
begin
drop table dbo.s_rule;
end
GO
+17
View File
@@ -0,0 +1,17 @@
/* 冒烟测试数据:主单 2 条,明细 3 条(O1 有 2 条明细,O2 有 1 条) */
delete from dbo.smoke_order_item;
GO
delete from dbo.smoke_order;
GO
insert into dbo.smoke_order (b_id, b_no, b_status) values ('SO-1', N'单号一', 'draft');
GO
insert into dbo.smoke_order (b_id, b_no, b_status) values ('SO-2', N'单号二', 'audited');
GO
insert into dbo.smoke_order_item (b_item_id, b_order_id, b_name) values ('SI-1', 'SO-1', N'明细1');
GO
insert into dbo.smoke_order_item (b_item_id, b_order_id, b_name) values ('SI-2', 'SO-1', N'明细2');
GO
insert into dbo.smoke_order_item (b_item_id, b_order_id, b_name) values ('SI-3', 'SO-2', N'明细3');
GO
+63
View File
@@ -0,0 +1,63 @@
/* ============================================================================
删除策略冒烟测试夹具(可重复执行)
----------------------------------------------------------------------------
建一对专用临时业务表 + 模块配置 + 删除规则,用于验证删除引擎:
smoke_order 主单(b_id varchar 业务键)
smoke_order_item 明细(b_item_id 主键,b_order_id 外键指向主单)
覆盖场景:
1. cascade:删主单连带删明细
2. restrict:明细被引用时拒绝删主单
3. SQL 规则:命中即整批拒绝
4. direct:按表直删
清理见 smoke_delete_teardown.sql。
============================================================================ */
if object_id('dbo.smoke_order_item', 'U') is null
begin
create table dbo.smoke_order_item (
b_item_id varchar(50) not null primary key,
b_order_id varchar(50) not null,
b_name nvarchar(100) null
);
end
GO
if object_id('dbo.smoke_order', 'U') is null
begin
create table dbo.smoke_order (
b_id varchar(50) not null primary key,
b_no nvarchar(50) null,
b_status varchar(20) null
);
end
GO
/* 模块配置:主单 */
if not exists (select 1 from dbo.s_module where b_id = 'smoke_order')
begin
insert into dbo.s_module (b_id, b_parent_id, b_depth, b_path, b_name, b_module_type, b_view_table, b_save_table, b_key_field, b_canuse, b_xh)
values ('smoke_order', null, 0, 'smoke_order', N'冒烟测试主单', 'data', 'smoke_order', 'smoke_order', 'b_id', 1, 9001);
end
GO
/* 模块配置:明细 */
if not exists (select 1 from dbo.s_module where b_id = 'smoke_order_item')
begin
insert into dbo.s_module (b_id, b_parent_id, b_depth, b_path, b_name, b_module_type, b_view_table, b_save_table, b_key_field, b_canuse, b_xh)
values ('smoke_order_item', null, 0, 'smoke_order_item', N'冒烟测试明细', 'data', 'smoke_order_item', 'smoke_order_item', 'b_item_id', 1, 9002);
end
GO
/* 关系:明细 → 主单,many_to_one。
按设计 §3.2,many_to_one 的外键在源字段:源字段 b_order_id 是明细表里的外键列,
目标字段 b_id 是主单被引用的列。删除主单时,明细(引用方)被 cascade 连带删除。 */
delete from dbo.s_relation where b_source_module_id = 'smoke_order_item' and b_target_module_id = 'smoke_order';
GO
insert into dbo.s_relation
(b_source_module_id, b_source_field, b_target_module_id, b_target_field, b_relation_type, b_on_delete, b_canuse, b_xh)
values
('smoke_order_item', 'b_order_id', 'smoke_order', 'b_id', 'many_to_one', 'cascade', 1, 10);
GO
+40
View File
@@ -0,0 +1,40 @@
/* ============================================================================
删除策略冒烟测试夹具:清理(可重复执行,表不存在也能跑通)
----------------------------------------------------------------------------
注意两点,都是实测踩出来的:
1. 关系行必须按双向清理:冒烟会临时造反向关系(环路场景 smoke_order → smoke_order_item),
只删一个方向会留下指向已 drop 表的孤儿行。
2. 业务表的 delete 必须用 object_id 守卫:清理可重入,表已 drop 时直接 delete 会报
Invalid object name,而 RunSqlFile 是单事务、一批失败整体回滚,
会导致整个清理静默失效(前面几批的删除也被回滚)。
============================================================================ */
delete from dbo.s_delete_rule where b_module_id in ('smoke_order', 'smoke_order_item');
GO
/* 关系行:双向清理,避免孤儿关系 */
delete from dbo.s_relation
where b_source_module_id in ('smoke_order', 'smoke_order_item')
or b_target_module_id in ('smoke_order', 'smoke_order_item');
GO
delete from dbo.s_module where b_id in ('smoke_order', 'smoke_order_item');
GO
if object_id('dbo.smoke_order_item', 'U') is not null
begin
delete from dbo.smoke_order_item;
end
GO
if object_id('dbo.smoke_order', 'U') is not null
begin
delete from dbo.smoke_order;
end
GO
drop table if exists dbo.smoke_order_item;
GO
drop table if exists dbo.smoke_order;
GO