"""snapshot the round's parameters at open: rounds.bet_amount_sats/fee_address/max_round_pool_sats, round_config.max_round_pool_sats (B-95) Revision ID: a7d3e9f15b48 Revises: f2c64a8d1e93 Create Date: 2026-10-15 16:00:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision: str = 'a7d3e9f15b48' down_revision: Union[str, Sequence[str], None] = 'f2c64a8d1e93' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None _ACTIVE = "'open', 'closing', 'drawing', 'paying_out'" def upgrade() -> None: """Upgrade schema. B-95 (DAT-27, DAT-55, DAT-61, DAT-62): a round now carries its own `bet_amount_sats`, `fee_address` and `max_round_pool_sats`, copied from `round_config` when it opens. Rounds that already exist are filled with the *current* values of `round_config` — for one still in progress that is exactly what it was using until now, since it read them live. The server defaults stay (changing them away would rebuild the table on SQLite). Plain add_column / UPDATE calls — never batch_alter_table, which on SQLite rebuilds the table and silently drops the expression indexes (B-97, DAT-56). """ op.add_column("round_config", sa.Column("max_round_pool_sats", sa.BigInteger(), server_default="0", nullable=False)) op.add_column("rounds", sa.Column("bet_amount_sats", sa.BigInteger(), server_default="1000000000", nullable=False)) op.add_column("rounds", sa.Column("fee_address", sa.String(length=128), server_default="", nullable=False)) op.add_column("rounds", sa.Column("max_round_pool_sats", sa.BigInteger(), server_default="0", nullable=False)) op.execute( "UPDATE rounds SET " "bet_amount_sats = COALESCE((SELECT bet_amount_sats FROM round_config ORDER BY id LIMIT 1), bet_amount_sats), " "fee_address = COALESCE((SELECT fee_address FROM round_config ORDER BY id LIMIT 1), fee_address)" ) def downgrade() -> None: """Downgrade schema.""" for column in ("max_round_pool_sats", "fee_address", "bet_amount_sats"): op.drop_column("rounds", column) op.drop_column("round_config", "max_round_pool_sats") # drop_column on SQLite is a table rebuild: recreate the expression index (B-97). op.execute("DROP INDEX IF EXISTS ix_rounds_single_active") op.execute(f"CREATE UNIQUE INDEX ix_rounds_single_active ON rounds ((1)) WHERE status IN ({_ACTIVE})")