apply_formula_structuring_ddl.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. # -*- coding: utf-8 -*-
  2. """第三批:公式结构化 DDL — 幂等可重跑。
  3. 1) 新建 ado_smart_ops_business_fact 业务事实字典表
  4. 2) 为 ado_smart_ops_kpi_master 增加 3 列:FormulaExpr / FormulaPreview / FormulaRefs
  5. 保留旧 Formula / CalcRule / DopFields 字段不动(Q3-B 向下兼容)。
  6. """
  7. from __future__ import annotations
  8. import sys
  9. import pymysql
  10. sys.stdout.reconfigure(encoding='utf-8')
  11. CONN = dict(
  12. host='123.60.180.165', port=3306,
  13. user='aidopremote', password='1234567890aiDOP#',
  14. database='aidopdev', charset='utf8mb4', autocommit=True,
  15. )
  16. FACT_TABLE_DDL = """
  17. CREATE TABLE IF NOT EXISTS `ado_smart_ops_business_fact` (
  18. `Id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  19. `FactCode` varchar(64) NOT NULL COMMENT '事实编码(英文,稳定)',
  20. `FactName` varchar(200) NOT NULL COMMENT '事实名称(中文,展示)',
  21. `ModuleCode` varchar(20) NULL COMMENT '归属模块 S1~S9 或 COMMON',
  22. `Unit` varchar(50) NULL COMMENT '单位',
  23. `AggType` varchar(20) NULL COMMENT '聚合类型 COUNT/SUM/AVG/MAX/MIN/LATEST',
  24. `DataSource` varchar(200) NULL COMMENT '预期数据来源(文字说明)',
  25. `Description` text NULL COMMENT '说明/备注',
  26. `IsEnabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
  27. `SortNo` int NOT NULL DEFAULT 0 COMMENT '排序号',
  28. `TenantId` bigint NOT NULL COMMENT '租户 ID',
  29. `CreatedAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  30. `UpdatedAt` datetime NULL COMMENT '更新时间',
  31. PRIMARY KEY (`Id`),
  32. UNIQUE KEY `uk_fact_code_tenant` (`FactCode`, `TenantId`),
  33. KEY `idx_fact_module_tenant` (`ModuleCode`, `TenantId`)
  34. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='业务事实字典(指标公式引用的分子/分母来源)';
  35. """
  36. KPIM_COLS = [
  37. ("FormulaExpr", "ALTER TABLE `ado_smart_ops_kpi_master` ADD COLUMN `FormulaExpr` varchar(500) NULL COMMENT '结构化表达式 @MetricCode/$FactCode 及算符常量'"),
  38. ("FormulaPreview", "ALTER TABLE `ado_smart_ops_kpi_master` ADD COLUMN `FormulaPreview` varchar(1000) NULL COMMENT '人读预览(引用替换为中文名)'"),
  39. ("FormulaRefs", "ALTER TABLE `ado_smart_ops_kpi_master` ADD COLUMN `FormulaRefs` varchar(500) NULL COMMENT '引用清单 JSON {metrics:[],facts:[]}'"),
  40. ]
  41. def table_exists(cur, table: str) -> bool:
  42. cur.execute("SELECT COUNT(*) AS c FROM information_schema.tables WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=%s", (table,))
  43. return cur.fetchone()[0] > 0
  44. def col_exists(cur, table: str, col: str) -> bool:
  45. cur.execute("SELECT COUNT(*) AS c FROM information_schema.columns WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=%s AND COLUMN_NAME=%s", (table, col))
  46. return cur.fetchone()[0] > 0
  47. def main() -> None:
  48. conn = pymysql.connect(**CONN)
  49. with conn.cursor() as cur:
  50. # 1) business fact
  51. if table_exists(cur, 'ado_smart_ops_business_fact'):
  52. print("[SKIP] ado_smart_ops_business_fact 已存在")
  53. else:
  54. cur.execute(FACT_TABLE_DDL)
  55. print("[OK] 创建 ado_smart_ops_business_fact")
  56. # 2) kpi master new columns
  57. for col, ddl in KPIM_COLS:
  58. if col_exists(cur, 'ado_smart_ops_kpi_master', col):
  59. print(f"[SKIP] kpi_master.{col} 已存在")
  60. else:
  61. cur.execute(ddl)
  62. print(f"[OK] 新增 kpi_master.{col}")
  63. # 验证
  64. cur.execute("SHOW COLUMNS FROM `ado_smart_ops_kpi_master`")
  65. cols = {r[0] for r in cur.fetchall()}
  66. missing = [c for c, _ in KPIM_COLS if c not in cols]
  67. if missing:
  68. raise RuntimeError(f"新增列缺失:{missing}")
  69. print("\n[DONE] DDL 全部就绪。")
  70. conn.close()
  71. if __name__ == "__main__":
  72. main()