#!/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)