fix(alembic): cps_v2_platforms 兼容 SQLite 且可重跑

batch_alter_table 包 ALTER(SQLite 无原生 ALTER COLUMN),server_default 按方言分叉(PG ::jsonb / SQLite 纯文本),add_column 加 _has_column 存在性守卫,让历史半应用的 SQLite 库自愈重跑。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
guke
2026-06-25 16:21:50 +08:00
parent b07997cd8d
commit b3c4898c5d
+52 -27
View File
@@ -23,39 +23,64 @@ branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None: def _has_column(insp: sa.Inspector, table: str, column: str) -> bool:
# 活动:淘宝淘口令 / 京东链接 return any(c["name"] == column for c in insp.get_columns(table))
op.add_column("cps_activity", sa.Column("payload", sa.Text(), nullable=True))
# 群:多平台(现有群都是美团,server_default 回填)+ sid 可空
op.add_column( def upgrade() -> None:
"cps_group", bind = op.get_bind()
sa.Column( insp = sa.inspect(bind)
"platforms", # SQLite 不认 ::jsonb cast(会报 "unrecognized token: :"),只有 PG 用显式 cast。
sa.JSON().with_variant(postgresql.JSONB(), "postgresql"), # 两边列类型都靠上面的 with_variant 区分,这里只管 server_default 文本。
nullable=False, platforms_default = (
server_default=sa.text("'[\"meituan\"]'::jsonb"), sa.text("'[\"meituan\"]'::jsonb")
), if bind.dialect.name == "postgresql"
else sa.text("'[\"meituan\"]'")
) )
op.alter_column("cps_group", "sid", existing_type=sa.String(64), nullable=True)
# 活动:淘宝淘口令 / 京东链接
# 加 add_column 存在性守卫:本迁移历史上在 SQLite 第一次跑时加完 payload 即在
# platforms 那步炸掉(::jsonb),DDL 非事务不回滚 → 半应用状态。守卫让其可自愈重跑。
if not _has_column(insp, "cps_activity", "payload"):
op.add_column("cps_activity", sa.Column("payload", sa.Text(), nullable=True))
# 群:多平台(现有群都是美团,server_default 回填)+ sid 可空。
# SQLite 不支持 ALTER COLUMN,必须用 batch(重建表)才能改 nullable;PG 走原生 ALTER。
with op.batch_alter_table("cps_group") as batch_op:
if not _has_column(insp, "cps_group", "platforms"):
batch_op.add_column(
sa.Column(
"platforms",
sa.JSON().with_variant(postgresql.JSONB(), "postgresql"),
nullable=False,
server_default=platforms_default,
)
)
batch_op.alter_column("sid", existing_type=sa.String(64), nullable=True)
# link:sid 可空 + target 加长 # link:sid 可空 + target 加长
op.alter_column("cps_link", "sid", existing_type=sa.String(64), nullable=True) with op.batch_alter_table("cps_link") as batch_op:
op.alter_column("cps_link", "target_url", existing_type=sa.String(1024), type_=sa.String(2048)) batch_op.alter_column("sid", existing_type=sa.String(64), nullable=True)
batch_op.alter_column("target_url", existing_type=sa.String(1024), type_=sa.String(2048))
# click:sid 可空 + 事件类型 # click:sid 可空 + 事件类型
op.alter_column("cps_click", "sid", existing_type=sa.String(64), nullable=True) with op.batch_alter_table("cps_click") as batch_op:
op.add_column( batch_op.alter_column("sid", existing_type=sa.String(64), nullable=True)
"cps_click", if not _has_column(insp, "cps_click", "event_type"):
sa.Column("event_type", sa.String(16), nullable=False, server_default="visit"), batch_op.add_column(
) sa.Column("event_type", sa.String(16), nullable=False, server_default="visit")
)
def downgrade() -> None: def downgrade() -> None:
op.drop_column("cps_click", "event_type") with op.batch_alter_table("cps_click") as batch_op:
op.alter_column("cps_click", "sid", existing_type=sa.String(64), nullable=False) batch_op.drop_column("event_type")
op.alter_column("cps_link", "target_url", existing_type=sa.String(2048), type_=sa.String(1024)) batch_op.alter_column("sid", existing_type=sa.String(64), nullable=False)
op.alter_column("cps_link", "sid", existing_type=sa.String(64), nullable=False) with op.batch_alter_table("cps_link") as batch_op:
op.drop_column("cps_group", "platforms") batch_op.alter_column("target_url", existing_type=sa.String(2048), type_=sa.String(1024))
op.alter_column("cps_group", "sid", existing_type=sa.String(64), nullable=False) batch_op.alter_column("sid", existing_type=sa.String(64), nullable=False)
op.drop_column("cps_activity", "payload") with op.batch_alter_table("cps_group") as batch_op:
batch_op.drop_column("platforms")
batch_op.alter_column("sid", existing_type=sa.String(64), nullable=False)
with op.batch_alter_table("cps_activity") as batch_op:
batch_op.drop_column("payload")