163 lines
5.8 KiB
Python
163 lines
5.8 KiB
Python
"""
|
|
Migration script from SQLite to PostgreSQL.
|
|
|
|
This script migrates data from the existing SQLite database to PostgreSQL.
|
|
|
|
Usage:
|
|
python scripts/migrate_to_postgres.py
|
|
|
|
Prerequisites:
|
|
- PostgreSQL database must be running
|
|
- DATABASE_URL environment variable must point to PostgreSQL
|
|
- SQLite database must exist at data/habitforge.db
|
|
"""
|
|
import os
|
|
import sys
|
|
from datetime import datetime
|
|
|
|
# Add parent directory to path
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from sqlalchemy import create_engine, text
|
|
from sqlalchemy.orm import sessionmaker
|
|
from backend import models
|
|
from backend.database import Base, SessionLocal as SQLiteSessionLocal
|
|
|
|
# PostgreSQL connection
|
|
POSTGRES_URL = os.getenv("DATABASE_URL", "postgresql://habitforge:habitforge@localhost:5432/habitforge")
|
|
|
|
def migrate_data():
|
|
"""Migrate data from SQLite to PostgreSQL."""
|
|
print("Starting migration from SQLite to PostgreSQL...")
|
|
|
|
# Create PostgreSQL engine
|
|
postgres_engine = create_engine(POSTGRES_URL)
|
|
PostgresSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=postgres_engine)
|
|
|
|
# Create tables in PostgreSQL
|
|
print("Creating tables in PostgreSQL...")
|
|
Base.metadata.create_all(bind=postgres_engine)
|
|
|
|
# Get SQLite session
|
|
sqlite_session = SQLiteSessionLocal()
|
|
|
|
# Get PostgreSQL session
|
|
postgres_session = PostgresSessionLocal()
|
|
|
|
try:
|
|
# Migrate Users
|
|
print("Migrating Users...")
|
|
users = sqlite_session.query(models.User).all()
|
|
for user in users:
|
|
new_user = models.User(
|
|
id=user.id,
|
|
username=user.username,
|
|
hashed_password=user.hashed_password
|
|
)
|
|
postgres_session.add(new_user)
|
|
postgres_session.commit()
|
|
print(f"Migrated {len(users)} users")
|
|
|
|
# Migrate Challenges
|
|
print("Migrating Challenges...")
|
|
challenges = sqlite_session.query(models.Challenge).all()
|
|
for challenge in challenges:
|
|
new_challenge = models.Challenge(
|
|
id=challenge.id,
|
|
name=challenge.name,
|
|
period_type=challenge.period_type,
|
|
daily_target=challenge.daily_target,
|
|
start_date=challenge.start_date,
|
|
end_date=challenge.end_date,
|
|
display_order=challenge.display_order,
|
|
user_id=challenge.user_id,
|
|
icon=challenge.icon,
|
|
image_url=challenge.image_url,
|
|
description=challenge.description,
|
|
unit_type=challenge.unit_type,
|
|
rest_days=challenge.rest_days,
|
|
frequency=challenge.frequency
|
|
)
|
|
postgres_session.add(new_challenge)
|
|
postgres_session.commit()
|
|
print(f"Migrated {len(challenges)} challenges")
|
|
|
|
# Migrate Tracking
|
|
print("Migrating Tracking...")
|
|
trackings = sqlite_session.query(models.Tracking).all()
|
|
for tracking in trackings:
|
|
new_tracking = models.Tracking(
|
|
id=tracking.id,
|
|
challenge_id=tracking.challenge_id,
|
|
date=tracking.date,
|
|
reps=tracking.reps,
|
|
completed=tracking.completed,
|
|
notes=tracking.notes
|
|
)
|
|
postgres_session.add(new_tracking)
|
|
postgres_session.commit()
|
|
print(f"Migrated {len(trackings)} trackings")
|
|
|
|
# Migrate DailyHealthMetrics
|
|
print("Migrating DailyHealthMetrics...")
|
|
metrics = sqlite_session.query(models.DailyHealthMetrics).all()
|
|
for metric in metrics:
|
|
new_metric = models.DailyHealthMetrics(
|
|
id=metric.id,
|
|
user_id=metric.user_id,
|
|
date=metric.date,
|
|
step_count=metric.step_count,
|
|
calories_burned=metric.calories_burned,
|
|
distance_meters=metric.distance_meters,
|
|
sleep_duration_minutes=metric.sleep_duration_minutes,
|
|
deep_sleep_minutes=metric.deep_sleep_minutes,
|
|
light_sleep_minutes=metric.light_sleep_minutes,
|
|
rem_sleep_minutes=metric.rem_sleep_minutes,
|
|
awake_duration_minutes=metric.awake_duration_minutes,
|
|
avg_heart_rate=metric.avg_heart_rate,
|
|
min_heart_rate=metric.min_heart_rate,
|
|
max_heart_rate=metric.max_heart_rate,
|
|
avg_spo2=metric.avg_spo2,
|
|
pai_score=metric.pai_score,
|
|
weight=metric.weight,
|
|
resting_heart_rate=metric.resting_heart_rate,
|
|
hrv=metric.hrv
|
|
)
|
|
postgres_session.add(new_metric)
|
|
postgres_session.commit()
|
|
print(f"Migrated {len(metrics)} daily health metrics")
|
|
|
|
print("\nMigration completed successfully!")
|
|
print(f"Total records migrated:")
|
|
print(f" - Users: {len(users)}")
|
|
print(f" - Challenges: {len(challenges)}")
|
|
print(f" - Trackings: {len(trackings)}")
|
|
print(f" - DailyHealthMetrics: {len(metrics)}")
|
|
|
|
except Exception as e:
|
|
print(f"\nError during migration: {e}")
|
|
postgres_session.rollback()
|
|
raise
|
|
finally:
|
|
sqlite_session.close()
|
|
postgres_session.close()
|
|
postgres_engine.dispose()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Check if SQLite database exists
|
|
if not os.path.exists("data/habitforge.db"):
|
|
print("Error: SQLite database not found at data/habitforge.db")
|
|
sys.exit(1)
|
|
|
|
# Confirm migration
|
|
print("This will migrate data from SQLite to PostgreSQL.")
|
|
print(f"PostgreSQL URL: {POSTGRES_URL}")
|
|
response = input("Do you want to continue? (yes/no): ")
|
|
|
|
if response.lower() != "yes":
|
|
print("Migration cancelled.")
|
|
sys.exit(0)
|
|
|
|
migrate_data()
|