diff --git a/alembic/versions/cps_v2_platforms.py b/alembic/versions/cps_v2_platforms.py index e80c1a6..8311a58 100644 --- a/alembic/versions/cps_v2_platforms.py +++ b/alembic/versions/cps_v2_platforms.py @@ -23,39 +23,53 @@ branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None +# ⚠️ SQLite 不支持 ALTER COLUMN(改可空/类型),必须用 op.batch_alter_table(重建表)模拟; +# env.py 的 render_as_batch 只管 autogenerate 渲染、不会让"手写的 op.alter_column"在运行时自动 batch。 +# batch_alter_table 在 Postgres 上等价于直接 ALTER(recreate=auto 不重建),两端通用。 def upgrade() -> None: - # 活动:淘宝淘口令 / 京东链接 + # 活动:淘宝淘口令 / 京东链接(纯 add column,SQLite 直接支持) op.add_column("cps_activity", sa.Column("payload", sa.Text(), nullable=True)) - # 群:多平台(现有群都是美团,server_default 回填)+ sid 可空 - op.add_column( - "cps_group", - sa.Column( - "platforms", - sa.JSON().with_variant(postgresql.JSONB(), "postgresql"), - nullable=False, - server_default=sa.text("'[\"meituan\"]'::jsonb"), - ), + # 群:多平台(现有群都是美团,server_default 回填)+ sid 可空。 + # server_default 分方言:Postgres 用 ::jsonb 显式转;SQLite 不认 ::jsonb(报 unrecognized token ":"), + # 用纯 JSON 字符串字面量即可(JSON 列在 SQLite 实际是 TEXT)。 + platforms_default = ( + "'[\"meituan\"]'::jsonb" + if op.get_bind().dialect.name == "postgresql" + else "'[\"meituan\"]'" ) - op.alter_column("cps_group", "sid", existing_type=sa.String(64), nullable=True) + with op.batch_alter_table("cps_group") as batch_op: + batch_op.add_column( + sa.Column( + "platforms", + sa.JSON().with_variant(postgresql.JSONB(), "postgresql"), + nullable=False, + server_default=sa.text(platforms_default), + ) + ) + batch_op.alter_column("sid", existing_type=sa.String(64), nullable=True) # link:sid 可空 + target 加长 - op.alter_column("cps_link", "sid", existing_type=sa.String(64), nullable=True) - op.alter_column("cps_link", "target_url", existing_type=sa.String(1024), type_=sa.String(2048)) + with op.batch_alter_table("cps_link") as batch_op: + 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 可空 + 事件类型 - op.alter_column("cps_click", "sid", existing_type=sa.String(64), nullable=True) - op.add_column( - "cps_click", - sa.Column("event_type", sa.String(16), nullable=False, server_default="visit"), - ) + with op.batch_alter_table("cps_click") as batch_op: + batch_op.alter_column("sid", existing_type=sa.String(64), nullable=True) + batch_op.add_column( + sa.Column("event_type", sa.String(16), nullable=False, server_default="visit") + ) def downgrade() -> None: - op.drop_column("cps_click", "event_type") - op.alter_column("cps_click", "sid", existing_type=sa.String(64), nullable=False) - op.alter_column("cps_link", "target_url", existing_type=sa.String(2048), type_=sa.String(1024)) - op.alter_column("cps_link", "sid", existing_type=sa.String(64), nullable=False) - op.drop_column("cps_group", "platforms") - op.alter_column("cps_group", "sid", existing_type=sa.String(64), nullable=False) + with op.batch_alter_table("cps_click") as batch_op: + batch_op.drop_column("event_type") + batch_op.alter_column("sid", existing_type=sa.String(64), nullable=False) + with op.batch_alter_table("cps_link") as batch_op: + batch_op.alter_column("target_url", existing_type=sa.String(2048), type_=sa.String(1024)) + batch_op.alter_column("sid", existing_type=sa.String(64), nullable=False) + with op.batch_alter_table("cps_group") as batch_op: + batch_op.alter_column("sid", existing_type=sa.String(64), nullable=False) + batch_op.drop_column("platforms") op.drop_column("cps_activity", "payload")