基线:全量源码首提(D1 版本控制落地,含第一轮优化 B1-B4/A1/A4/缩放修复)
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""触发器生成器重构:①去掉聚合用列引用模式 ②箱号表数量触发器按箱号行生成(WHEN 行ID,真 SUM)
|
||||
③图号行触发器传箱号表 ④重建/新表入口同步。幂等。"""
|
||||
import io
|
||||
|
||||
P = r"C:\Users\099978\Documents\SharpDevelop Projects\成套报价软件\成套报价软件\计算引擎.cs"
|
||||
s = io.open(P, encoding="utf-8-sig").read()
|
||||
n = 0
|
||||
|
||||
def rep(old, new):
|
||||
global s, n
|
||||
if new in s and old not in s:
|
||||
print("已改(跳过):", old[:50].replace("\n", " "))
|
||||
return
|
||||
assert old in s, "锚点缺失: " + old[:80]
|
||||
s = s.replace(old, new, 1)
|
||||
n += 1
|
||||
|
||||
# 1) 子翻译 透传清理
|
||||
rep("p.引用模式 = 引用模式; p.下层表 = 下层表; p.层内公式 = 层内公式; p.展开栈 = 展开栈; p.聚合用列引用 = 聚合用列引用;",
|
||||
"p.引用模式 = 引用模式; p.下层表 = 下层表; p.层内公式 = 层内公式; p.展开栈 = 展开栈;")
|
||||
|
||||
# 2) 解析器删字段
|
||||
rep(''' public string 引用模式 = "NEW"; // NEW=触发器 NEW."列" / ROW=上级目标行 "列"
|
||||
public bool 聚合用列引用 = false; // true=SUM('列') 直接引用本行列(该聚合由下级触发器维护)''',
|
||||
''' public string 引用模式 = "NEW"; // NEW=触发器 NEW."列" / ROW=上级目标行 "列"''')
|
||||
|
||||
# 3) Sum子查询 删分支
|
||||
rep(''' /// <summary>SUM('列') → 对下层表整表求和;或(自触发场景)直接引用本行列(由下级触发器维护)。</summary>
|
||||
private string Sum子查询(string col)
|
||||
{
|
||||
string c = "\\"" + col.Replace("\\"", "\\"\\"") + "\\"";
|
||||
if (聚合用列引用)
|
||||
return "COALESCE(CAST(" + (引用模式 == "NEW" ? "NEW." : "") + c + " AS REAL),0)";
|
||||
return "COALESCE((SELECT CAST(SUM(CAST(" + c + " AS REAL)) AS REAL) FROM \\"" + 下层表.Replace("\\"", "\\"\\"") + "\\"),0)";
|
||||
}''',
|
||||
''' /// <summary>SUM('列') → 对下层表整表求和(每箱号一张元件表/每图号一张箱号表,无条件)。</summary>
|
||||
private string Sum子查询(string col)
|
||||
{
|
||||
return "COALESCE((SELECT CAST(SUM(CAST(\\"" + col.Replace("\\"", "\\"\\"") +
|
||||
"\\" AS REAL)) AS REAL) FROM \\"" + 下层表.Replace("\\"", "\\"\\"") + "\\"),0)";
|
||||
}''')
|
||||
|
||||
# 4) 翻译公式 删参数
|
||||
rep(''' private static string 翻译公式(string 表达式, Dictionary<string, 公式条目> 层内公式,
|
||||
string 引用模式, string 下层表, out string 错误, bool 聚合用列引用 = false)''',
|
||||
''' private static string 翻译公式(string 表达式, Dictionary<string, 公式条目> 层内公式,
|
||||
string 引用模式, string 下层表, out string 错误)''')
|
||||
rep(''' { 引用模式 = 引用模式, 下层表 = 下层表, 层内公式 = 层内公式, 展开栈 = new HashSet<string>(), 聚合用列引用 = 聚合用列引用 };''',
|
||||
''' { 引用模式 = 引用模式, 下层表 = 下层表, 层内公式 = 层内公式, 展开栈 = new HashSet<string>() };''')
|
||||
|
||||
# 5) 生成Set片段 删参数
|
||||
rep("private static string 生成Set片段(List<公式条目> 公式, string 引用模式, string 下层表, bool 聚合用列引用 = false)",
|
||||
"private static string 生成Set片段(List<公式条目> 公式, string 引用模式, string 下层表)")
|
||||
rep("string sql = 翻译公式(f.表达式, map, 引用模式, 下层表, out err, 聚合用列引用);",
|
||||
"string sql = 翻译公式(f.表达式, map, 引用模式, 下层表, out err);")
|
||||
rep("{ string e2; sql = 翻译公式(d[2], map, 引用模式, 下层表, out e2, 聚合用列引用); break; }",
|
||||
"{ string e2; sql = 翻译公式(d[2], map, 引用模式, 下层表, out e2); break; }")
|
||||
|
||||
# 6) 建箱号表触发器:按行生成
|
||||
rep(''' /// <summary>为一张箱号表生成触发器(u/i/d):行内公式 + 所属图号行聚合。</summary>
|
||||
public static void 建箱号表触发器(System.Data.SQLite.SQLiteConnection conn, System.Data.SQLite.SQLiteTransaction tx,
|
||||
string 箱号表, string 图号ID, string 图号表名,
|
||||
List<公式条目> 箱号公式, List<公式条目> 图号公式)
|
||||
{
|
||||
Drop触发器(conn, tx, 箱号表);
|
||||
string of = "";
|
||||
foreach (var c in 箱号输入列) of += "\\"" + c + "\\",";
|
||||
of = of.TrimEnd(',');
|
||||
|
||||
string xhSetNew = 生成Set片段(箱号公式, "NEW", null, true); // 本行(数量变);单台成本等由元件触发器维护
|
||||
string xhSetRow = 生成Set片段(箱号公式, "ROW", 箱号表, true); // 同上
|
||||
string thSet = 生成Set片段(图号公式, "ROW", 箱号表);
|
||||
string 刷图号 = "UPDATE \\"" + 图号表名 + "\\" SET " + thSet + " WHERE \\"内部ID\\"='" + 图号ID.Replace("'", "''") + "';";
|
||||
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_u AFTER UPDATE OF " + of + " ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW BEGIN UPDATE \\"" + 箱号表 + "\\" SET " + xhSetNew +
|
||||
" WHERE rowid=NEW.rowid; " + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_i AFTER INSERT ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW BEGIN UPDATE \\"" + 箱号表 + "\\" SET " + xhSetRow +
|
||||
" WHERE rowid=NEW.rowid; " + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_d AFTER DELETE ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW BEGIN " + 刷图号 + "END;");
|
||||
}''',
|
||||
''' /// <summary>
|
||||
/// 为一张箱号表生成触发器。箱号聚合依赖"每行各自的元件表",数量更新触发器按行生成
|
||||
/// (WHEN NEW."内部ID"=行ID,体内 SUM 子查询 FROM 该行的元件表);INSERT/DELETE 表级只刷图号聚合。
|
||||
/// 行列表:每项 [箱号ID, 该行元件表名]。
|
||||
/// </summary>
|
||||
public static void 建箱号表触发器(System.Data.SQLite.SQLiteConnection conn, System.Data.SQLite.SQLiteTransaction tx,
|
||||
string 箱号表, string 图号ID, string 图号表名, List<string[]> 行列表,
|
||||
List<公式条目> 箱号公式, List<公式条目> 图号公式)
|
||||
{
|
||||
Drop触发器(conn, tx, 箱号表);
|
||||
string of = "";
|
||||
foreach (var c in 箱号输入列) of += "\\"" + c + "\\",";
|
||||
of = of.TrimEnd(',');
|
||||
|
||||
string thSet = 生成Set片段(图号公式, "ROW", 箱号表);
|
||||
string 刷图号 = "UPDATE \\"" + 图号表名 + "\\" SET " + thSet + " WHERE \\"内部ID\\"='" + 图号ID.Replace("'", "''") + "';";
|
||||
|
||||
foreach (var 行 in 行列表)
|
||||
{
|
||||
string 行ID = 行[0], yj表 = 行[1];
|
||||
if (string.IsNullOrEmpty(yj表)) continue;
|
||||
string xhSetNew = 生成Set片段(箱号公式, "NEW", yj表);
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_r_" + Safe(行ID) +
|
||||
"_u AFTER UPDATE OF " + of + " ON \\"" + 箱号表 + "\\" FOR EACH ROW WHEN NEW.\\"内部ID\\"='" +
|
||||
行ID.Replace("'", "''") + "' BEGIN UPDATE \\"" + 箱号表 + "\\" SET " + xhSetNew +
|
||||
" WHERE rowid=NEW.rowid; " + 刷图号 + "END;");
|
||||
}
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_i AFTER INSERT ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW BEGIN " + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_d AFTER DELETE ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW BEGIN " + 刷图号 + "END;");
|
||||
}''')
|
||||
|
||||
# 7) 建图号行触发器:真 SUM
|
||||
rep(''' public static void 建图号行触发器(System.Data.SQLite.SQLiteConnection conn, System.Data.SQLite.SQLiteTransaction tx,
|
||||
string 图号表名, string 图号ID, List<公式条目> 图号公式)
|
||||
{
|
||||
string thSetNew = 生成Set片段(图号公式, "NEW", null, true);''',
|
||||
''' public static void 建图号行触发器(System.Data.SQLite.SQLiteConnection conn, System.Data.SQLite.SQLiteTransaction tx,
|
||||
string 图号表名, string 图号ID, string 箱号表, List<公式条目> 图号公式)
|
||||
{
|
||||
string thSetNew = 生成Set片段(图号公式, "NEW", 箱号表);''')
|
||||
|
||||
# 8) 重建项目全部触发器:组装行列表
|
||||
rep(''' // 先建箱号表映射后建元件触发器(元件触发器引用箱号表名,顺序无碍;图号行触发器每图号一次)
|
||||
var 已建图号 = new HashSet<string>();
|
||||
foreach (var m in 箱号行列表)
|
||||
建箱号表触发器(conn, tx, m[0], m[1], 图号表名, 箱号公式, 图号公式);
|
||||
foreach (var m in 元件表列表)
|
||||
建元件表触发器(conn, tx, m[0], m[1], m[2], m[3], 图号表名, 元件公式, 箱号公式, 图号公式);
|
||||
foreach (var kv in 箱号表Of图号)
|
||||
if (已建图号.Add(kv.Key))
|
||||
建图号行触发器(conn, tx, 图号表名, kv.Key, 图号公式);''',
|
||||
''' // 按箱号表分组元件表:[箱号表] → [箱号ID, 元件表] 列表
|
||||
var 行按表 = new Dictionary<string, List<string[]>>();
|
||||
foreach (var m in 元件表列表)
|
||||
{
|
||||
List<string[]> rows;
|
||||
if (!行按表.TryGetValue(m[1], out rows)) { rows = new List<string[]>(); 行按表[m[1]] = rows; }
|
||||
rows.Add(new[] { m[2], m[0] });
|
||||
}
|
||||
var 已建图号 = new HashSet<string>();
|
||||
foreach (var m in 箱号行列表)
|
||||
{
|
||||
List<string[]> rows;
|
||||
if (!行按表.TryGetValue(m[0], out rows)) rows = new List<string[]>();
|
||||
建箱号表触发器(conn, tx, m[0], m[1], 图号表名, rows, 箱号公式, 图号公式);
|
||||
}
|
||||
foreach (var m in 元件表列表)
|
||||
建元件表触发器(conn, tx, m[0], m[1], m[2], m[3], 图号表名, 元件公式, 箱号公式, 图号公式);
|
||||
foreach (var kv in 箱号表Of图号)
|
||||
if (已建图号.Add(kv.Key))
|
||||
建图号行触发器(conn, tx, 图号表名, kv.Key, kv.Value, 图号公式);''')
|
||||
|
||||
# 9) 建新表触发器:箱号分支传空行列表
|
||||
rep(''' else if (新表类型 == "箱号")
|
||||
建箱号表触发器(conn, tx, 箱号表, 图号ID, 图号表名, 箱号公式, 图号公式);''',
|
||||
''' else if (新表类型 == "箱号")
|
||||
{
|
||||
// 新箱号表暂无行级元件表映射;行级触发器由"建元件表触发器时同批重建/进项目自检"补齐
|
||||
建箱号表触发器(conn, tx, 箱号表, 图号ID, 图号表名, new List<string[]>(), 箱号公式, 图号公式);
|
||||
}''')
|
||||
|
||||
io.open(P, "w", encoding="utf-8-sig").write(s)
|
||||
print("重构完成", n, "处")
|
||||
Reference in New Issue
Block a user