- Remove card_1..card_26 FK columns from Roster ORM model - Add RosterSlot model with (roster, slot, card) and a unique index on (roster, slot) - Activate get_cards() helper on Roster using the new junction table - Register RosterSlot in create_tables for SQLite dev environments - Add migrations/migrate_roster_junction_table.py to backfill existing data Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
66 lines
1.8 KiB
Python
66 lines
1.8 KiB
Python
"""
|
|
Migration: Replace 26 FK columns on Roster with RosterSlot junction table.
|
|
|
|
Creates the `rosterslot` table and migrates existing lineup data from the
|
|
card_1..card_26 columns. Safe to re-run (skips rosters already migrated).
|
|
|
|
Usage:
|
|
python migrations/migrate_roster_junction_table.py
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
|
|
from app.db_engine import db, Roster, RosterSlot
|
|
|
|
SLOTS = 26
|
|
|
|
|
|
def migrate():
|
|
db.connect(reuse_if_open=True)
|
|
|
|
# Create the table if it doesn't exist yet
|
|
db.create_tables([RosterSlot], safe=True)
|
|
|
|
# Read raw rows from the old schema via plain SQL so we don't depend on
|
|
# the ORM model knowing about the legacy card_N columns.
|
|
cursor = db.execute_sql("SELECT * FROM roster")
|
|
columns = [desc[0] for desc in cursor.description]
|
|
|
|
migrated = 0
|
|
skipped = 0
|
|
|
|
with db.atomic():
|
|
for row in cursor.fetchall():
|
|
row_dict = dict(zip(columns, row))
|
|
roster_id = row_dict["id"]
|
|
|
|
already_migrated = (
|
|
RosterSlot.select().where(RosterSlot.roster == roster_id).exists()
|
|
)
|
|
if already_migrated:
|
|
skipped += 1
|
|
continue
|
|
|
|
slots_to_insert = []
|
|
for slot_num in range(1, SLOTS + 1):
|
|
col = f"card_{slot_num}_id"
|
|
card_id = row_dict.get(col)
|
|
if card_id is not None:
|
|
slots_to_insert.append(
|
|
{"roster": roster_id, "slot": slot_num, "card": card_id}
|
|
)
|
|
|
|
if slots_to_insert:
|
|
RosterSlot.insert_many(slots_to_insert).execute()
|
|
migrated += 1
|
|
|
|
print(f"Migration complete: {migrated} rosters migrated, {skipped} already done.")
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
migrate()
|