147 lines
5.4 KiB
Python
147 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
数据库迁移脚本:添加 revision_count, is_latest, original_entry_id 字段
|
|
"""
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# 加载 .env 文件
|
|
env_file = Path(__file__).parent.parent / ".env"
|
|
if env_file.exists():
|
|
with open(env_file) as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if line and not line.startswith("#"):
|
|
key, value = line.split("=", 1)
|
|
os.environ[key.strip()] = value.strip()
|
|
|
|
from psycopg import connect
|
|
|
|
def run_migration():
|
|
try:
|
|
# 从环境变量获取数据库连接信息
|
|
db_password = os.getenv("DB_PASSWORD")
|
|
print(f"📛 连接数据库: {os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}")
|
|
print(f"👤 用户: {os.getenv('DB_USER')}")
|
|
|
|
conn = connect(
|
|
host=os.getenv("DB_HOST"),
|
|
port=int(os.getenv("DB_PORT")),
|
|
dbname=os.getenv("DB_NAME"),
|
|
user=os.getenv("DB_USER"),
|
|
password=db_password if db_password else None,
|
|
)
|
|
|
|
with conn.cursor() as cur:
|
|
# 首先检查字段是否存在
|
|
print("🔄 检查字段是否存在...")
|
|
cur.execute("""
|
|
SELECT column_name FROM information_schema.columns
|
|
WHERE table_name = 'journal_entries'
|
|
AND column_name IN ('is_latest', 'revision_count', 'original_entry_id')
|
|
""")
|
|
existing_columns = {row[0] for row in cur.fetchall()}
|
|
print(f"✓ 已存在的字段: {existing_columns if existing_columns else '无'}")
|
|
|
|
# 添加 is_latest 字段
|
|
if 'is_latest' not in existing_columns:
|
|
print("🔄 添加 is_latest 字段...")
|
|
try:
|
|
cur.execute("""
|
|
ALTER TABLE journal_entries
|
|
ADD COLUMN is_latest BOOLEAN DEFAULT true;
|
|
""")
|
|
conn.commit()
|
|
print("✓ is_latest 字段已添加")
|
|
except Exception as e:
|
|
print(f"✗ 添加失败: {e}")
|
|
conn.rollback()
|
|
else:
|
|
print("✓ is_latest 字段已存在")
|
|
|
|
# 添加 revision_count 字段
|
|
if 'revision_count' not in existing_columns:
|
|
print("🔄 添加 revision_count 字段...")
|
|
try:
|
|
cur.execute("""
|
|
ALTER TABLE journal_entries
|
|
ADD COLUMN revision_count INTEGER DEFAULT 1;
|
|
""")
|
|
conn.commit()
|
|
print("✓ revision_count 字段已添加")
|
|
except Exception as e:
|
|
print(f"✗ 添加失败: {e}")
|
|
conn.rollback()
|
|
else:
|
|
print("✓ revision_count 字段已存在")
|
|
|
|
# 添加 original_entry_id 字段
|
|
if 'original_entry_id' not in existing_columns:
|
|
print("🔄 添加 original_entry_id 字段...")
|
|
try:
|
|
cur.execute("""
|
|
ALTER TABLE journal_entries
|
|
ADD COLUMN original_entry_id INTEGER;
|
|
""")
|
|
conn.commit()
|
|
print("✓ original_entry_id 字段已添加")
|
|
except Exception as e:
|
|
print(f"✗ 添加失败: {e}")
|
|
conn.rollback()
|
|
else:
|
|
print("✓ original_entry_id 字段已存在")
|
|
|
|
# 创建索引
|
|
print("🔄 创建索引...")
|
|
try:
|
|
cur.execute("""
|
|
CREATE INDEX IF NOT EXISTS idx_journal_entries_is_latest
|
|
ON journal_entries(is_latest, entry_date);
|
|
""")
|
|
conn.commit()
|
|
print("✓ idx_journal_entries_is_latest 索引已创建")
|
|
except Exception as e:
|
|
print(f"✗ 创建索引失败: {e}")
|
|
conn.rollback()
|
|
|
|
try:
|
|
cur.execute("""
|
|
CREATE INDEX IF NOT EXISTS idx_journal_entries_original_entry_id
|
|
ON journal_entries(original_entry_id);
|
|
""")
|
|
conn.commit()
|
|
print("✓ idx_journal_entries_original_entry_id 索引已创建")
|
|
except Exception as e:
|
|
print(f"✗ 创建索引失败: {e}")
|
|
conn.rollback()
|
|
|
|
# 验证字段
|
|
print("🔄 验证字段...")
|
|
cur.execute("""
|
|
SELECT column_name, data_type, is_nullable
|
|
FROM information_schema.columns
|
|
WHERE table_name = 'journal_entries'
|
|
AND column_name IN ('is_latest', 'revision_count', 'original_entry_id')
|
|
ORDER BY ordinal_position;
|
|
""")
|
|
|
|
rows = cur.fetchall()
|
|
print("\n📋 数据库字段信息:")
|
|
for row in rows:
|
|
print(f" - {row[0]}: {row[1]} (nullable: {row[2]})")
|
|
|
|
conn.close()
|
|
|
|
print("\n✅ 迁移完成!")
|
|
return 0
|
|
|
|
except Exception as e:
|
|
print(f"\n❌ 迁移失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(run_migration())
|