Spaces:
Sleeping
Sleeping
| """Additive SQLite auto-migration: an old-schema DB gains new ORM columns | |
| at startup instead of 500ing (the 'no such column: projects.archived' bug).""" | |
| import sqlite3 | |
| from sqlalchemy import create_engine, inspect | |
| from app.db import Base, auto_migrate_sqlite | |
| from app.models import Project # noqa: F401 - registers tables on Base.metadata | |
| def test_old_schema_gains_missing_columns(tmp_path): | |
| db_path = tmp_path / "old.db" | |
| # Simulate a dev DB created before archived/language/etc. existed. | |
| conn = sqlite3.connect(db_path) | |
| conn.execute( | |
| "CREATE TABLE projects (id VARCHAR(32) PRIMARY KEY, name VARCHAR(200), " | |
| "description TEXT, created_at VARCHAR(32))" | |
| ) | |
| conn.execute( | |
| "INSERT INTO projects VALUES ('abc123', 'Old Project', '', '2026-07-01T00:00:00')" | |
| ) | |
| conn.commit() | |
| conn.close() | |
| engine = create_engine(f"sqlite:///{db_path}") | |
| Base.metadata.create_all(engine) # creates the other, brand-new tables | |
| added = auto_migrate_sqlite(engine, Base.metadata) | |
| assert "projects.archived" in added | |
| cols = {c["name"] for c in inspect(engine).get_columns("projects")} | |
| assert "archived" in cols | |
| # Existing row survives with the default applied, and queries work. | |
| conn = sqlite3.connect(db_path) | |
| row = conn.execute("SELECT name, archived FROM projects WHERE id='abc123'").fetchone() | |
| conn.close() | |
| assert row == ("Old Project", 0) | |
| # Second run is a no-op (idempotent). | |
| assert auto_migrate_sqlite(engine, Base.metadata) == [] | |