"""补齐 0001 create_all 未覆盖的老库列(显式清单,禁止内省全库) 0001 对「已存在的表」不会 ALTER。下列列在 ORM / 0001 注释中视为新库默认字段, 但 staging/production 等自 squash 前就存在的库需要本迁移显式 add_column。 新增 ORM 字段时:禁止改已部署 revision id;在本文件追加列定义,或新建 0020_* 迁移。 Revision ID: 0019_align_legacy_schema Revises: 0018_users_language_preference """ from __future__ import annotations import sys from pathlib import Path from typing import Sequence, Union import sqlalchemy as sa # versions/ -> alembic/ _ALEMBIC_DIR = Path(__file__).resolve().parents[1] if str(_ALEMBIC_DIR) not in sys.path: sys.path.insert(0, str(_ALEMBIC_DIR)) from script_helpers import add_column_if_missing, drop_column_if_exists, table_exists revision: str = "0019_align_legacy_schema" down_revision: Union[str, None] = "0018_users_language_preference" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None # (table, column) — 仅列「0002–0018 未 add_column 且老库常缺」的字段 _LEGACY_COLUMNS: tuple[tuple[str, sa.Column], ...] = ( ( "segments", sa.Column("audio_duration_seconds", sa.Integer(), nullable=True), ), ( "conversations", sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True), ), ( "segments", sa.Column("tts_audio_urls", sa.JSON(), nullable=True), ), ( "conversation_messages", sa.Column("tts_audio_urls", sa.JSON(), nullable=True), ), ) def upgrade() -> None: for table_name, column in _LEGACY_COLUMNS: if not table_exists(table_name): continue add_column_if_missing(table_name, column) def downgrade() -> None: for table_name, column in reversed(_LEGACY_COLUMNS): if not table_exists(table_name): continue drop_column_if_exists(table_name, column.name)