基线:全量源码首提(D1 版本控制落地,含第一轮优化 B1-B4/A1/A4/缩放修复)
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""触发器总开关+批量刷新:
|
||||
①计算引擎:触发器统一加 WHEN 开关=0 条件;新增 开关表/开关设/批量刷新方法;重建时确保开关表存在
|
||||
②管线(图号/箱号粘贴、删除):开关=1 → 批量写 → 刷新图号全部计算 → 开关=0 (全在原事务内)
|
||||
幂等。"""
|
||||
import io
|
||||
|
||||
ROOT = r"C:\Users\099978\Documents\SharpDevelop Projects\成套报价软件\成套报价软件"
|
||||
n = 0
|
||||
|
||||
def edit(path, pairs, tag):
|
||||
global s, n
|
||||
for old, new in pairs:
|
||||
if old not in s:
|
||||
if new in s:
|
||||
print(tag, "已有(跳过)")
|
||||
continue
|
||||
raise AssertionError(tag + " 锚点缺失: " + old[:70])
|
||||
s = s.replace(old, new, 1)
|
||||
n += 1
|
||||
io.open(path, "w", encoding="utf-8-sig").write(s)
|
||||
print(tag, "ok")
|
||||
|
||||
p = ROOT + r"\计算引擎.cs"
|
||||
s = io.open(p, encoding="utf-8-sig").read()
|
||||
|
||||
# 1) 开关常量与开关表
|
||||
@@SKIP@@
|
||||
public const string 触发器前缀 = "trgjs_";''',
|
||||
''' /// <summary>触发器名前缀(重建时按前缀全清)。</summary>
|
||||
public const string 触发器前缀 = "trgjs_";
|
||||
|
||||
/// <summary>触发器总开关条件(批量操作时设 开关=1 跳过触发器体,提交前批量刷新+设回 0)。</summary>
|
||||
public const string 开关条件 = "(SELECT 开关 FROM _触发器开关 WHERE id=1)=0";''')
|
||||
|
||||
# 上面的辅助不适用,直接顺序替换
|
||||
def rep2(old, new):
|
||||
global s, n
|
||||
if old not in s:
|
||||
if new in s:
|
||||
print("跳过(已改)")
|
||||
return
|
||||
raise AssertionError("锚点缺失: " + old[:70])
|
||||
s = s.replace(old, new, 1)
|
||||
n += 1
|
||||
|
||||
rep2(''' /// <summary>触发器名前缀(重建时按前缀全清)。</summary>
|
||||
public const string 触发器前缀 = "trgjs_";''',
|
||||
''' /// <summary>触发器名前缀(重建时按前缀全清)。</summary>
|
||||
public const string 触发器前缀 = "trgjs_";
|
||||
|
||||
/// <summary>触发器总开关条件:批量操作时置 开关=1,触发器整体短路,提交前批量刷新后置回 0。</summary>
|
||||
public const string 开关条件 = "(SELECT 开关 FROM _触发器开关 WHERE id=1)=0";''')
|
||||
|
||||
# 2) EnsureFormulaTable 里顺带建开关表
|
||||
rep2(''' using (var cmd = new System.Data.SQLite.SQLiteCommand(
|
||||
"CREATE TABLE IF NOT EXISTS \\"" + 公式表名 + "\\" (" +
|
||||
"层级 TEXT, 目标列 TEXT, 表达式 TEXT, 排序 INTEGER, 启用 INTEGER DEFAULT 1);", conn))
|
||||
cmd.ExecuteNonQuery();''',
|
||||
''' using (var cmd = new System.Data.SQLite.SQLiteCommand(
|
||||
"CREATE TABLE IF NOT EXISTS \\"" + 公式表名 + "\\" (" +
|
||||
"层级 TEXT, 目标列 TEXT, 表达式 TEXT, 排序 INTEGER, 启用 INTEGER DEFAULT 1);", conn))
|
||||
cmd.ExecuteNonQuery();
|
||||
// 开关表放项目库(触发器同库),由 重建项目全部触发器 保证存在''')
|
||||
|
||||
# 3) 所有触发器 CREATE 加 WHEN 开关条件
|
||||
rep2(''' Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(元件表) + "_u AFTER UPDATE OF " + of + " ON \\"" +
|
||||
元件表 + "\\" FOR EACH ROW BEGIN UPDATE \\"" + 元件表 + "\\" SET " + selfSet +
|
||||
" WHERE rowid=NEW.rowid; " + 刷箱号 + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(元件表) + "_i AFTER INSERT ON \\"" +
|
||||
元件表 + "\\" FOR EACH ROW BEGIN UPDATE \\"" + 元件表 + "\\" SET " + selfSet +
|
||||
" WHERE rowid=NEW.rowid; " + 刷箱号 + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(元件表) + "_d AFTER DELETE ON \\"" +
|
||||
元件表 + "\\" FOR EACH ROW BEGIN " + 刷箱号 + 刷图号 + "END;");''',
|
||||
''' Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(元件表) + "_u AFTER UPDATE OF " + of + " ON \\"" +
|
||||
元件表 + "\\" FOR EACH ROW WHEN " + 开关条件 + " BEGIN UPDATE \\"" + 元件表 + "\\" SET " + selfSet +
|
||||
" WHERE rowid=NEW.rowid; " + 刷箱号 + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(元件表) + "_i AFTER INSERT ON \\"" +
|
||||
元件表 + "\\" FOR EACH ROW WHEN " + 开关条件 + " BEGIN UPDATE \\"" + 元件表 + "\\" SET " + selfSet +
|
||||
" WHERE rowid=NEW.rowid; " + 刷箱号 + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(元件表) + "_d AFTER DELETE ON \\"" +
|
||||
元件表 + "\\" FOR EACH ROW WHEN " + 开关条件 + " BEGIN " + 刷箱号 + 刷图号 + "END;");''')
|
||||
|
||||
rep2(''' Exec(conn, tx, "DROP TRIGGER IF EXISTS " + 触发器前缀 + Safe(箱号表) + "_r_" + Safe(箱号ID) + "_u;");
|
||||
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; UPDATE \\"" + 图号表名 + "\\" SET " + thSet +
|
||||
" WHERE \\"内部ID\\"='" + 图号ID.Replace("'", "''") + "'; END;");''',
|
||||
''' Exec(conn, tx, "DROP TRIGGER IF EXISTS " + 触发器前缀 + Safe(箱号表) + "_r_" + Safe(箱号ID) + "_u;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_r_" + Safe(箱号ID) +
|
||||
"_u AFTER UPDATE OF " + of + " ON \\"" + 箱号表 + "\\" FOR EACH ROW WHEN NEW.\\"内部ID\\"='" +
|
||||
箱号ID.Replace("'", "''") + "' AND " + 开关条件 + " BEGIN UPDATE \\"" + 箱号表 + "\\" SET " + xhSetNew +
|
||||
" WHERE rowid=NEW.rowid; UPDATE \\"" + 图号表名 + "\\" SET " + thSet +
|
||||
" WHERE \\"内部ID\\"='" + 图号ID.Replace("'", "''") + "'; END;");''')
|
||||
|
||||
rep2(''' 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;");''',
|
||||
''' Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_i AFTER INSERT ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW WHEN " + 开关条件 + " BEGIN " + 刷图号 + "END;");
|
||||
Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + Safe(箱号表) + "_d AFTER DELETE ON \\"" +
|
||||
箱号表 + "\\" FOR EACH ROW WHEN " + 开关条件 + " BEGIN " + 刷图号 + "END;");''')
|
||||
|
||||
rep2(''' Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + "th_" + suffix + "_u AFTER UPDATE OF \\"" +
|
||||
图号输入列[0] + "\\" ON \\"" + 图号表名 + "\\" FOR EACH ROW WHEN NEW.\\"内部ID\\"='" +
|
||||
图号ID.Replace("'", "''") + "' BEGIN UPDATE \\"" + 图号表名 + "\\" SET " + thSetNew +
|
||||
" WHERE rowid=NEW.rowid; END;");''',
|
||||
''' Exec(conn, tx, "CREATE TRIGGER " + 触发器前缀 + "th_" + suffix + "_u AFTER UPDATE OF \\"" +
|
||||
图号输入列[0] + "\\" ON \\"" + 图号表名 + "\\" FOR EACH ROW WHEN NEW.\\"内部ID\\"='" +
|
||||
图号ID.Replace("'", "''") + "' AND " + 开关条件 + " BEGIN UPDATE \\"" + 图号表名 + "\\" SET " + thSetNew +
|
||||
" WHERE rowid=NEW.rowid; END;");''')
|
||||
|
||||
# 4) 重建项目全部触发器:确保开关表+默认行
|
||||
rep2(''' var old = new List<string>();''',
|
||||
''' using (var cmd = new System.Data.SQLite.SQLiteCommand(
|
||||
"CREATE TABLE IF NOT EXISTS _触发器开关 (id INTEGER PRIMARY KEY, 开关 INTEGER DEFAULT 0);", conn, tx))
|
||||
cmd.ExecuteNonQuery();
|
||||
Exec(conn, tx, "INSERT OR IGNORE INTO _触发器开关 (id, 开关) VALUES (1, 0);");
|
||||
|
||||
var old = new List<string>();''')
|
||||
|
||||
# 5) 批量刷新方法(管线提交前调用):按表索引刷新该图号全部计算
|
||||
rep2(''' /// <summary>新表(管线内建表后)即时补触发器——只处理该表自身。</summary>''',
|
||||
''' /// <summary>
|
||||
/// 批量刷新某图号的全部计算(触发器关闭期间用):元件表派生列→箱号行聚合→图号行聚合。
|
||||
/// 全部为集合 SQL,每表一条 UPDATE;开关由调用方控制。
|
||||
/// </summary>
|
||||
public static void 批量刷新图号计算(System.Data.SQLite.SQLiteConnection conn, System.Data.SQLite.SQLiteTransaction tx,
|
||||
string 图号ID, string 图号表名, System.Data.SQLite.SQLiteConnection fakConn)
|
||||
{
|
||||
var 元件公式 = 加载公式(fakConn, "元件");
|
||||
var 箱号公式 = 加载公式(fakConn, "箱号");
|
||||
var 图号公式 = 加载公式(fakConn, "图号");
|
||||
|
||||
string xhTbl = null;
|
||||
using (var cmd = new System.Data.SQLite.SQLiteCommand(
|
||||
"SELECT 实际表名 FROM 表索引 WHERE 类型='箱号' AND 图号=@th LIMIT 1;", conn, tx))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@th", 图号ID);
|
||||
object o = cmd.ExecuteScalar();
|
||||
xhTbl = o == null || o == DBNull.Value ? null : o.ToString();
|
||||
}
|
||||
if (string.IsNullOrEmpty(xhTbl)) return;
|
||||
|
||||
// 1) 每张元件表:派生列集合 UPDATE
|
||||
var yj表们 = new List<string>();
|
||||
using (var cmd = new System.Data.SQLite.SQLiteCommand(
|
||||
"SELECT 实际表名 FROM 表索引 WHERE 类型='元件' AND 图号=@th;", conn, tx))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@th", 图号ID);
|
||||
using (var r = cmd.ExecuteReader())
|
||||
while (r.Read()) yj表们.Add(r.GetString(0));
|
||||
}
|
||||
string yjSet = 生成Set片段(元件公式, "ROW", null);
|
||||
foreach (var yj in yj表们)
|
||||
Exec(conn, tx, "UPDATE \\"" + yj + "\\" SET " + yjSet + ";");
|
||||
|
||||
// 2) 箱号每行:聚合(行自己的元件表 SUM)——行级一条 UPDATE
|
||||
string xhSet = 生成Set片段(箱号公式, "ROW", null); // 由下方逐行替换 SUM
|
||||
// 逐行:SUM 需要按行的元件表,取 表索引(元件) 列表
|
||||
using (var cmd = new System.Data.SQLite.SQLiteCommand(
|
||||
"SELECT 箱号, 实际表名 FROM 表索引 WHERE 类型='元件' AND 图号=@th;", conn, tx))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@th", 图号ID);
|
||||
using (var r = cmd.ExecuteReader())
|
||||
{
|
||||
var pairs = new List<string[]>();
|
||||
while (r.Read()) pairs.Add(new[] { r.IsDBNull(0) ? "" : r.GetString(0), r.IsDBNull(1) ? "" : r.GetString(1) });
|
||||
foreach (var pr in pairs)
|
||||
{
|
||||
string 行Set = 生成Set片段(箱号公式, "ROW", pr[1]);
|
||||
Exec(conn, tx, "UPDATE \\"" + xhTbl + "\\" SET " + 行Set + " WHERE \\"内部ID\\"='" + pr[0].Replace("'", "''") + "';");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3) 图号行:聚合(FROM 箱号表)
|
||||
string thSet = 生成Set片段(图号公式, "ROW", xhTbl);
|
||||
Exec(conn, tx, "UPDATE \\"" + 图号表名 + "\\" SET " + thSet + " WHERE \\"内部ID\\"='" + 图号ID.Replace("'", "''") + "';");
|
||||
}
|
||||
|
||||
/// <summary>开关设值(1=批量模式跳过触发器,0=恢复自动触发)。</summary>
|
||||
public static void 开关设(System.Data.SQLite.SQLiteConnection conn, System.Data.SQLite.SQLiteTransaction tx, int 值)
|
||||
{
|
||||
Exec(conn, tx, "UPDATE _触发器开关 SET 开关=" + 值 + " WHERE id=1;");
|
||||
}
|
||||
|
||||
/// <summary>新表(管线内建表后)即时补触发器——只处理该表自身。</summary>''')
|
||||
|
||||
io.open(p, "w", encoding="utf-8-sig").write(s)
|
||||
print("计算引擎 完成", n, "处")
|
||||
Reference in New Issue
Block a user