| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- package fixture
- import (
- "fmt"
- "io"
- "strings"
- )
- // 本文件只做第二批报告的终端排版。
- // PrintBatch2Report 打印「搬 4 表」结果。
- func PrintBatch2Report(w io.Writer, r *Batch2Report) {
- fmt.Fprintf(w, "== 第二批映射与装载 ==\n")
- fmt.Fprintf(w, "取样:分账树根=%d,充值工单用户=%d,收支记录创建人=%d,字典=%v\n",
- r.Options.DivideRootUserID, r.Options.BalanceRequestUserID,
- r.Options.ExpenditureLogUserID, r.Options.WithExpenditureDict)
- fmt.Fprintf(w, "legacy 行数:divide_into=%d, divide_into_log=%d, balance_request=%d, expenditure_log=%d, 字典=%d\n",
- r.LegacyCounts["t_user_divide_into"], r.LegacyCounts["t_user_divide_into_log"],
- r.LegacyCounts["t_user_balance_request"], r.LegacyCounts["t_expenditure_log"],
- r.LegacyCounts["t_expenditure"])
- fmt.Fprintf(w, "写入:t_expenditure=%d, t_user_divide_into=%d, t_user_divide_into_log=%d, "+
- "t_user_balance_request=%d, t_expenditure_log=%d\n",
- r.LoadedCounts["t_expenditure"], r.LoadedCounts["t_user_divide_into"],
- r.LoadedCounts["t_user_divide_into_log"], r.LoadedCounts["t_user_balance_request"],
- r.LoadedCounts["t_expenditure_log"])
- fmt.Fprintf(w, "引用人映射:%d 个 legacy uid → ULID(t_user %d 行 / t_legacy_mapping %d 行)\n",
- len(r.RefUsers), r.UsersWritten, r.MappingsWritten)
- fmt.Fprintf(w, "分账明细 id(D1 原样保留):%v\n", r.DivideLogIDs)
- if len(r.BizNoSamples) > 0 {
- fmt.Fprintf(w, "biz_no 样本(文本列已脱敏):\n")
- for _, s := range r.BizNoSamples {
- fmt.Fprintf(w, " %-24s biz=%s type=%-4d money=%s time=%s remark=%s\n",
- s.Table, s.BizNo, s.Type, CentsToDecimal(s.MoneyCents), s.CreateTime, s.RemarkMask)
- }
- }
- if len(r.Warnings) > 0 {
- fmt.Fprintf(w, "映射告警(%d):\n", len(r.Warnings))
- for _, x := range r.Warnings {
- fmt.Fprintf(w, " - %s\n", x)
- }
- } else {
- fmt.Fprintf(w, "映射告警:无\n")
- }
- }
- // PrintBatch2Verify 打印第二批核对结果(按「列 × N 行」聚合,避免逐格刷屏)。
- func PrintBatch2Verify(w io.Writer, r *Batch2VerifyReport) {
- fmt.Fprintf(w, "== 第二批逐列核对(列 × 行 聚合)==\n")
- lastTable := ""
- for _, c := range r.Cols {
- if c.Table != lastTable {
- fmt.Fprintf(w, "\n-- %s(target %d 行)--\n", c.Table, r.TargetRows[c.Table])
- lastTable = c.Table
- }
- st := markOK
- if !c.OK() {
- st = markFail
- }
- fmt.Fprintf(w, " %s %-24s %d/%d 相等 %s\n", st, c.Column, c.Equal, c.Total, c.Note)
- for _, s := range c.Samples {
- fmt.Fprintf(w, " ✘ %s\n", s)
- }
- }
- fmt.Fprintf(w, "\n== D1:id 与 legacy 完全相同 ==\n")
- for _, d := range r.D1 {
- st := markOK
- if !d.Pass {
- st = markFail
- }
- fmt.Fprintf(w, " %s %-24s legacy=%v\n target=%v\n", st, d.Table, d.LegacyIDs, d.TargetIDs)
- }
- fmt.Fprintf(w, "\n== biz_no 四项验证 ==\n")
- for _, v := range r.BizNo {
- fmt.Fprintf(w, " %s:legacy %d 行 / target %d 行\n", v.Table, v.LegacyRows, v.Rows)
- fmt.Fprintf(w, " ① 逐字符相等 %d 行;长度=32 的 %d 行;hex 形态 %d 行\n", v.CharEqual, v.Len32, v.HexOK)
- fmt.Fprintf(w, " ② 唯一:DISTINCT biz_no = %d(总 %d)\n", v.UniqueBizNo, v.Rows)
- fmt.Fprintf(w, " ③ id 解耦:max(id)=%d, AUTO_INCREMENT=%d;反序镜像 %v → %v\n",
- v.MaxID, v.AutoIncrementVal, v.MirrorOK, v.MirrorSample)
- fmt.Fprintf(w, " ④ 反查:biz_no JOIN 回 legacy 命中 %d 行\n", v.ReverseJoin)
- }
- fmt.Fprintf(w, "\n== 语义断言 ==\n")
- for _, a := range r.Assertions {
- st := markOK
- if !a.Pass {
- st = markFail
- }
- fmt.Fprintf(w, " %s %s\n %s\n", st, a.Name, a.Detail)
- }
- fmt.Fprintf(w, "\n核对结论:%s(不一致列 + 失败断言 = %d)\n", verdict(r.OK()), r.FailCount())
- }
- // PrintIdempotency 打印「跑两次」的幂等结论。
- func PrintIdempotency(w io.Writer, r *IdempotencyResult) {
- fmt.Fprintf(w, "== 幂等实测(同一批数据跑两次)==\n")
- for _, t := range []string{"t_user_balance_request", "t_expenditure_log"} {
- st := markOK
- if !r.SameRows[t] || !r.SameIDs[t] || r.NewBizNos[t] != 0 {
- st = markFail
- }
- fmt.Fprintf(w, " %s %s\n", st, t)
- fmt.Fprintf(w, " 第一次:%d 行,id=%v\n", len(r.Before[t]), r.IDListFirst[t])
- fmt.Fprintf(w, " 第二次:%d 行,id=%v\n", len(r.After[t]), r.IDListAgain[t])
- fmt.Fprintf(w, " 行数不变=%v,已存在行 id 不变=%v,新增 biz_no=%d\n",
- r.SameRows[t], r.SameIDs[t], r.NewBizNos[t])
- }
- fmt.Fprintf(w, "\n幂等结论:%s\n", verdict(r.AllOK()))
- }
- // PrintBatch2Clean 打印清理结果。
- func PrintBatch2Clean(w io.Writer, r *Batch2CleanReport) {
- fmt.Fprintf(w, "== 第二批清理 ==\n")
- fmt.Fprintf(w, "按 biz_no 精确删除 %d 行(balance_request + expenditure_log)\n", r.BizNos)
- for _, t := range []string{"t_expenditure", "t_user_divide_into", "t_user_divide_into_log",
- "t_user_balance_request", "t_expenditure_log", "t_legacy_mapping", "t_user"} {
- fmt.Fprintf(w, " %-26s 删除 %-4d 行,剩余全表 %d 行\n", t, r.Deleted[t], r.Remaining[t])
- }
- zero := true
- for _, t := range []string{"t_expenditure", "t_user_divide_into", "t_user_divide_into_log",
- "t_user_balance_request", "t_expenditure_log", "t_legacy_mapping", "t_user"} {
- if r.Remaining[t] != 0 {
- zero = false
- }
- }
- fmt.Fprintf(w, "7 张表回 0 行:%s\n", verdict(zero))
- }
- // PrintCounts 打印一组表的行数。
- func PrintCounts(w io.Writer, title string, counts map[string]int64, tables []string) {
- fmt.Fprintf(w, "== %s ==\n", title)
- for _, t := range tables {
- fmt.Fprintf(w, " %-26s %d\n", t, counts[t])
- }
- }
- // Batch2Tables 是第二批涉及的表名(固定顺序,报告用)。
- func Batch2Tables() []string {
- return []string{"t_expenditure", "t_user_divide_into", "t_user_divide_into_log",
- "t_user_balance_request", "t_expenditure_log", "t_legacy_mapping", "t_user"}
- }
- // JoinIDs 把 id 列表拼成一行(报告用,避免超长时刷屏)。
- func JoinIDs(ids []int64) string {
- if len(ids) == 0 {
- return "[]"
- }
- parts := make([]string, len(ids))
- for i, v := range ids {
- parts[i] = fmt.Sprint(v)
- }
- return "[" + strings.Join(parts, " ") + "]"
- }
|