reset_db.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. 数据库重置脚本
  5. 这个脚本用于清理数据库并准备新的迁移
  6. """
  7. import os
  8. import sys
  9. from sqlalchemy import text, inspect, create_engine
  10. import re
  11. import logging
  12. from sqlalchemy.ext.declarative import declarative_base
  13. # 配置日志
  14. logging.basicConfig(level=logging.INFO)
  15. logger = logging.getLogger(__name__)
  16. # 加载环境变量配置
  17. from dotenv import load_dotenv
  18. load_dotenv("config.env")
  19. # 从环境变量获取数据库连接信息,如果没有则使用默认值
  20. DB_USER = os.getenv("DB_USER", "postgres")
  21. DB_PASSWORD = os.getenv("DB_PASSWORD", "123456789Qq")
  22. DB_HOST = os.getenv("DB_HOST", "localhost")
  23. DB_PORT = os.getenv("DB_PORT", "5432")
  24. DB_NAME = os.getenv("DB_NAME", "soilgd")
  25. print(f"连接到数据库: {DB_USER}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
  26. # 构建数据库连接URL
  27. SQLALCHEMY_DATABASE_URL = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
  28. # 创建数据库引擎
  29. engine = create_engine(
  30. SQLALCHEMY_DATABASE_URL,
  31. pool_size=5,
  32. max_overflow=10,
  33. pool_timeout=30,
  34. pool_recycle=1800
  35. )
  36. # 要删除的表列表(按顺序)
  37. TABLES_TO_DROP = [
  38. 'fifty_thousand_survey_data',
  39. 'surveydata',
  40. 'unit_ceil',
  41. 'raster_table',
  42. 'Conventional_land_information',
  43. 'Point_information',
  44. 'alembic_version'
  45. ]
  46. # 不应该删除的系统表
  47. SYSTEM_TABLES = [
  48. 'spatial_ref_sys', # PostGIS系统表
  49. 'geography_columns',
  50. 'geometry_columns',
  51. 'raster_columns',
  52. 'raster_overviews'
  53. ]
  54. def get_all_tables():
  55. """获取数据库中所有表的名称(排除系统表)"""
  56. inspector = inspect(engine)
  57. tables = inspector.get_table_names()
  58. # 排除系统表
  59. return [t for t in tables if t not in SYSTEM_TABLES]
  60. def get_table_case_insensitive(table_name):
  61. """不区分大小写查找表名"""
  62. all_tables = get_all_tables()
  63. return [t for t in all_tables if t.lower() == table_name.lower()]
  64. def reset_database():
  65. """重置数据库,删除所有表"""
  66. print("\n==== 开始重置数据库 ====")
  67. # 获取删除前的所有表
  68. before_tables = get_all_tables()
  69. print(f"\n删除前的表: {before_tables}")
  70. try:
  71. for table_name in TABLES_TO_DROP:
  72. # 查找该表在数据库中的实际名称(考虑大小写)
  73. actual_tables = get_table_case_insensitive(table_name)
  74. if not actual_tables:
  75. print(f"表 '{table_name}' 不存在,跳过")
  76. continue
  77. for actual_table in actual_tables:
  78. try:
  79. with engine.begin() as conn:
  80. print(f"\n尝试删除表 '{actual_table}'...")
  81. # 使用双引号包裹表名以保持大小写
  82. sql = f'DROP TABLE IF EXISTS "{actual_table}" CASCADE'
  83. conn.execute(text(sql))
  84. print(f"执行SQL: {sql}")
  85. # 验证表是否已删除
  86. check_tables = get_table_case_insensitive(actual_table)
  87. if not check_tables:
  88. print(f"✓ 表 '{actual_table}' 已成功删除")
  89. else:
  90. print(f"✗ 表 '{actual_table}' 删除失败,仍然存在")
  91. except Exception as e:
  92. print(f"删除表 '{actual_table}' 时出错: {str(e)}")
  93. # 获取删除后的所有表
  94. after_tables = get_all_tables()
  95. print(f"\n==== 删除操作完成 ====")
  96. print(f"删除前的表: {len(before_tables)}个 - {before_tables}")
  97. print(f"删除后的表: {len(after_tables)}个 - {after_tables}")
  98. # 找出仍然存在的表
  99. remaining_tables = []
  100. for table in before_tables:
  101. # 检查表是否应该被删除
  102. should_be_deleted = any(re.match(f"^{t}$", table, re.IGNORECASE) for t in TABLES_TO_DROP)
  103. if should_be_deleted and table in after_tables:
  104. remaining_tables.append(table)
  105. if remaining_tables:
  106. print(f"\n警告:以下表应该被删除但仍然存在: {remaining_tables}")
  107. print("这可能是由于权限问题或者表依赖关系导致")
  108. else:
  109. print("\n所有目标表已成功删除")
  110. print("\n==== 数据库重置完成 ====")
  111. return 0
  112. except Exception as e:
  113. print(f"\n重置数据库时出错: {str(e)}")
  114. return 1
  115. if __name__ == '__main__':
  116. sys.exit(reset_database())