173 lines
6.4 KiB
Python
173 lines
6.4 KiB
Python
#!/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()
|