#!/usr/bin/env python3 """ 修复数据库中的版本链接错误和is_latest标记 """ import psycopg from datetime import datetime try: conn = psycopg.connect( host='192.168.0.61', port=55432, dbname='njts_acct', user='njts_app', password='njts_app2025' ) with conn.cursor() as cur: print("=" * 70) print("【数据库修复:版本链接和is_latest标记】") print("=" * 70) # 第一步:识别【修正後】記錄,並確保其 original_entry_id 指向真正的原始版本 print("\n【步驟 1】修復 original_entry_id 鏈接...") # 查找所有【修正後】的記錄 cur.execute(""" SELECT journal_entry_id, description, original_entry_id FROM journal_entries WHERE description LIKE '%【修正後】%' AND is_deleted = false ORDER BY journal_entry_id """) corrupted_count = 0 for row in cur.fetchall(): je_id, desc, orig_id = row # 如果original_entry_id指向另一个【修正後】記錄,就往上追溯 if orig_id: cur.execute(""" SELECT original_entry_id, description FROM journal_entries WHERE journal_entry_id = %s """, (orig_id,)) parent_row = cur.fetchone() if parent_row: parent_orig_id, parent_desc = parent_row # 如果指向的記錄也是【修正後】,說明有鏈接錯誤 if '【修正後】' in parent_desc and parent_orig_id and parent_orig_id != orig_id: print(f"\n修復 ID={je_id}: {desc[:30]}") print(f" 舊的 original_entry_id: {orig_id} (也是【修正後】記錄)") print(f" 新的 original_entry_id: {parent_orig_id}") cur.execute(""" UPDATE journal_entries SET original_entry_id = %s WHERE journal_entry_id = %s """, (parent_orig_id, je_id)) corrupted_count += 1 conn.commit() if corrupted_count > 0: print(f"\n✓ 已修復 {corrupted_count} 條記錄的 original_entry_id") else: print("✓ 沒有發現 original_entry_id 鏈接錯誤") # 第二步:重新設置 is_latest 標記 print("\n【步驟 2】重新設置 is_latest 標記...") # 清空所有 is_latest 標記 cur.execute("UPDATE journal_entries SET is_latest = false WHERE is_deleted = false") conn.commit() # 對每條版本鏈,只有最新版本的 is_latest = true cur.execute(""" SELECT DISTINCT original_entry_id FROM journal_entries WHERE original_entry_id IS NOT NULL AND is_deleted = false UNION SELECT DISTINCT journal_entry_id FROM journal_entries WHERE original_entry_id IS NULL AND is_deleted = false AND journal_entry_id NOT IN ( SELECT original_entry_id FROM journal_entries WHERE original_entry_id IS NOT NULL ) """) chain_heads = [row[0] for row in cur.fetchall()] updated_count = 0 for chain_head in chain_heads: # 找出這條鏈中最新的版本(根據 created_at 或 journal_entry_id) cur.execute(""" SELECT journal_entry_id FROM journal_entries WHERE (journal_entry_id = %s OR original_entry_id = %s) AND is_deleted = false ORDER BY journal_entry_id DESC LIMIT 1 """, (chain_head, chain_head)) latest = cur.fetchone() if latest: latest_id = latest[0] cur.execute(""" UPDATE journal_entries SET is_latest = true WHERE journal_entry_id = %s """, (latest_id,)) updated_count += 1 conn.commit() print(f"✓ 已設置 {updated_count} 條最新版本的 is_latest = true") # 第三步:驗證 print("\n【步驟 3】驗證修復結果...") print("-" * 70) # 檢查是否有多個 is_latest=true 在同一個鏈中 cur.execute(""" SELECT original_entry_id, COUNT(*) as cnt FROM journal_entries WHERE is_latest = true AND is_deleted = false AND original_entry_id IS NOT NULL GROUP BY original_entry_id HAVING COUNT(*) > 1 """) duplicates = cur.fetchall() if duplicates: print("⚠️ 警告:發現重複的 is_latest=true") for dup in duplicates: print(f" original_entry_id={dup[0]}: {dup[1]} 條記錄") else: print("✓ 沒有發現重複的 is_latest=true") # 統計各狀態的記錄數 cur.execute(""" SELECT is_latest, COUNT(*) as cnt FROM journal_entries WHERE is_deleted = false GROUP BY is_latest """) stats = cur.fetchall() print("\n記錄統計:") for stat in stats: print(f" is_latest={stat[0]}: {stat[1]} 條") # 驗證【test元】的鏈 print("\n【test 元】鏈的驗證:") print("-" * 70) cur.execute(""" SELECT journal_entry_id, description, is_latest, revision_count, original_entry_id FROM journal_entries WHERE (description LIKE '%test%' AND is_deleted = false) AND journal_entry_id >= 410 ORDER BY journal_entry_id """) test_records = cur.fetchall() for rec in test_records: je_id, desc, is_latest, rev_cnt, orig_id = rec status = "✓" if is_latest else " " print(f"{status} ID={je_id:3d} rev={rev_cnt} orig_id={str(orig_id):>6s} {desc[:40]}") conn.close() print("\n" + "=" * 70) print("修復完成!") print("=" * 70) except Exception as e: print(f'錯誤: {e}') import traceback traceback.print_exc()