backup_before_strategy_refactor.py 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python3
  2. """
  3. 备份 strategy 抽象化重构前的 DB 状态。
  4. 在 DB 内建 bk_20260422_<table> 表,快照以下 6 张表:
  5. strategy / requirement_strategy / strategy_capability
  6. strategy_resource / strategy_knowledge / knowledge
  7. 回滚时用:
  8. DELETE FROM <table>; INSERT INTO <table> SELECT * FROM bk_20260422_<table>;
  9. (或按 version 过滤回滚 knowledge 表)
  10. """
  11. import sys
  12. from pathlib import Path
  13. sys.path.insert(0, str(Path(__file__).parent.parent.parent))
  14. from knowhub.knowhub_db.pg_capability_store import PostgreSQLCapabilityStore
  15. TABLES = [
  16. 'strategy',
  17. 'requirement_strategy',
  18. 'strategy_capability',
  19. 'strategy_resource',
  20. 'strategy_knowledge',
  21. 'knowledge',
  22. ]
  23. BK_PREFIX = 'bk_20260422_'
  24. def main():
  25. s = PostgreSQLCapabilityStore()
  26. cur = s._get_cursor()
  27. try:
  28. print(f'{"="*60}', flush=True)
  29. print(f'Backup strategy refactor prep — 2026-04-22', flush=True)
  30. print(f'{"="*60}\n', flush=True)
  31. results = []
  32. for t in TABLES:
  33. bk = f'{BK_PREFIX}{t}'
  34. # 检查 bk 表是否已存在
  35. cur.execute("""SELECT EXISTS (
  36. SELECT 1 FROM information_schema.tables WHERE table_name=%s)""", (bk,))
  37. exists = cur.fetchone()['exists']
  38. if exists:
  39. cur.execute(f'SELECT COUNT(*) c FROM {bk}')
  40. bk_count = cur.fetchone()['c']
  41. print(f'⚠️ {bk} 已存在({bk_count} 行),跳过 CREATE', flush=True)
  42. # still count source
  43. cur.execute(f'SELECT COUNT(*) c FROM {t}')
  44. src_count = cur.fetchone()['c']
  45. results.append((t, src_count, bk_count, 'existed'))
  46. continue
  47. # 计数
  48. cur.execute(f'SELECT COUNT(*) c FROM {t}')
  49. src_count = cur.fetchone()['c']
  50. print(f'backing up {t} ({src_count} rows) → {bk}', flush=True)
  51. # CREATE TABLE AS (AnalyticDB 的 greenplum 分支支持)
  52. cur.execute(f'CREATE TABLE {bk} AS SELECT * FROM {t}')
  53. # 验证
  54. cur.execute(f'SELECT COUNT(*) c FROM {bk}')
  55. bk_count = cur.fetchone()['c']
  56. ok = '✓' if bk_count == src_count else '❌'
  57. print(f' {ok} {bk}: {bk_count} rows', flush=True)
  58. results.append((t, src_count, bk_count, 'created'))
  59. print(f'\n{"="*60}', flush=True)
  60. print(f'{"Table":32s} {"src":>8s} {"bk":>8s} {"status":>10s}', flush=True)
  61. print(f'{"-"*60}', flush=True)
  62. all_ok = True
  63. for t, src, bk_n, status in results:
  64. ok = '✓' if src == bk_n else '❌'
  65. if src != bk_n: all_ok = False
  66. print(f'{t:32s} {src:>8d} {bk_n:>8d} {status:>10s} {ok}', flush=True)
  67. print(f'{"="*60}', flush=True)
  68. if all_ok:
  69. print('\n✅ Backup complete. All counts match.', flush=True)
  70. else:
  71. print('\n❌ Counts mismatch. INVESTIGATE before proceeding.', flush=True)
  72. # 显示回滚指令
  73. print('\n回滚指令(当需要时):', flush=True)
  74. for t in TABLES:
  75. bk = f'{BK_PREFIX}{t}'
  76. if t == 'knowledge':
  77. print(f" DELETE FROM {t} WHERE version = 'howard_strategy_instance';", flush=True)
  78. print(f" -- 不删 v0 老数据;新 version 删除后相当于恢复到 1046 行状态", flush=True)
  79. else:
  80. print(f' DELETE FROM {t}; INSERT INTO {t} SELECT * FROM {bk};', flush=True)
  81. finally:
  82. cur.close()
  83. s.close()
  84. if __name__ == '__main__':
  85. main()