"""补建所有 ORM 模型中存在但数据库缺失的列 0001 用 create_all 建表,对已有表不会 ALTER 追加列。 本迁移自动内省 ORM 元数据与实际数据库 schema 的差异, 为每张已有表补齐缺失列(不含 FK 约束,仅补列定义)。 Revision ID: 0020_backfill_all_missing_columns Revises: 0019_backfill_missing_columns """ from __future__ import annotations from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "0020_backfill_missing_schema" down_revision: Union[str, None] = "0019_backfill_missing_columns" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def _import_all_models() -> None: from app.features.asset import models as _asset # noqa: F401 from app.features.auth import models as _auth # noqa: F401 from app.features.conversation import models as _conv # noqa: F401 from app.features.evaluation import models as _eval # noqa: F401 from app.features.memory import models as _memory # noqa: F401 from app.features.memoir import models as _memoir # noqa: F401 from app.features.payment import models as _payment # noqa: F401 from app.features.story import models as _story # noqa: F401 from app.features.user import models as _user # noqa: F401 def upgrade() -> None: from app.core.db import Base _import_all_models() bind = op.get_bind() inspector = sa.inspect(bind) existing_tables = set(inspector.get_table_names()) for table in Base.metadata.sorted_tables: if table.name not in existing_tables: continue db_cols = {c["name"] for c in inspector.get_columns(table.name)} for col in table.columns: if col.name in db_cols: continue kwargs: dict = {"nullable": True} if col.server_default is not None: kwargs["server_default"] = col.server_default.arg new_col = sa.Column(col.name, col.type, **kwargs) op.add_column(table.name, new_col) def downgrade() -> None: pass