migrate_external_api.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. """
  2. 数据库迁移脚本:为对外API功能扩展projects表结构
  3. 添加以下字段:
  4. - status: 项目状态 (draft, configuring, ready, in_progress, completed)
  5. - source: 项目来源 (internal, external)
  6. - task_type: 任务类型 (text_classification, image_classification, object_detection, ner)
  7. - updated_at: 更新时间
  8. - external_id: 外部系统的项目ID
  9. 使用方法:
  10. cd backend
  11. python scripts/migrate_external_api.py
  12. """
  13. import sys
  14. import os
  15. # 添加父目录到路径
  16. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  17. from database import get_db_connection, db_config
  18. import logging
  19. logging.basicConfig(level=logging.INFO)
  20. logger = logging.getLogger(__name__)
  21. def check_column_exists(cursor, table: str, column: str) -> bool:
  22. """检查列是否存在"""
  23. if db_config.db_type == 'mysql':
  24. cursor.execute("""
  25. SELECT COUNT(*) as cnt FROM information_schema.columns
  26. WHERE table_schema = %s AND table_name = %s AND column_name = %s
  27. """, (db_config.database, table, column))
  28. row = cursor.fetchone()
  29. return row['cnt'] > 0 if row else False
  30. else:
  31. cursor.execute(f"PRAGMA table_info({table})")
  32. columns = cursor.fetchall()
  33. return any(col['name'] == column for col in columns)
  34. def migrate_mysql():
  35. """MySQL数据库迁移"""
  36. with get_db_connection() as conn:
  37. cursor = conn.cursor()
  38. # 添加 status 字段
  39. if not check_column_exists(cursor, 'projects', 'status'):
  40. logger.info("添加 projects.status 字段...")
  41. cursor.execute("""
  42. ALTER TABLE projects
  43. ADD COLUMN status VARCHAR(20) DEFAULT 'draft'
  44. """)
  45. cursor.execute("CREATE INDEX idx_projects_status ON projects(status)")
  46. logger.info("✓ status 字段添加成功")
  47. else:
  48. logger.info("○ status 字段已存在,跳过")
  49. # 添加 source 字段
  50. if not check_column_exists(cursor, 'projects', 'source'):
  51. logger.info("添加 projects.source 字段...")
  52. cursor.execute("""
  53. ALTER TABLE projects
  54. ADD COLUMN source VARCHAR(20) DEFAULT 'internal'
  55. """)
  56. cursor.execute("CREATE INDEX idx_projects_source ON projects(source)")
  57. logger.info("✓ source 字段添加成功")
  58. else:
  59. logger.info("○ source 字段已存在,跳过")
  60. # 添加 task_type 字段
  61. if not check_column_exists(cursor, 'projects', 'task_type'):
  62. logger.info("添加 projects.task_type 字段...")
  63. cursor.execute("""
  64. ALTER TABLE projects
  65. ADD COLUMN task_type VARCHAR(50)
  66. """)
  67. logger.info("✓ task_type 字段添加成功")
  68. else:
  69. logger.info("○ task_type 字段已存在,跳过")
  70. # 添加 updated_at 字段
  71. if not check_column_exists(cursor, 'projects', 'updated_at'):
  72. logger.info("添加 projects.updated_at 字段...")
  73. cursor.execute("""
  74. ALTER TABLE projects
  75. ADD COLUMN updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  76. """)
  77. logger.info("✓ updated_at 字段添加成功")
  78. else:
  79. logger.info("○ updated_at 字段已存在,跳过")
  80. # 添加 external_id 字段
  81. if not check_column_exists(cursor, 'projects', 'external_id'):
  82. logger.info("添加 projects.external_id 字段...")
  83. cursor.execute("""
  84. ALTER TABLE projects
  85. ADD COLUMN external_id VARCHAR(100)
  86. """)
  87. cursor.execute("CREATE INDEX idx_projects_external_id ON projects(external_id)")
  88. logger.info("✓ external_id 字段添加成功")
  89. else:
  90. logger.info("○ external_id 字段已存在,跳过")
  91. logger.info("MySQL 迁移完成!")
  92. def migrate_sqlite():
  93. """SQLite数据库迁移"""
  94. with get_db_connection() as conn:
  95. cursor = conn.cursor()
  96. # 添加 status 字段
  97. if not check_column_exists(cursor, 'projects', 'status'):
  98. logger.info("添加 projects.status 字段...")
  99. cursor.execute("""
  100. ALTER TABLE projects
  101. ADD COLUMN status TEXT DEFAULT 'draft'
  102. """)
  103. cursor.execute("CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status)")
  104. logger.info("✓ status 字段添加成功")
  105. else:
  106. logger.info("○ status 字段已存在,跳过")
  107. # 添加 source 字段
  108. if not check_column_exists(cursor, 'projects', 'source'):
  109. logger.info("添加 projects.source 字段...")
  110. cursor.execute("""
  111. ALTER TABLE projects
  112. ADD COLUMN source TEXT DEFAULT 'internal'
  113. """)
  114. cursor.execute("CREATE INDEX IF NOT EXISTS idx_projects_source ON projects(source)")
  115. logger.info("✓ source 字段添加成功")
  116. else:
  117. logger.info("○ source 字段已存在,跳过")
  118. # 添加 task_type 字段
  119. if not check_column_exists(cursor, 'projects', 'task_type'):
  120. logger.info("添加 projects.task_type 字段...")
  121. cursor.execute("""
  122. ALTER TABLE projects
  123. ADD COLUMN task_type TEXT
  124. """)
  125. logger.info("✓ task_type 字段添加成功")
  126. else:
  127. logger.info("○ task_type 字段已存在,跳过")
  128. # 添加 updated_at 字段
  129. if not check_column_exists(cursor, 'projects', 'updated_at'):
  130. logger.info("添加 projects.updated_at 字段...")
  131. cursor.execute("""
  132. ALTER TABLE projects
  133. ADD COLUMN updated_at TIMESTAMP
  134. """)
  135. logger.info("✓ updated_at 字段添加成功")
  136. else:
  137. logger.info("○ updated_at 字段已存在,跳过")
  138. # 添加 external_id 字段
  139. if not check_column_exists(cursor, 'projects', 'external_id'):
  140. logger.info("添加 projects.external_id 字段...")
  141. cursor.execute("""
  142. ALTER TABLE projects
  143. ADD COLUMN external_id TEXT
  144. """)
  145. cursor.execute("CREATE INDEX IF NOT EXISTS idx_projects_external_id ON projects(external_id)")
  146. logger.info("✓ external_id 字段添加成功")
  147. else:
  148. logger.info("○ external_id 字段已存在,跳过")
  149. logger.info("SQLite 迁移完成!")
  150. def main():
  151. """执行迁移"""
  152. logger.info(f"开始数据库迁移,数据库类型: {db_config.db_type}")
  153. if db_config.db_type == 'mysql':
  154. migrate_mysql()
  155. else:
  156. migrate_sqlite()
  157. logger.info("=" * 50)
  158. logger.info("迁移完成!新增字段:")
  159. logger.info(" - status: 项目状态 (draft/configuring/ready/in_progress/completed)")
  160. logger.info(" - source: 项目来源 (internal/external)")
  161. logger.info(" - task_type: 任务类型")
  162. logger.info(" - updated_at: 更新时间")
  163. logger.info(" - external_id: 外部系统项目ID")
  164. if __name__ == "__main__":
  165. main()