From 3404df0f284e0598126799159944cd698b638c74 Mon Sep 17 00:00:00 2001 From: Marker689 Date: Sun, 10 May 2026 04:45:31 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B0=D0=B2=D1=82=D0=BE-=D0=BC=D0=B8?= =?UTF-8?q?=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20SQLite=20=E2=80=94=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B4=D0=BE=D1=81=D1=82=D0=B0=D1=8E=D1=89=D0=B8?= =?UTF-8?q?=D1=85=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD=D0=BE=D0=BA=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit При добавлении нового поля в модель (report в Finding) старое create_all не добавляет колонку в существующую БД → 500 ошибка. Теперь _migrate() проверяет PRAGMA table_info и добавляет недостающие колонки через ALTER TABLE --- guarddog_nexus/database.py | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/guarddog_nexus/database.py b/guarddog_nexus/database.py index 95fa759..ebab461 100644 --- a/guarddog_nexus/database.py +++ b/guarddog_nexus/database.py @@ -1,9 +1,12 @@ """Async SQLite database setup via SQLAlchemy.""" + +from sqlalchemy import inspect, text from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase from guarddog_nexus.config import config +from guarddog_nexus.logging_setup import log DATABASE_URL = f"sqlite+aiosqlite:///{config.database_path}" @@ -15,11 +18,56 @@ class Base(DeclarativeBase): pass +async def _migrate(): + """Add any missing columns from model definitions to existing SQLite tables.""" + import guarddog_nexus.models # noqa: F401 + + async with _engine.connect() as conn: + for table in Base.metadata.sorted_tables: + # Get existing columns in DB + col_names = [] + try: + existing = await conn.run_sync( + lambda c: [col["name"] for col in inspect(c).get_columns(table.name)] + ) + col_names = existing + except Exception: + continue + + # Add missing model columns + for col in table.columns: + if col.name not in col_names: + col_type = col.type.compile(_engine.dialect) + nullable = "" if col.nullable else " NOT NULL" + default = "" + if col.default and col.default.arg is not None: + default_val = col.default.arg + if isinstance(default_val, str): + default = f" DEFAULT '{default_val}'" + else: + default = f" DEFAULT {default_val}" + if col.server_default: + # Skip — func.now() etc. not trivially stringable + pass + + sql = ( + f"ALTER TABLE {table.name} ADD COLUMN " + f"{col.name} {col_type}{nullable}{default}" + ) + log.info("Migration: %s", sql) + try: + await conn.execute(text(sql)) + await conn.commit() + except Exception as e: + log.warning("Migration skipped (may already exist): %s", e) + + async def init_db(): import guarddog_nexus.models # noqa: F401 async with _engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) + await _migrate() async def get_session() -> AsyncSession: