run_migrations_054_056.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. """
  2. 执行迁移脚本 054 ~ 056
  3. 054: 为 models_new 表添加 group_name 和 encrypted_api_key 字段
  4. 055: 将 asr_task.result_text 从 VARCHAR(500) 改为 TEXT
  5. 056: 将 asr_task.file_url / result_url 从 VARCHAR(500) 改为 TEXT
  6. 使用方法(在项目根目录执行):
  7. python backend/migrations/run_migrations_054_056.py
  8. 或在 backend/ 目录下执行:
  9. python migrations/run_migrations_054_056.py
  10. """
  11. import sys
  12. import os
  13. from pathlib import Path
  14. # 将 backend/ 加入 Python 路径,以便复用 DATABASE_URL
  15. project_root = Path(__file__).parent.parent
  16. sys.path.insert(0, str(project_root))
  17. import psycopg2
  18. from app.database import DATABASE_URL
  19. # ==================== 迁移文件列表(按顺序执行)====================
  20. MIGRATIONS_DIR = Path(__file__).parent
  21. MIGRATION_FILES = [
  22. "054_add_group_name_and_encrypted_api_key.sql",
  23. "055_alter_asr_task_result_text_to_text.sql",
  24. "056_alter_asr_task_url_fields_to_text.sql",
  25. ]
  26. def get_dsn(database_url: str) -> str:
  27. """将 SQLAlchemy URL 转换为 psycopg2 DSN"""
  28. # 兼容 postgresql+psycopg2:// 和 postgresql:// 两种格式
  29. url = database_url.replace("postgresql+psycopg2://", "postgresql://")
  30. return url
  31. def run_sql_file(conn, filepath: Path) -> None:
  32. """执行单个 SQL 文件"""
  33. sql = filepath.read_text(encoding="utf-8")
  34. with conn.cursor() as cur:
  35. cur.execute(sql)
  36. def main():
  37. print("=" * 60)
  38. print("迁移执行脚本:054 ~ 056")
  39. print("=" * 60)
  40. print()
  41. # 列出将要执行的文件
  42. print("将执行以下迁移文件:")
  43. for name in MIGRATION_FILES:
  44. path = MIGRATIONS_DIR / name
  45. status = "✓ 存在" if path.exists() else "✗ 文件不存在!"
  46. print(f" [{status}] {name}")
  47. print()
  48. # 检查文件是否都存在
  49. missing = [n for n in MIGRATION_FILES if not (MIGRATIONS_DIR / n).exists()]
  50. if missing:
  51. print("错误:以下文件不存在,请检查路径:")
  52. for n in missing:
  53. print(f" {MIGRATIONS_DIR / n}")
  54. sys.exit(1)
  55. confirm = input("确认执行以上迁移?(yes/no): ").strip().lower()
  56. if confirm != "yes":
  57. print("已取消。")
  58. sys.exit(0)
  59. print()
  60. # 连接数据库
  61. dsn = get_dsn(DATABASE_URL)
  62. print("正在连接数据库...")
  63. try:
  64. conn = psycopg2.connect(dsn)
  65. conn.autocommit = False
  66. print("✓ 数据库连接成功")
  67. except Exception as e:
  68. print(f"✗ 数据库连接失败:{e}")
  69. sys.exit(1)
  70. print()
  71. # 逐个执行迁移
  72. try:
  73. for name in MIGRATION_FILES:
  74. path = MIGRATIONS_DIR / name
  75. print(f"执行:{name} ...")
  76. try:
  77. run_sql_file(conn, path)
  78. print(f" ✓ 成功")
  79. except Exception as e:
  80. conn.rollback()
  81. print(f" ✗ 失败:{e}")
  82. print()
  83. print("已回滚所有未提交的变更。")
  84. sys.exit(1)
  85. conn.commit()
  86. print()
  87. print("=" * 60)
  88. print("✓ 全部迁移执行成功,已提交。")
  89. print("=" * 60)
  90. finally:
  91. conn.close()
  92. if __name__ == "__main__":
  93. main()