改用API驗證
This commit is contained in:
193
migrations/fix_translation_cache.py
Normal file
193
migrations/fix_translation_cache.py
Normal file
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
修復 dt_translation_cache 資料表結構
|
||||
|
||||
問題:資料表欄位名稱與模型定義不一致
|
||||
- content_hash → source_text_hash
|
||||
- source_lang → source_language
|
||||
- target_lang → target_language
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from app import create_app, db
|
||||
from sqlalchemy import text
|
||||
|
||||
|
||||
def run_migration():
|
||||
app = create_app()
|
||||
|
||||
with app.app_context():
|
||||
print("=" * 60)
|
||||
print("修復 dt_translation_cache 資料表結構")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
# 1. 檢查當前結構
|
||||
print("\n[1/6] 檢查當前資料表結構...")
|
||||
result = db.session.execute(text('SHOW COLUMNS FROM dt_translation_cache'))
|
||||
current_columns = {row[0]: row for row in result}
|
||||
print(f" ✓ 當前欄位: {', '.join(current_columns.keys())}")
|
||||
|
||||
# 2. 備份資料
|
||||
print("\n[2/6] 備份現有資料...")
|
||||
db.session.execute(text('''
|
||||
CREATE TABLE IF NOT EXISTS dt_translation_cache_backup_20251001
|
||||
AS SELECT * FROM dt_translation_cache
|
||||
'''))
|
||||
db.session.commit()
|
||||
|
||||
backup_count = db.session.execute(
|
||||
text('SELECT COUNT(*) FROM dt_translation_cache_backup_20251001')
|
||||
).scalar()
|
||||
print(f" ✓ 已備份 {backup_count} 筆記錄")
|
||||
|
||||
# 3. 重新命名欄位:content_hash → source_text_hash
|
||||
if 'content_hash' in current_columns and 'source_text_hash' not in current_columns:
|
||||
print("\n[3/6] 重新命名 content_hash → source_text_hash...")
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
CHANGE COLUMN content_hash source_text_hash VARCHAR(64) NOT NULL COMMENT '來源文字hash'
|
||||
'''))
|
||||
db.session.commit()
|
||||
print(" ✓ 已重新命名")
|
||||
else:
|
||||
print("\n[3/6] 跳過(已經是 source_text_hash)")
|
||||
|
||||
# 4. 重新命名欄位:source_lang → source_language
|
||||
if 'source_lang' in current_columns and 'source_language' not in current_columns:
|
||||
print("\n[4/6] 重新命名 source_lang → source_language...")
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
CHANGE COLUMN source_lang source_language VARCHAR(50) NOT NULL COMMENT '來源語言'
|
||||
'''))
|
||||
db.session.commit()
|
||||
print(" ✓ 已重新命名")
|
||||
else:
|
||||
print("\n[4/6] 跳過(已經是 source_language)")
|
||||
|
||||
# 5. 重新命名欄位:target_lang → target_language
|
||||
if 'target_lang' in current_columns and 'target_language' not in current_columns:
|
||||
print("\n[5/6] 重新命名 target_lang → target_language...")
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
CHANGE COLUMN target_lang target_language VARCHAR(50) NOT NULL COMMENT '目標語言'
|
||||
'''))
|
||||
db.session.commit()
|
||||
print(" ✓ 已重新命名")
|
||||
else:
|
||||
print("\n[5/6] 跳過(已經是 target_language)")
|
||||
|
||||
# 6. 刪除不需要的欄位
|
||||
print("\n[6/6] 清理多餘欄位...")
|
||||
|
||||
# 檢查並刪除 quality_score
|
||||
if 'quality_score' in current_columns:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
DROP COLUMN quality_score
|
||||
'''))
|
||||
print(" ✓ 已刪除 quality_score")
|
||||
|
||||
# 檢查並刪除 hit_count
|
||||
if 'hit_count' in current_columns:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
DROP COLUMN hit_count
|
||||
'''))
|
||||
print(" ✓ 已刪除 hit_count")
|
||||
|
||||
# 檢查並刪除 last_used_at
|
||||
if 'last_used_at' in current_columns:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
DROP COLUMN last_used_at
|
||||
'''))
|
||||
print(" ✓ 已刪除 last_used_at")
|
||||
|
||||
db.session.commit()
|
||||
|
||||
# 7. 重建索引和約束
|
||||
print("\n[7/7] 重建索引和約束...")
|
||||
|
||||
# 先刪除舊的唯一約束(如果存在)
|
||||
try:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
DROP INDEX idx_content_hash
|
||||
'''))
|
||||
print(" ✓ 已刪除舊索引 idx_content_hash")
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
DROP INDEX idx_source_lang_target_lang
|
||||
'''))
|
||||
print(" ✓ 已刪除舊索引 idx_source_lang_target_lang")
|
||||
except:
|
||||
pass
|
||||
|
||||
# 建立新的唯一約束
|
||||
try:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
ADD UNIQUE KEY uk_cache (source_text_hash, source_language, target_language)
|
||||
'''))
|
||||
print(" ✓ 已建立唯一約束 uk_cache")
|
||||
except Exception as e:
|
||||
if 'Duplicate' not in str(e):
|
||||
print(f" ⚠ 約束建立警告: {str(e)}")
|
||||
|
||||
# 建立語言索引
|
||||
try:
|
||||
db.session.execute(text('''
|
||||
ALTER TABLE dt_translation_cache
|
||||
ADD INDEX idx_languages (source_language, target_language)
|
||||
'''))
|
||||
print(" ✓ 已建立索引 idx_languages")
|
||||
except Exception as e:
|
||||
if 'Duplicate' not in str(e):
|
||||
print(f" ⚠ 索引建立警告: {str(e)}")
|
||||
|
||||
db.session.commit()
|
||||
|
||||
# 驗證最終結構
|
||||
print("\n" + "=" * 60)
|
||||
print("驗證最終資料表結構")
|
||||
print("=" * 60)
|
||||
|
||||
result = db.session.execute(text('SHOW COLUMNS FROM dt_translation_cache'))
|
||||
final_columns = list(result)
|
||||
|
||||
print(f"\n最終欄位列表 (共 {len(final_columns)} 個):")
|
||||
for col in final_columns:
|
||||
print(f" - {col[0]:30} {col[1]:30} NULL={col[2]}")
|
||||
|
||||
# 顯示索引
|
||||
print("\n索引:")
|
||||
result = db.session.execute(text('SHOW INDEX FROM dt_translation_cache'))
|
||||
for idx in result:
|
||||
print(f" - {idx[2]:30} -> {idx[4]}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ Migration 執行完成!")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
print(f"\n❌ Migration 失敗: {str(e)}")
|
||||
print("\n可以使用備份表還原資料:")
|
||||
print(" DROP TABLE dt_translation_cache;")
|
||||
print(" CREATE TABLE dt_translation_cache AS SELECT * FROM dt_translation_cache_backup_20251001;")
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_migration()
|
Reference in New Issue
Block a user