"""marquee_seed 升级为「生成规则」:用户名可空 + 金额拆 min/max 区间 把种子从「死记录」升级: - masked_user 改 nullable(留空 → feed 随机合成脱敏用户名) - saved_amount_cents(单值)拆成 min_cents / max_cents(feed 在区间内随机取值;固定金额则相等) 现有 6 条种子:min_cents = max_cents = 原 saved_amount_cents,masked_user 原样保留。 Revision ID: marquee_seed02 Revises: marquee_seed01 Create Date: 2026-06-07 11:00:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = 'marquee_seed02' down_revision: Union[str, Sequence[str], None] = 'marquee_seed01' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # 1) 先加可空新列,使现有行合法 with op.batch_alter_table('marquee_seed', schema=None) as batch_op: batch_op.add_column(sa.Column('min_cents', sa.Integer(), nullable=True)) batch_op.add_column(sa.Column('max_cents', sa.Integer(), nullable=True)) # 2) 用旧单值回填区间(固定金额) op.execute('UPDATE marquee_seed SET min_cents = saved_amount_cents, max_cents = saved_amount_cents') # 3) 收紧:区间非空、用户名可空、删旧列 with op.batch_alter_table('marquee_seed', schema=None) as batch_op: batch_op.alter_column('min_cents', existing_type=sa.Integer(), nullable=False) batch_op.alter_column('max_cents', existing_type=sa.Integer(), nullable=False) batch_op.alter_column('masked_user', existing_type=sa.String(length=64), nullable=True) batch_op.drop_column('saved_amount_cents') def downgrade() -> None: # 反向:恢复单值列(取下限),用户名回非空 with op.batch_alter_table('marquee_seed', schema=None) as batch_op: batch_op.add_column(sa.Column('saved_amount_cents', sa.Integer(), nullable=True)) op.execute('UPDATE marquee_seed SET saved_amount_cents = min_cents') # 自动合成名的种子 masked_user 为 NULL,降级前补占位符以满足非空 op.execute("UPDATE marquee_seed SET masked_user = '用户********000' WHERE masked_user IS NULL") with op.batch_alter_table('marquee_seed', schema=None) as batch_op: batch_op.alter_column('saved_amount_cents', existing_type=sa.Integer(), nullable=False) batch_op.alter_column('masked_user', existing_type=sa.String(length=64), nullable=False) batch_op.drop_column('max_cents') batch_op.drop_column('min_cents')