Files
ai-gateway-go/scripts/export_legacy_dictionary.py
superidou 5759c1862e AI Gateway Go 0.10.0 源码快照 + 旗舰版需求规划报告
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。
含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-12 11:45:54 +08:00

98 lines
3.8 KiB
Python
Raw Permalink 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
"""Export the Python gateway SQLAlchemy schema as a reviewable Markdown dictionary.
This is an offline migration-development tool. It is not part of the Go runtime.
"""
from __future__ import annotations
import argparse
import importlib
import sys
from pathlib import Path
CURRENT_TARGETS = {
"departments": "gateway.departments(已落地)",
"providers": "gateway.providers + gateway.provider_models(已落地,models 拆表)",
"users": "gateway.portal_users(已落地)",
"virtual_keys": "gateway.api_keys(已落地,字段需转换)",
"admin_accounts": "gateway.admin_accounts(已落地)",
"audit_logs": "gateway.audit_events(已落地,不迁移无限长正文)",
}
def default_text(column) -> str:
value = column.default
if value is None:
return "—"
argument = value.arg
if callable(argument):
return getattr(argument, "__name__", "callable")
return str(argument).replace("|", "\\|")
def render(legacy_root: Path) -> str:
sys.path.insert(0, str(legacy_root))
db = importlib.import_module("app.db")
tables = [table for name, table in sorted(db.Base.metadata.tables.items()) if name != "audit_log_views"]
lines = [
"# 旧 Python 网关数据字典与 ID 迁移映射",
"",
"> 由 `scripts/export_legacy_dictionary.py` 从旧工程 SQLAlchemy metadata 生成。",
"> `audit_log_views` 是兼容查询投影,不作为独立持久化实体,因此这里统计 38 个实体。",
"",
"## 映射约定",
"",
"- 旧整数主键统一通过 `gateway.legacy_id_mappings` 映射为 UUID,不在新业务表保留双主键。",
"- UUID 使用固定 namespace 的 UUIDv5 生成,输入为 `source_system/entity_type/legacy_id`,重复导入保持幂等。",
"- 外键迁移必须先查映射表;缺失映射时整批失败,不允许写入悬空引用。",
"- 旧密文不能直接复用:Provider、TOTP、内部服务 Key 等敏感字段在导入时解密后用新用途标签重新加密。",
"- `audit_logs` 的完整请求/响应正文不进入新库,只迁移受长度约束的预览与结构化元数据。",
"",
"## 实体去向",
"",
"| 旧表 | 新域/目标 | 状态 |",
"|---|---|---|",
]
for table in tables:
target = CURRENT_TARGETS.get(table.name, "对应 M2M4 领域表")
status = "已建表,待批量导入器" if table.name in CURRENT_TARGETS else "已登记,随对应里程碑建表"
lines.append(f"| `{table.name}` | {target} | {status} |")
lines.extend(["", "## 字段字典", ""])
for table in tables:
lines.extend([
f"### `{table.name}`",
"",
"| 字段 | 旧类型 | 可空 | 默认值 | 键/引用 |",
"|---|---|---:|---|---|",
])
for column in table.columns:
flags = []
if column.primary_key:
flags.append("PK")
if column.unique:
flags.append("UNIQUE")
flags.extend(f"FK → `{fk.target_fullname}`" for fk in column.foreign_keys)
lines.append(
f"| `{column.name}` | `{column.type}` | {'是' if column.nullable else '否'} | "
f"`{default_text(column)}` | {''.join(flags) or '—'} |"
)
lines.append("")
return "\n".join(lines).rstrip() + "\n"
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--legacy-root", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(render(args.legacy_root.resolve()), encoding="utf-8")
if __name__ == "__main__":
main()