hr-system/scripts/json2ddl.py

90 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""json2ddl 等价实现ocai database-table-definition-spec
读取 models/{module}/*.jsonsummary/fields/indexes/codes生成幂等 MySQL/MariaDB DDL。
幂等性CREATE TABLE IF NOT EXISTS索引先查 information_schema 再按需补建(可重跑)。
用法python3 scripts/json2ddl.py <models根目录> [输出sql文件]
"""
import json, os, sys, glob
TYPE_MAP = {
"varchar": lambda f: f"VARCHAR({f.get('length', 64)})",
"text": lambda f: "TEXT",
"int": lambda f: "INT",
"date": lambda f: "DATE",
"timestamp": lambda f: "TIMESTAMP NULL DEFAULT NULL",
"decimal": lambda f: f"DECIMAL({f.get('precision', 18)},{f.get('scale', 4)})",
}
def render_field(f):
t = f["type"]
if t not in TYPE_MAP:
raise ValueError(f"未知字段类型 {t} ({f.get('name')})")
col = f"`{f['name']}` {TYPE_MAP[t](f)}"
if f.get("notnull"):
col += " NOT NULL"
if "default" in f and t != "timestamp":
dv = f["default"]
col += f" DEFAULT '{dv}'" if isinstance(dv, str) else f" DEFAULT {dv}"
col += f" COMMENT '{f['title']}'"
return col
def render_index_sql(table, idx):
kind = "UNIQUE KEY" if idx.get("unique") else "KEY"
cols = ",".join(f"`{c}`" for c in idx["fields"])
return f" {kind} `{idx['name']}` ({cols})"
def gen_table_ddl(path):
doc = json.load(open(path, encoding="utf-8"))
s = doc["summary"][0]
table = s["name"]
lines = [render_field(f) for f in doc["fields"]]
pk = ",".join(f"`{c}`" for c in s.get("pk", ["id"]))
lines.append(f" PRIMARY KEY ({pk})")
for idx in doc.get("indexes", []):
lines.append(render_index_sql(table, idx))
charset = s.get("charset", "utf8mb4")
collate = s.get("collate", "utf8mb4_unicode_ci")
title = s.get("title", table)
return table, (f"CREATE TABLE IF NOT EXISTS `{table}` (\n" + ",\n".join(lines) +
f"\n) ENGINE=InnoDB DEFAULT CHARSET={charset} COLLATE={collate} COMMENT='{title}';")
def gen_index_guard_sql(table, idx):
"""运行时补索引建表时已含此处供重跑补漏apply_ddl.py 使用)"""
kind = "UNIQUE INDEX" if idx.get("unique") else "INDEX"
cols = ",".join(f"`{c}`" for c in idx["fields"])
return f"ALTER TABLE `{table}` ADD {kind} `{idx['name']}` ({cols});"
def main():
src = sys.argv[1] if len(sys.argv) > 1 else "models"
out = sys.argv[2] if len(sys.argv) > 2 else None
parts = ["-- 人事系统 hr-web 批次1 DDLjson2ddl 生成,幂等可重跑)",
"-- 来源models/*.jsondatabase-design.md v3.049 表目标库hrs(MariaDB)",
"-- 执行mysql -utest -ptest123 hrs < mysql.ddl.sql 或 python3 scripts/apply_ddl.py",
"SET NAMES utf8mb4;", ""]
n = 0
for moddir in sorted(glob.glob(os.path.join(src, "*"))):
if not os.path.isdir(moddir):
continue
files = sorted(glob.glob(os.path.join(moddir, "*.json")))
if not files:
continue
parts.append(f"-- ===== {os.path.basename(moddir)}{len(files)} 张)=====")
for p in files:
table, ddl = gen_table_ddl(p)
parts.append(f"-- {table}")
parts.append(ddl)
parts.append("")
n += 1
parts.append(f"-- 共 {n} 张表")
sql = "\n".join(parts) + "\n"
if out:
with open(out, "w", encoding="utf-8") as f:
f.write(sql)
print(f"生成 {out}{n} 张表")
else:
sys.stdout.write(sql)
if __name__ == "__main__":
main()