From f5270be494d5befba23d2da1f8f5d02ba568feb0 Mon Sep 17 00:00:00 2001 From: NotSoToothless <67082114+FURRO404@users.noreply.github.com> Date: Thu, 14 May 2026 14:30:02 -0700 Subject: [PATCH] auto-migrate teams_data.clanrating and team_members.points on tssbot boot (#1235) Co-authored-by: Claude Opus 4.7 (1M context) --- BOT/storage.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/BOT/storage.py b/BOT/storage.py index 611dba0..1e84401 100644 --- a/BOT/storage.py +++ b/BOT/storage.py @@ -215,6 +215,26 @@ async def _apply(conn: aiosqlite.Connection, statements: list[str]) -> None: await conn.execute(sql) +async def _existing_columns(conn: aiosqlite.Connection, table: str) -> set[str]: + rows = await conn.execute_fetchall(f"PRAGMA table_info({table})") + return {row[1] for row in rows} + + +async def _migrate( + conn: aiosqlite.Connection, table: str, additions: dict[str, str] +) -> None: + """Add any missing columns. `additions` maps column name → full column DDL. + + SQLite's ``ALTER TABLE ADD COLUMN`` only accepts a literal DEFAULT, which + is fine for all our additions. Existing rows pick up the DEFAULT value. + """ + cols = await _existing_columns(conn, table) + for col, ddl in additions.items(): + if col not in cols: + await conn.execute(f"ALTER TABLE {table} ADD COLUMN {ddl}") + log.info("migrated %s: added column %s", table, col) + + async def _init_battles_db() -> None: async with aiosqlite.connect(TSS_BATTLES_DB_PATH) as conn: for sql in _PRAGMAS: @@ -234,6 +254,17 @@ async def _init_teams_db() -> None: await conn.execute(_TEAM_MEMBERS_SQL) await conn.execute(_TEAM_NAME_HISTORY_SQL) await conn.execute(_TEAMS_POINTS_SQL) + + # Forward-only migrations for DBs created before a column landed. + # Keep CREATE TABLE statements above in sync — these only matter when + # the table already existed. + await _migrate(conn, "teams_data", { + "clanrating": "clanrating INTEGER", + }) + await _migrate(conn, "team_members", { + "points": "points INTEGER NOT NULL DEFAULT 0", + }) + await _apply(conn, _TEAMS_DATA_INDEXES) await _apply(conn, _TEAM_MEMBERS_INDEXES) await _apply(conn, _TEAM_NAME_HISTORY_INDEXES)