""" Migration script to add slug columns and generate slugs for existing data """ import os import sys # Add parent directory (backend/) to path for imports sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from sqlmodel import create_engine, Session, select, text from slugify import generate_slug, generate_show_slug, generate_performance_slug DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://elmeg:elmeg@localhost/elmeg") engine = create_engine(DATABASE_URL) def add_slug_columns(): """Add slug columns to tables if they don't exist""" with engine.connect() as conn: # Add slug to song conn.execute(text("ALTER TABLE song ADD COLUMN IF NOT EXISTS slug VARCHAR UNIQUE")) conn.execute(text("CREATE INDEX IF NOT EXISTS ix_song_slug ON song(slug)")) # Add slug to venue conn.execute(text("ALTER TABLE venue ADD COLUMN IF NOT EXISTS slug VARCHAR UNIQUE")) conn.execute(text("CREATE INDEX IF NOT EXISTS ix_venue_slug ON venue(slug)")) # Add slug to show conn.execute(text("ALTER TABLE show ADD COLUMN IF NOT EXISTS slug VARCHAR UNIQUE")) conn.execute(text("CREATE INDEX IF NOT EXISTS ix_show_slug ON show(slug)")) # Add slug to tour conn.execute(text("ALTER TABLE tour ADD COLUMN IF NOT EXISTS slug VARCHAR UNIQUE")) conn.execute(text("CREATE INDEX IF NOT EXISTS ix_tour_slug ON tour(slug)")) # Add slug to performance conn.execute(text("ALTER TABLE performance ADD COLUMN IF NOT EXISTS slug VARCHAR UNIQUE")) conn.execute(text("CREATE INDEX IF NOT EXISTS ix_performance_slug ON performance(slug)")) conn.commit() print("✓ Slug columns added") def generate_song_slugs(): """Generate slugs for all songs""" with Session(engine) as session: # Get all songs without slugs result = session.exec(text("SELECT id, title FROM song WHERE slug IS NULL")) songs = result.fetchall() existing_slugs = set() # Get existing slugs existing = session.exec(text("SELECT slug FROM song WHERE slug IS NOT NULL")) for row in existing.fetchall(): existing_slugs.add(row[0]) count = 0 for song_id, title in songs: base_slug = generate_slug(title, 50) slug = base_slug counter = 2 while slug in existing_slugs: slug = f"{base_slug}-{counter}" counter += 1 existing_slugs.add(slug) session.execute( text("UPDATE song SET slug = :slug WHERE id = :id"), {"slug": slug, "id": song_id} ) count += 1 session.commit() print(f"✓ Generated slugs for {count} songs") def generate_venue_slugs(): """Generate slugs for all venues""" with Session(engine) as session: result = session.exec(text("SELECT id, name, city FROM venue WHERE slug IS NULL")) venues = result.fetchall() existing_slugs = set() existing = session.exec(text("SELECT slug FROM venue WHERE slug IS NOT NULL")) for row in existing.fetchall(): existing_slugs.add(row[0]) count = 0 for venue_id, name, city in venues: # Include city to help disambiguate base_slug = generate_slug(f"{name} {city}", 60) slug = base_slug counter = 2 while slug in existing_slugs: slug = f"{base_slug}-{counter}" counter += 1 existing_slugs.add(slug) session.execute( text("UPDATE venue SET slug = :slug WHERE id = :id"), {"slug": slug, "id": venue_id} ) count += 1 session.commit() print(f"✓ Generated slugs for {count} venues") def generate_show_slugs(): """Generate slugs for all shows""" with Session(engine) as session: result = session.exec(text(""" SELECT s.id, s.date, v.name FROM show s LEFT JOIN venue v ON s.venue_id = v.id WHERE s.slug IS NULL """)) shows = result.fetchall() existing_slugs = set() existing = session.exec(text("SELECT slug FROM show WHERE slug IS NOT NULL")) for row in existing.fetchall(): existing_slugs.add(row[0]) count = 0 for show_id, date, venue_name in shows: date_str = date.strftime("%Y-%m-%d") if date else "unknown" venue_slug = generate_slug(venue_name or "unknown", 25) base_slug = f"{date_str}-{venue_slug}" slug = base_slug counter = 2 while slug in existing_slugs: slug = f"{base_slug}-{counter}" counter += 1 existing_slugs.add(slug) session.execute( text("UPDATE show SET slug = :slug WHERE id = :id"), {"slug": slug, "id": show_id} ) count += 1 session.commit() print(f"✓ Generated slugs for {count} shows") def generate_tour_slugs(): """Generate slugs for all tours""" with Session(engine) as session: result = session.exec(text("SELECT id, name FROM tour WHERE slug IS NULL")) tours = result.fetchall() existing_slugs = set() existing = session.exec(text("SELECT slug FROM tour WHERE slug IS NOT NULL")) for row in existing.fetchall(): existing_slugs.add(row[0]) count = 0 for tour_id, name in tours: base_slug = generate_slug(name, 50) slug = base_slug counter = 2 while slug in existing_slugs: slug = f"{base_slug}-{counter}" counter += 1 existing_slugs.add(slug) session.execute( text("UPDATE tour SET slug = :slug WHERE id = :id"), {"slug": slug, "id": tour_id} ) count += 1 session.commit() print(f"✓ Generated slugs for {count} tours") def generate_performance_slugs(): """Generate slugs for all performances (songslug-date format)""" with Session(engine) as session: result = session.exec(text(""" SELECT p.id, s.slug as song_slug, sh.date FROM performance p JOIN song s ON p.song_id = s.id JOIN show sh ON p.show_id = sh.id WHERE p.slug IS NULL """)) performances = result.fetchall() existing_slugs = set() existing = session.exec(text("SELECT slug FROM performance WHERE slug IS NOT NULL")) for row in existing.fetchall(): existing_slugs.add(row[0]) count = 0 for perf_id, song_slug, date in performances: date_str = date.strftime("%Y-%m-%d") if date else "unknown" base_slug = f"{song_slug}-{date_str}" slug = base_slug counter = 2 # Handle multiple performances of same song in same show while slug in existing_slugs: slug = f"{base_slug}-{counter}" counter += 1 existing_slugs.add(slug) session.execute( text("UPDATE performance SET slug = :slug WHERE id = :id"), {"slug": slug, "id": perf_id} ) count += 1 session.commit() print(f"✓ Generated slugs for {count} performances") def run_migration(): print("=== Running Slug Migration ===") add_slug_columns() generate_song_slugs() generate_venue_slugs() generate_tour_slugs() generate_show_slugs() generate_performance_slugs() # Must run after song slugs print("=== Migration Complete ===") if __name__ == "__main__": run_migration()