| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- """
- 百宝箱数据库迁移脚本
- 执行百宝箱相关的SQL迁移文件
- 从.env文件读取数据库连接信息
- """
- import os
- import sys
- from pathlib import Path
- from dotenv import load_dotenv
- import psycopg2
- from psycopg2 import sql
- # 添加项目根目录到路径
- sys.path.insert(0, str(Path(__file__).parent.parent))
- # 加载环境变量
- env_path = Path(__file__).parent.parent / '.env'
- load_dotenv(dotenv_path=env_path)
- def get_db_connection():
- """从环境变量获取数据库连接"""
- try:
- conn = psycopg2.connect(
- host=os.getenv("DB_HOST", "localhost"),
- port=int(os.getenv("DB_PORT", "5432")),
- database=os.getenv("DB_NAME", "aigcspace"),
- user=os.getenv("DB_USER", "postgres"),
- password=os.getenv("DB_PASSWORD", "")
- )
- return conn
- except Exception as e:
- print(f"❌ 数据库连接失败: {e}")
- sys.exit(1)
- def execute_sql_file(cursor, file_path: Path):
- """执行SQL文件"""
- try:
- with open(file_path, 'r', encoding='utf-8') as f:
- sql_content = f.read()
-
- # 执行SQL
- cursor.execute(sql_content)
- print(f"✓ 执行成功: {file_path.name}")
- return True
- except Exception as e:
- print(f"❌ 执行失败: {file_path.name}")
- print(f" 错误信息: {e}")
- return False
- def verify_data(cursor):
- """验证数据是否正确插入"""
- try:
- # 查询总数
- cursor.execute("SELECT COUNT(*) FROM aigcspace.toolbox_apps;")
- total = cursor.fetchone()[0]
- print(f"\n📊 数据验证:")
- print(f" 总应用数: {total}")
-
- # 按分类统计
- cursor.execute("""
- SELECT category, COUNT(*) as count
- FROM aigcspace.toolbox_apps
- WHERE status = 'active'
- GROUP BY category
- ORDER BY count DESC;
- """)
-
- print(f"\n 分类分布:")
- for row in cursor.fetchall():
- print(f" - {row[0]}: {row[1]}个")
-
- # 显示所有应用
- cursor.execute("""
- SELECT app_key, name, category, is_new, version
- FROM aigcspace.toolbox_apps
- ORDER BY sort_order DESC;
- """)
-
- print(f"\n 应用列表:")
- for row in cursor.fetchall():
- app_key, name, category, is_new, version = row
- new_tag = " [New]" if is_new else ""
- version_tag = f" ({version})" if version else ""
- print(f" - {name}{new_tag}{version_tag} - {category}")
-
- return True
- except Exception as e:
- print(f"❌ 数据验证失败: {e}")
- return False
- def main():
- """主函数"""
- print("=" * 60)
- print("百宝箱数据库迁移脚本")
- print("=" * 60)
-
- # 获取迁移文件路径
- migrations_dir = Path(__file__).parent.parent / 'migrations'
- migration_files = [
- migrations_dir / '034_create_toolbox_apps_table.sql',
- migrations_dir / '035_init_toolbox_apps_data.sql'
- ]
-
- # 检查文件是否存在
- for file_path in migration_files:
- if not file_path.exists():
- print(f"❌ 迁移文件不存在: {file_path}")
- sys.exit(1)
-
- print(f"\n📁 找到 {len(migration_files)} 个迁移文件")
- for file_path in migration_files:
- print(f" - {file_path.name}")
-
- # 连接数据库
- print(f"\n🔌 连接数据库...")
- print(f" Host: {os.getenv('DB_HOST', 'localhost')}")
- print(f" Port: {os.getenv('DB_PORT', '5432')}")
- print(f" Database: {os.getenv('DB_NAME', 'aigcspace')}")
- print(f" User: {os.getenv('DB_USER', 'postgres')}")
-
- conn = get_db_connection()
- cursor = conn.cursor()
-
- print(f"✓ 数据库连接成功")
-
- # 执行迁移文件
- print(f"\n🚀 开始执行迁移...")
- success_count = 0
-
- for file_path in migration_files:
- if execute_sql_file(cursor, file_path):
- success_count += 1
- else:
- # 如果执行失败,回滚并退出
- conn.rollback()
- cursor.close()
- conn.close()
- print(f"\n❌ 迁移失败,已回滚所有更改")
- sys.exit(1)
-
- # 提交事务
- conn.commit()
- print(f"\n✓ 所有迁移执行成功 ({success_count}/{len(migration_files)})")
-
- # 验证数据
- verify_data(cursor)
-
- # 关闭连接
- cursor.close()
- conn.close()
-
- print(f"\n" + "=" * 60)
- print("✅ 百宝箱数据库迁移完成!")
- print("=" * 60)
- print(f"\n💡 下一步:")
- print(f" 1. 启动后端服务: cd backend && python main.py")
- print(f" 2. 启动前端服务: cd frontend && npm run dev")
- print(f" 3. 访问页面: http://localhost:5173/toolbox")
- print()
- if __name__ == "__main__":
- try:
- main()
- except KeyboardInterrupt:
- print(f"\n\n⚠️ 用户中断执行")
- sys.exit(1)
- except Exception as e:
- print(f"\n\n❌ 执行过程中发生错误: {e}")
- import traceback
- traceback.print_exc()
- sys.exit(1)
|