36 lines
1.7 KiB
Python
36 lines
1.7 KiB
Python
"""Мини-миграция: create_all не добавляет колонки в существующие таблицы — добавляем недостающие."""
|
|
import logging
|
|
|
|
from sqlalchemy import inspect, text, Boolean, Integer, Float
|
|
|
|
from . import models # noqa: F401 (регистрация таблиц)
|
|
from . import db as _db
|
|
from .db import Base
|
|
|
|
log = logging.getLogger("migrate")
|
|
|
|
|
|
def ensure_schema(engine=None):
|
|
engine = engine or _db.engine
|
|
Base.metadata.create_all(engine)
|
|
insp = inspect(engine)
|
|
with engine.begin() as conn:
|
|
for table in Base.metadata.sorted_tables:
|
|
have = {c["name"] for c in insp.get_columns(table.name)}
|
|
for col in table.columns:
|
|
if col.name in have:
|
|
continue
|
|
ddl = col.type.compile(engine.dialect)
|
|
default = ""
|
|
if not col.nullable or col.default is not None:
|
|
arg = getattr(col.default, "arg", None)
|
|
if isinstance(col.type, Boolean):
|
|
default = " DEFAULT " + ("true" if arg else "false") if engine.dialect.name == "postgresql" \
|
|
else f" DEFAULT {1 if arg else 0}"
|
|
elif isinstance(col.type, (Integer, Float)) and isinstance(arg, (int, float)):
|
|
default = f" DEFAULT {arg}"
|
|
elif isinstance(arg, str):
|
|
default = " DEFAULT '" + arg.replace("'", "''") + "'"
|
|
log.warning("Добавляю колонку %s.%s", table.name, col.name)
|
|
conn.execute(text(f'ALTER TABLE {table.name} ADD COLUMN {col.name} {ddl}{default}'))
|