Files
petpicturequeue/migrate_session_changes.py
2025-08-07 18:18:36 -04:00

206 lines
6.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Database migration script for session changes
Handles all database schema changes made during this session:
1. Adding likes column (if not exists)
2. Ensuring description column exists
3. Updating any existing records to have default values
This script is idempotent - can be run multiple times safely.
"""
import sqlite3
import sys
import os
from datetime import datetime
def get_database_path():
"""Get the correct database path"""
if os.path.exists("pet_pictures.db"):
return "pet_pictures.db"
elif os.path.exists("app/pet_pictures.db"):
return "app/pet_pictures.db"
else:
return "pet_pictures.db" # Default path
def check_column_exists(cursor, table_name, column_name):
"""Check if a column exists in a table"""
cursor.execute(f"PRAGMA table_info({table_name})")
columns = [column[1] for column in cursor.fetchall()]
return column_name in columns
def migrate_database():
"""Main migration function"""
db_path = get_database_path()
print(f"Using database: {db_path}")
try:
# Connect to the database
db = sqlite3.connect(db_path)
cursor = db.cursor()
print("Starting database migration...")
# Check if pet_pictures table exists
cursor.execute("""
SELECT name FROM sqlite_master
WHERE type='table' AND name='pet_pictures'
""")
if not cursor.fetchone():
print("pet_pictures table doesn't exist. Creating it...")
cursor.execute("""
CREATE TABLE pet_pictures (
id INTEGER PRIMARY KEY AUTOINCREMENT,
filename TEXT NOT NULL,
subscriber_name TEXT NOT NULL,
description TEXT,
uploaded_at TIMESTAMP NOT NULL,
posted BOOLEAN DEFAULT 0,
likes INTEGER DEFAULT 0
)
""")
db.commit()
print("✓ Created pet_pictures table with all columns")
return
migrations_applied = 0
# Migration 1: Add description column if it doesn't exist
if not check_column_exists(cursor, 'pet_pictures', 'description'):
print("Adding description column...")
cursor.execute("ALTER TABLE pet_pictures ADD COLUMN description TEXT")
db.commit()
print("✓ Added description column")
migrations_applied += 1
else:
print("• Description column already exists")
# Migration 2: Add likes column if it doesn't exist
if not check_column_exists(cursor, 'pet_pictures', 'likes'):
print("Adding likes column...")
cursor.execute("ALTER TABLE pet_pictures ADD COLUMN likes INTEGER DEFAULT 0")
# Update existing records to have 0 likes
cursor.execute("UPDATE pet_pictures SET likes = 0 WHERE likes IS NULL")
db.commit()
print("✓ Added likes column and initialized existing records")
migrations_applied += 1
else:
print("• Likes column already exists")
# Migration 3: Ensure posted column exists and has correct type
if not check_column_exists(cursor, 'pet_pictures', 'posted'):
print("Adding posted column...")
cursor.execute("ALTER TABLE pet_pictures ADD COLUMN posted BOOLEAN DEFAULT 0")
db.commit()
print("✓ Added posted column")
migrations_applied += 1
else:
print("• Posted column already exists")
# Migration 4: Clean up any NULL values in critical columns
print("Cleaning up NULL values...")
cursor.execute("""
UPDATE pet_pictures
SET likes = 0
WHERE likes IS NULL
""")
cursor.execute("""
UPDATE pet_pictures
SET posted = 0
WHERE posted IS NULL
""")
cursor.execute("""
UPDATE pet_pictures
SET description = ''
WHERE description IS NULL
""")
db.commit()
print("✓ Cleaned up NULL values")
# Verify final schema
cursor.execute("PRAGMA table_info(pet_pictures)")
columns = cursor.fetchall()
print("\nFinal table schema:")
for column in columns:
print(f" {column[1]} {column[2]} {'NOT NULL' if column[3] else 'NULL'} {f'DEFAULT {column[4]}' if column[4] else ''}")
# Get record count
cursor.execute("SELECT COUNT(*) FROM pet_pictures")
record_count = cursor.fetchone()[0]
print(f"\nMigration completed successfully!")
print(f"Applied {migrations_applied} migrations")
print(f"Database contains {record_count} pet pictures")
# Log migration
print(f"Migration completed at: {datetime.now().isoformat()}")
except sqlite3.Error as e:
print(f"❌ Database error occurred: {e}")
sys.exit(1)
except Exception as e:
print(f"❌ An unexpected error occurred: {e}")
sys.exit(1)
finally:
if 'db' in locals():
db.close()
def verify_migration():
"""Verify that the migration was successful"""
db_path = get_database_path()
try:
db = sqlite3.connect(db_path)
cursor = db.cursor()
# Check all required columns exist
required_columns = ['id', 'filename', 'subscriber_name', 'description', 'uploaded_at', 'posted', 'likes']
cursor.execute("PRAGMA table_info(pet_pictures)")
existing_columns = [column[1] for column in cursor.fetchall()]
missing_columns = set(required_columns) - set(existing_columns)
if missing_columns:
print(f"❌ Verification failed: Missing columns: {missing_columns}")
return False
print("✅ Verification successful: All required columns present")
return True
except sqlite3.Error as e:
print(f"❌ Verification failed with database error: {e}")
return False
finally:
if 'db' in locals():
db.close()
if __name__ == "__main__":
print("=" * 60)
print("Pet Picture Database Migration Script")
print("Session Changes: Adding likes system and ensuring schema consistency")
print("=" * 60)
# Run migration
migrate_database()
print("\n" + "=" * 60)
print("Verifying migration...")
# Verify migration
if verify_migration():
print("🎉 Migration completed successfully!")
else:
print("⚠️ Migration verification failed")
sys.exit(1)
print("=" * 60)