- Added the `run_simple_migrations` function call in the database initialization process to ensure any missing columns are added during setup. - Updated the .gitignore file to exclude the `models_old.py` file, improving project cleanliness.
67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
import logging
|
|
from typing import Set
|
|
|
|
from sqlalchemy import inspect, text
|
|
from sqlalchemy.engine import Connection
|
|
|
|
from .models import Base
|
|
|
|
|
|
def _add_missing_columns(connection: Connection) -> None:
|
|
inspector = inspect(connection)
|
|
metadata = Base.metadata
|
|
|
|
existing_tables: Set[str] = set(inspector.get_table_names())
|
|
|
|
for table in metadata.tables.values():
|
|
table_name = table.name
|
|
if table_name not in existing_tables:
|
|
# Tables are created elsewhere via create_all; skip here.
|
|
continue
|
|
|
|
existing_columns = {col_info["name"] for col_info in inspector.get_columns(table_name)}
|
|
|
|
for desired_column in table.columns:
|
|
if desired_column.name in existing_columns:
|
|
continue
|
|
|
|
# Build ADD COLUMN DDL
|
|
preparer = connection.dialect.identifier_preparer
|
|
table_quoted = preparer.format_table(table)
|
|
column_name_quoted = preparer.quote(desired_column.name)
|
|
column_type_sql = desired_column.type.compile(dialect=connection.dialect)
|
|
|
|
default_clause = ""
|
|
server_default = getattr(desired_column, "server_default", None)
|
|
if server_default is not None and getattr(server_default, "arg", None) is not None:
|
|
try:
|
|
compiled_default = str(
|
|
server_default.arg.compile(dialect=connection.dialect)
|
|
)
|
|
default_clause = f" DEFAULT {compiled_default}"
|
|
except Exception: # best-effort
|
|
pass
|
|
|
|
# For safety, add new columns as NULLable to avoid failures on existing rows
|
|
# If strict NOT NULL is needed, it can be enforced manually later.
|
|
ddl = f"ALTER TABLE {table_quoted} ADD COLUMN {column_name_quoted} {column_type_sql}{default_clause}"
|
|
|
|
logging.info(
|
|
f"Migrator: adding missing column {desired_column.name} to table {table_name}"
|
|
)
|
|
connection.execute(text(ddl))
|
|
|
|
|
|
def run_simple_migrations(connection: Connection) -> None:
|
|
"""
|
|
Run lightweight, idempotent migrations:
|
|
- Ensure missing columns are added to existing tables to match models in db/models.py
|
|
Note: Table creation is handled separately via Base.metadata.create_all.
|
|
"""
|
|
try:
|
|
_add_missing_columns(connection)
|
|
logging.info("Migrator: schema synchronized (columns added as needed).")
|
|
except Exception as e:
|
|
logging.error(f"Migrator: failed to run simple migrations: {e}", exc_info=True)
|
|
raise
|