206 lines
6.8 KiB
Python
Executable File
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) |