fix: add automatic migration system to db_init.py
Added migration tracking and execution to db_init.py: - Created schema_migrations table to track applied migrations - Added run_migrations() to automatically apply pending SQL files - Migrations from backend/migrations/*.sql are now applied on startup This fixes the missing email verification columns (migration 003). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9fa60434c1
commit
22651647cb
|
|
@ -91,6 +91,107 @@ def get_profile_count():
|
||||||
print(f"Error getting profile count: {e}")
|
print(f"Error getting profile count: {e}")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
def ensure_migration_table():
|
||||||
|
"""Create migration tracking table if it doesn't exist."""
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
filename VARCHAR(255) UNIQUE NOT NULL,
|
||||||
|
applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating migration table: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_applied_migrations():
|
||||||
|
"""Get list of already applied migrations."""
|
||||||
|
try:
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("SELECT filename FROM schema_migrations ORDER BY filename")
|
||||||
|
migrations = [row[0] for row in cur.fetchall()]
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
return migrations
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error getting applied migrations: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def apply_migration(filepath, filename):
|
||||||
|
"""Apply a single migration file."""
|
||||||
|
try:
|
||||||
|
with open(filepath, 'r') as f:
|
||||||
|
migration_sql = f.read()
|
||||||
|
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
# Execute migration
|
||||||
|
cur.execute(migration_sql)
|
||||||
|
|
||||||
|
# Record migration
|
||||||
|
cur.execute(
|
||||||
|
"INSERT INTO schema_migrations (filename) VALUES (%s)",
|
||||||
|
(filename,)
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
print(f" ✓ Applied: {filename}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Failed to apply {filename}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def run_migrations(migrations_dir="/app/migrations"):
|
||||||
|
"""Run all pending migrations."""
|
||||||
|
import glob
|
||||||
|
|
||||||
|
if not os.path.exists(migrations_dir):
|
||||||
|
print("✓ No migrations directory found")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Ensure migration tracking table exists
|
||||||
|
if not ensure_migration_table():
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Get already applied migrations
|
||||||
|
applied = get_applied_migrations()
|
||||||
|
|
||||||
|
# Get all migration files
|
||||||
|
migration_files = sorted(glob.glob(os.path.join(migrations_dir, "*.sql")))
|
||||||
|
|
||||||
|
if not migration_files:
|
||||||
|
print("✓ No migration files found")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Apply pending migrations
|
||||||
|
pending = []
|
||||||
|
for filepath in migration_files:
|
||||||
|
filename = os.path.basename(filepath)
|
||||||
|
if filename not in applied:
|
||||||
|
pending.append((filepath, filename))
|
||||||
|
|
||||||
|
if not pending:
|
||||||
|
print(f"✓ All {len(applied)} migrations already applied")
|
||||||
|
return True
|
||||||
|
|
||||||
|
print(f" Found {len(pending)} pending migration(s)...")
|
||||||
|
for filepath, filename in pending:
|
||||||
|
if not apply_migration(filepath, filename):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("═══════════════════════════════════════════════════════════")
|
print("═══════════════════════════════════════════════════════════")
|
||||||
print("MITAI JINKENDO - Database Initialization (v9c)")
|
print("MITAI JINKENDO - Database Initialization (v9c)")
|
||||||
|
|
@ -109,6 +210,12 @@ if __name__ == "__main__":
|
||||||
else:
|
else:
|
||||||
print("✓ Schema already exists")
|
print("✓ Schema already exists")
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
print("\nRunning database migrations...")
|
||||||
|
if not run_migrations():
|
||||||
|
print("✗ Migration failed")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Check for migration
|
# Check for migration
|
||||||
print("\nChecking for SQLite data migration...")
|
print("\nChecking for SQLite data migration...")
|
||||||
sqlite_db = "/app/data/bodytrack.db"
|
sqlite_db = "/app/data/bodytrack.db"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user